TDD gurus more and more tell us that TDD is not about tests, it is about design. So I know some developers who create really great design without TDD. Should they practice TDD then?


5 Answers 5


TDD doesn't only help me come to the best final design, it helps me get there in fewer attempts.

I used to have two or three stabs at a problem before deciding which design I thought was best. Now, that exact same time is spent writing tests and focussing my mind on the correct design. And, as a bonus, it leaves me with a suite of repeatable tests. Win!

That said, there are inevitably going to be people for whom TDD offers nothing. As long as they still have automated, repeatable tests at the end of it, that's fine.

  • 4
    in fewer attempts, really? Aug 22, 2011 at 6:54
  • 3
    Yes, really. TDD forces me to think about a class in terms of the calling code, as well as its functionality, because you start by writing the code you expect to be able to write to consume the class. When I'm writing a class "blind" I tend to focus on what it does more than what the calling class expects, which is almost always a mistake.
    – pdr
    Aug 22, 2011 at 9:28
  • 4
    See, there's that word again, forced. I don't know why people aren't more often disturbed by the frequency of the word "forced" as it occurs in discussions about TDD. One shouldn't need to be forced into designing something correctly; they should learn how to design things correctly, and then continue to do so without being forced into it, especially when that act of forcing is so incredibly time-consuming. Aug 22, 2011 at 10:37
  • 3
    @Rei: People aren't more often disturbed because they know that the other person really means "pushed" or "guided" or ... and here's a revelation when you're talking about Test Driven Development ... perhaps "driven". And yes, some might find that they think that way naturally, without being driven, I said that in the post. But you've still got to test your software so you're not that much better off.
    – pdr
    Aug 22, 2011 at 10:51
  • 3
    When someone says "forces modular design", they are indeed forced. It's very hard (if not impossible) to make a non-composable design with TDD, and that's a good thing. The problem isn't this end result of being forceful; it's the amount of menial, rote effort it takes. Proper design is a teachable and learnable skill, and time ought to be spent on learning. Also, tests written for TDD don't look much like the tests written for catching bugs. If they do, something is wrong. Aug 22, 2011 at 12:37

What this particular TDD guru is really trying to say isn't that TDD is a design process (although a number of people have unfortunately interpreted it that way). The message here is that using a process such as TDD, if you do it right, will tend to improve your overall design.

The fundamental concept is one that's much older than TDD; designing for testability. If you rigorously adhere to the SOLID principles, especially the Single Responsibility Principle, you'll find code very easy to test. On the other hand, if you tend to be a bit sloppier in your design, you'll probably find the process of writing unit tests to force you to do this more often, to avoid the frustration of (a) figuring out what needs to be tested, and (b) spending more time setting up dependencies than writing the actual tests.

You don't have to follow TDD to get the benefits of this, but it does help to write the tests early - preferably very soon after you implement a class, if not before or during. If you wait too long, you run the risk of the "dirty hybrid" tests the author is talking about, which don't have a lot of value because they're brittle and tend to break during harmless refactoring - not to mention making larger-scale redesigns an excruciatingly difficult process.

You can't know if you're truly designing for testability if you don't write tests, and haphazard "feature tests" with only 15% code coverage don't count.

Of course you can create good designs without ever writing a single test - but are you sure they're great designs? How do you know, if you they aren't clearly specified by tests? Testing uncovers a lot of issues, and while a QA process may find visible bugs, they won't uncover poor design decisions.

  • 1
    The point of a good design isn't just being tested. But yes, TDD is a good tool to spot flawed designs.
    – deadalnix
    Aug 21, 2011 at 17:37

Simplistic answer coming from someone striving to learn TDD: You don't need it, but the major benefit it gives you is, quite simply, confidence: Confidence that your application works. Confidence that the use cases are satisfied. Confidence that your logic is sound for the "Foobar" module. Confidence that your code is structured properly to be maintainable and extensible six months down the road when the CEO wants to add in some new crazy feature he read about. Confidence that, when your application grows, the foundations have been laid for the architecture to not fall apart or require gobs of messy hacks to jury-rig new features.

