TDD Is Dead;
Long Live TDD
The Simple Design And Testing Conference last weekend was awesome; all the discussions got my head swirling with a million new ideas, and it’s hard to just pick one and blog about it. Nevertheless.
Naresh Jain Is A Scary Man
After all the open spaces had concluded, and just a few of us SDTconf attendees were standing around talking, I fell into a conversation with a few guys about TDD (Naresh Jain, Corey Haines, Gary Bernhardt, Matthew Otto, Daniel Brown and Jim Hurne to drop a few names). The topic soon (immediately?) found its way to the subject of TDD. And that’s when Naresh —who calls himself a “Recovering Agilist”— lobbed in his heretical bombshell: “I’m just not convinced that TDD is the only way to design good software.”
Naresh had some interesting points. Maybe he will blog about them. But his arguments have gotten me thinking: what, exactly, are the benefits of TDD that I have seen, experienced, and appreciate? I’m going to list them here.
Why Naresh Is Wrong
And TDD Is The Best Thing Ever
TDD As Kind Teacher
I really do think that test-first is an awesome approach to teaching programming. Dan Wiebe, who teaches Java programming to prison inmates, says that he tells his students they are not allowed to use System.out: they learn to play with code using tests. Thus tests become the “natural habitat” for code. I have to say, I really like that. In fact, that’s exactly the approach I began to take when teaching Java to my son over this past summer. (I need to acknowledge that Edgcase’s Ruby Koans initially suggested to me the notion of TDD as a teaching tool. If you haven’t already, check them out.)
TDD As Dopamine Drip
Few things are as sweet to me as the green bar. The TDD workflow, for me, has the same emotional signature as a very rewarding hobby. You have all these short, exciting adventures into red-bar-land. And then, at the end of each episode, you return to the ranch, and all the other cowboys nod with respect, and all is right with the world. Who says you can’t code when you’re high?
TDD As Brain Girdle
I will be the first to admit that my use of TDD doesn’t indicate that I’m smart. What it proves is that I’m humble. I like my brain, and I don’t want to disparage it, because it really can do some amazing things. But keeping track of a bajillion different actors in a complex system isn’t one of them. And I think that’s ok. One of the coolest things about humans is that we use tools to accomplish things which we could never do through brute strength. I celebrate the pulley, the lever, the inclined plane and the post-it.
TDD, for me, is a bit like version control. Once I have concluded a coding session, and everything works as it should, I do not feel quite at rest until I have committed my work into my version control repository. Once it’s there, it’s all locked up in a safe place: I know I can get to it easily, I know my fellow programmers can get to it easily also, and I am now ready to turn my attention away from that code and to other things.
TDD does something similar for my mental organization. Once I have excercized all the key parts of my code with tests, I feel better about setting it aside so that I can attend to other things. One reason for this, I believe, is that tests make it easier for me to re-orient myself to my old code: what does this class do? Ah, yes, I see that these tests are making it do what it’s supposed to do, I can “see it in action” as it were.
Is this dangerous? Possibly. Certainly I cannot take a suite of tests as a kind of insurance that my code is awesome or even adequate. But the truth is that I do use it as one standard for considering a piece of code complete.
TDD as Scrooge
Speaking of complete, I also find that TDD helps keep me from developing my code to a state of over-completeness. When I code without tests, I might end up rowing upstream in a gold-plated dinghy, although I do always try to keep YAGNI (You Ain’t Gonna Need It) in mind. What’s more often the case is that I start to overlay my dinghy with gold leaf and stop myself. Repeatedly. If I had a nickel for every bit of gold leaf I’ve wasted that way…then I could have had a nickel plated dinghy, which is nearly as impractical yet less blingalicious.
The point is that in nearly all cases, the dinghy you’re building just needs to be a small boat that floats. My tests pair with me, asking me, “is it a boat?” and “does it float?” If so, then green bar. Move on. Next abstraction.
TDD As SmellOVision
Remember smellovision? I sure do. When I was kid, my friends and I used to speculate that one day there would be smellovision: stories that you could smell as well as watch. Instead we got LCD flat panels, which is a real disappointment. But I find that TDD is pretty close to my original concept. You have this story card. You start to implement it, using TDD. Pretty soon you find that you’re having a really hard time writing one particular test. 9 out of 10 Pragmatic Press authors agree this is a strong indication that your code could use some rethinking.
One very interesting example of this came up at SDTconf in a discussion about mocking, and dependancy. I’m going to literally force you to go read Venkat Subramaniam’s blog post about it. Point is, when you find you’re doing a whole lot of mocking, it may be an indication that your classes can be rewritten to be much simpler.
In my experience, code smells like that emerge in the tests long before they become clear in the implementation code.
Why Naresh Could Be Right (But I Have No Acceptance Test For That)
As I look back over my catalog of TDD’s Shining Virtues, I feel compelled to admit that they do not directly answer Naresh’s original thesis. None of my points above speak directly to TDD enhancing a program’s design. In plenty of ways it would improve my code, and in some cases it might point to problems in my design. Nevertheless, while the design process is too creative for a square dance like TDD to contain, at this point TDD remains an integral part of my design process.
There are, certainly, non-TDD’ing programmers who could design and implement elipses around me and my TDD. Naresh is one of them. But my challenge to anyone who challenges TDD is this: teach me. If there is another way, and it can be taught, and I can learn it, then, heck. I’ll be the first to push TDD into the repository of programming history with the commit comment:
-m"It sure was fun while it lasted."
Note: the reader should be aware that I hope Naresh will forgive me for using him as the straw man for my arguments. His journey through the realm of Agile and test-driven development is longer, more distinguished and more interesting than mine by a long shot. He’s a brilliant guy and I’m hugely grateful for his work in coordinating the Simple Design and Testing Conferences. If you don’t believe me, then I’m literally going to force you to go read his blog.