Actually I thought it was an atrocious article, full of sloppy thinking and riddled with condescension. These twelve supposed benefits of TDD range the gamut from ridiculously untrue (āunit tests prove that your code actually worksā) to personal preferences (āitās more fun to code with tests than withoutā), to unscientific generalizations from limited personal anecdotes or perhaps selected case studies (āitās faster than writing code without testsā), to solutions to problems few people encounter (āit virtually eliminates coderās blockā). He lost me LONG before the last sentence.
No, Iām with James Bach. There are No Best Practices; a āBest Practiceā is a rule devoid of context[1]. As Andy Hunt points out in his awesome presentation, āHerding Racehorses, Herding Sheepā[2], context-free rules are only the first stage towards holistic comprehension. Theyāre great for novices, but experienced practicioners violate these rules all time. In chess, for example, a beginner might learn ānever lose a piece without winning a piece of equal or greater valueā - and that piece of advice, if taken to heart, will improve their game a great deal. But itās not a silver bullet. In fact, their chess ability will reach an early plateau if they donāt start learning the situations in which they NEED to sacrifice material in exchange for position.
When I hear someone say, āwe should use TDD all the timeā, itās very clear to me that theyāre a software engineering novice. They havenāt quite understood in what circumstances TDD works best, which circumstances it has no effect either way, and yes, in which circumstances itās just a plumb waste of time.
Where does TDD shine? TDD works best in new āfrom scratchā development, in code which lends itself to well-defined, testable outputs (eg, text or API calls, not-eg UI or AI algorithms), in code which is algorithmically simple enough to run in sub-millisecond times, and in code which is largely self-contained (rather than dependent on a network, database, or large object model environment or outside framework).
Letās face it. These are very limiting criteria, and thereās a lot of real-world code which canāt be shoehorned to fit this model. Donāt think that because TDD worked so well for you in your college project or cool little app that you wrote, that itās the One True Way that All Development Must Be Done.
I have been written to write a developer test from time to time. Who hasnāt? Sometimes itās a unit test, sometimes itās an system integration test (testing the interfaction of several units). But I donāt write tests for everything. Like I said, some code I simply canāt test. Other code is so simple, Iād be wasting my time trying to test it. But beyond that, Iām in the practice of looking at the bugs that I myself, or my coworkers have written, and asking myself, āhow could this have been avoidedā? And the answer is almost never āa unit test would have caught thatā. I just donāt see where the ROI is in banging out all these tests that donāt catch anything.
And quite frankly, the few merits TDD has (āunit tests make better designsā) is a level of hand-holding I outgrew long ago. Iāve learned (mostly from painful experience maintaining other peopleās code) what code smells I should avoid. The question āhow should this function be used?ā comes far more naturally to me than āhow should this function be implemented?ā. I donāt need TDD to force me to think that way. I know to keep my objects small, to write referentially transparent code, to not write Rube Goldberg machines, to minimize my usage of if statements, to tell rather than ask, to avoid casting and pointer arithmetic, to avoid code which transfers ownership of objects, to use std::string and std::vector rather than fixed-sized C-style buffers, to avoid premature optimization and premature abstraction, to prefer composition and aggregation over inheritence, to be careful to distinguish between a count of bytes or a count of characters, and the zillion other things which practicioners of TDD eventually stumble upon.
For me, TDD zealots are just one of a long line of religious loonies knocking on my door, trying to prove that my way of doing things is irrepairably broken and the only path to salvation is Jesus, Mohammed, Krishna, Dianetics, or Unit Testing. And maybe thereās a good idea or two to be gleaned from all the mountains of bullshit. But you know what? Keep your crazy religion, 'cause I donāt need it.
[1] - http://www.rtpspin.org/Information/030327prs.ppt
[2] - http://www.satisfice.com/blog/archives/27