Unit Testing, Agile Development, Leadership & .NET - By Roy Osherove
I'm in agreement with you on what TDD means (at least that's what it means to me). I start systems with a bit of a design. Whether it's something in my head (if I'm the driver in a pair in which I'll communicate the design through tests to my pair) or something on a whiteboard, cocktail napkin or notes jotted down in a text file. As for TDD being bad, I suppose that's true if you're purely driving a design out of tests and you couldn't architect yourself out of a paper bag. For the rest of us, I think it's a fabulous tool for communication, collaboration, and evolution of a design.
Related (possibly identical) to #2 is Test-conscious design and architecture => Every design and architecture should have testability as one of the fundamental requirements. This applies to Alpha-architects and as-you-go-Architects equally. In its full form, it should realy be *-conscious-design,
where * =
A related term (possible identical) to #1 is Test-driven-Programming. This is not 'design' although it might have a flow-back effect as syntax etc crystalises while coding. This is where I personally feel that TDD actually works. For this, the idea is
1. you have a solid architecture/design in mind
2. you have a reasonable idea of the type of code you are about to produce (rough form, syntax, hierarchies, core fragments), but its not a formal UML or anything crazy.
3. you have an overriding desire to not produce any lines of code that are not unit-tested, either due to philosophy, or awareness that your planned code is risky/complex/likely to have issues.
If all of 1,2,3 are true, then TDP is great. you write tests, you write code, you get green lights, you get near-100% coverage and its all happy and well-behaved. Refactoring during TDP s truly refactoring rather than 'wow I had no idea I was going about this backwards, I better rewrite everything', which is clearly not normal refactoring.
I personally do not like the concept of TDD meaning test-driven-DESIGN where, for some reason, the syntactical form of a unit test is supposed to pre-date thinking about the problem.
I think one of the issues with Agile is that a lot of people do not have experience of using waterfall via a methodology, like SSADM, and thus do not understand what agile was reacting against. Instead they compare agile's statements to some ersatz, light weight, in-house agile methodology (which is, in a sense where agile grew from).
I think this problem is as prevalent in the agile community as outside it.
So when XP talks about not doing 'big-design up front' it is reacting to the multi-month design phases that characterized waterfall where in a 9 month project, the first 3 months would be spent doing design.
I do not believe that Agile intends that you do not have an idea of where you are heading with your design. Crystal expects there to be a design produced from its Exploratory 360 phase. I think that XP expects there to be an idea of design, because I think that the reason for whole team involvement in the Planning Game is to have a design conversation amidst the team while they begin implementing.
But with Agile these activities take hours or perhaps days, not months. We learn about our destination, and some key way markers on the journey, but we don't necessarily know the whole route.
The problem is that we have lost the context in which Agile was formed, and many exponents are mouthing the mantras, without understanding the reason for them. That lack of understanding is, I think, damaging to Agile, and people need to step back and ask why more often.
In turn, I think you'd have to define design. To me, design is thought and collaboration - not a piece of paper. As you hint, you can start coding with a design solely in your head. But the point is the design is there, even if not physically manifested.
But people who start a development without any thought or collaboration (design) deserve all the pain they get. TDD does not a *substitute* for design, it is a tool that can be used to *aid* design. That brings us full circle back to Jim's statement about it deteriorating design. I would also love to read the cited papers.
A TDD approach to evolving design from scratch is a demanding exercise in OO design skills. It is a hard thing to do without the proper requisite knowledge in recognizing code smells and how to refactor to better solutions.
However, it is also one of the best ways I have encountered to sharpen those skills. Studying design patterns and refactorings builds up the potential for design improvement and TDD instills it into practice. Doing one without the other is ineffective.
For developers without a high level of skill in these areas, I would question how effective prescribed designs are really going to be anyway. Perhaps TDD will deteriorate your design in these cases, but thats likely a symptom of poor design in the first place.
Excellent post. I'm a bit horrified that someone speaking as an authority would lay out a blanket statement like "don't do TDD".
I guess I hadn't really thought of what TDD means to me, but I'd say #3 or #4 is probably accurate. And I completely, 100% disagree with Jim's view. There is zero doubt in my mind that TDD has made me a better, more productive developer and has improved the design of my projects.
I agree with you that TDD means that you write tests first, and evolve your design as you go. I find that this works well. I may have to change my design as the application grows, but that's expected, and refactoring the code to fit the new design is never a big deal. That said, sometimes I design the whole thing on paper before writing any code --- I like to have some idea where I'm going, even if the destination changes on the way, as I spot improvements during development.
In my experience, TDD certainly doesn't kill my designs --- TDD makes my designs better.
PS. Ron will be upset that you added an extra "e" in the middle of his surname.
According to what many are talking about, many say that BDD or Behavior Driven Development is more reliable than TDD and gives better production and code, you´re basically giving people what they want. If you have a good time again you can blog about that too, would be fun to see the results and comparison of the two
I think one thing missing from the discussion is the granularity or degree of TDD.
In SQL, we all know that 5th NF is better than 3rd NF. But 5th is rarely practical.
I think you have good test in place "just "before or "just" after a design and get the benifiets.
Also TDD'ing database and GUI can be impracticle. Stick to TDD'ing the unique code you wrote.