When George Dinwiddie wrote recently about why he practices TDD, it made me think anew about why I do it. His explanation was similar to, yet different from, mine. The practical benefits he lists are old friends, and I probably feel a similar “freedom” to his, but something fundamental to my experience of Test-Driven Development is out of frame, not pictured. What, though? I couldn't pin it down. It wormed around in my brain, trying to find the exit.
Then Kent Beck offered another way of valuing TDD, and immediately I was able to triangulate mine. I agree strongly with Kent, too: if I had to remember more than one or two things at any given time, I'd be a terrible programmer. But that's also not the strongest reason I write tests first.
I drive my development with tests, above all else, because it makes me do better thinking.
Like anyone involved in the development of software, my brain is full of assumptions and expectations based on working understandings. In my role as a developer, my expectations are derived from the customer's wants, and my assumptions are derived from the code's wants. These derivations are lossy. My understandings are imperfect. For as long as they're worming around in my brain, I don't know what's imperfect about them. I might even try to think I know exactly what to build and how to build it. Yikes.
Not an insight: when I write tests first, my tests are the first code to explicitly exercise the programming interface I'm designing. The tests help me negotiate what the interface needs by trying to use it, early and often.
Maybe an insight: when I write tests first, my brain is the first brain to explicitly exercise the expectation-to-assumption interface I'm designing. The act of writing tests first helps me negotiate what the interface needs by trying to use it, early and often.
I practice TDD because by forcing me to define a clear interface between my assumptions and my expectations, it flushes out inaccuracies in both.
I practice TDD because if my hypotheses haven't yet exited my brain, they can't possibly be meaningful hypotheses. Preparing to show them to other people forces me to formulate them precisely. Showing them to other people tells me how they might be wrong.
I practice TDD because it's the best way I know to deliver increments of shared understanding. As Agile as Agile gets.
And yet there’s one more reason that I think often gets overlooked. Well written tests, especially those made during TDD and not after the fact, are the best documentation for a future developer who has to maintain the code.
And considering how much of development is maintaining existing code – that might be the best reason of all.