I realize the above sounded a bit evangelical but that's how I see the benefit of TDD. Even if you can create good, solid, well-architected designs using TDD forces your hand into doing things right, and then proves that things are done right, and more importantly provides a baseline for keeping things right. From the very little I've dabbled in TDD, using it forced me to make the code clean and follow proper software engineering concepts, where otherwise I would do the "quickest thing possible" which often resulted in messy "hack" code.

  • +1 TDD is feedback. As most measures of feedback go, it's fairly objective and completely automated, so it can be shared by team members of all skill levels. Before TDD, good code was something you "felt", or was confirmed sometime after the users got the software. The shorter the loop, the more confident you feel. Unfortunately TDD is prone to overconfidence as "feeling" a good design, but it's far easier to self-correct. Aug 23, 2011 at 16:29

I can talk only from my experience. For me TDD brought several things I didn't have before in my development style habits toolbox. Although, it is worth to say again that TDD is not solution to everything. I always try to separate exploration and production ready implementation. TDD in exploration phase is absolutely not needed and even is slowing down. On the other side for production ready code it brings several benefits which on short and long run are very valuable for the mental health of developers and karma of the project.

  • TDD makes me think before I implement, which is usually very good practice which prevents lot of shoot and forget solutions
  • It makes me think in small portions of problem, forcing me to break apart solution to small pieces that fit together.
  • It makes me write very decoupled code because whenever I have to stub/mock/fake something which doesn't fit into the problem I naturally throw one "WTF, why should I do this if I don't have to be coupled with it". And it makes me realize connections between things better.
  • It gives me set of easily executable checks for my code, so I don't have to go through painful "var_dump", "p", "pp", "echo" style of debugging of code. It just reports what is wrong, when is wrong. And if I don't have a check for it yet, it is just matter of adding simple test to check it over and over again.
  • It makes me certain that my code works if all tests pass before we deploy. Then instead of eating my nails I go eating a cake and drinking coffe and enjoying my afternoons.
  • High level tests are very nice in the cases you have to refactor something. If my module has to provide some functionality to outside world and I have developed functional/integration/cucumber tests to prove it's working correctly I will be very brave to refactor the hell out of that code. Several times I was faced with the code that didn't have tests and need to refactor it. In that case there were two ways to go in practice. 1) drop the code 2) skip the changes and leave it as it is.

There is one thing that TDD doesn't fix. If you don't know how to build the thing you are building, then TDD will not produce solution for you. You need to have rough "design" or overview of the problem and solution. TDD will make you just implement it in more elegant and maintainable way with the code of higher quality.

At last, I prefer thinking in BDD terms which lean on TDD practices. BDD makes me to implement solution using vocabulary of the domain and to make software fit the problem better.


There may be many ways to achieve great design, and there are unquestionably many different interpretations of what constitutes "great" - or even "good". I suspect most TDDers would not agree with you about the definition - that if we were to look at the code you feel is great, we would consider it less than great. TDD drives us to some very specific qualities, and these qualities are rarely found in non-TDD code.

Testability, obviously, is one of those qualities, and the overarching one. Extremely small methods and classes are perhaps a sub-characteristic, and this leads to excellent naming. Maybe you know programmers who achieve these qualities without doing TDD, but I don't.

  • 1
    You'd almost certainly find these same qualities in code produced by a waterfall process, e.g. for the military, space, etc. I suppose it's true that they're not common in the half-assed versions of Agile and/or waterfall practiced in most organizations for everyday projects.
    – Aaronaught
    Aug 21, 2011 at 13:57
  • @Aaronaught Tell that to the Mars Climate Orbiter team. :-)
    – Eric King
    Aug 21, 2011 at 15:20
  • I had some experience with the waterfall process on non-weapons military projects in the 90's, and also a lot of water-cooler discussion with veterans of other military applications. The general consensus was that waterfall methodology and cost-plus billing produced buggy systems that were very difficult to maintain. Aug 21, 2011 at 16:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.