Steve Eichert takes issue with Jon Lam’s “dogmatic” label for TDD this morning; something he heard in the latest .NET Rocks episode. Specifically, he writes:

While I agree that the key is unit tests, I don’t agree that a test driven approach is extreme or dogmatic. In my opinion its the most pragmatic approach to writing code that is well designed and well tested. The fact is, writing unit tests after the fact sucks! Especially if “after the fact” is days or weeks after the real code is written.

I couldn’t agree more. For the past year or so our shop has been doing TDD, but it’s been hit or miss. Some developers do a better job of writing tests first and letting the process guide their design, while others tend to write code first and retrofit tests later. The latter method doesn’t produce nearly as good of results, nor does it make the developers feel like they are getting much out of unit testing.

It’s a difficult to get everyone on the same page with a technique that is so new to all of us. This week I’ve been pairing with one of my coworkers and we’ve been working diligently to write test first, refactor often, and let the tests guide our design. And like always, when we stick to the technique diligently we see better results; our design evolves to fit the needs of the feature or use case we’re implementing, we see better code, fewer bugs and we’re able to feel much better about the overall quality of the code we’ve written, knowing that it not only works, but will be easy to maintain in the future. We get a lot of confidence out of this.

That said, I think there’s a very important lesson in here for all of us TDD practitioners and “believers” to realize, and that is this: There’s a reason TDD gets slapped with the “dogmatic” label, and we need to be mindful about that reason when “spreading the word”.

TDD is like many other religious ideology. When people discover it and use it and find it incredibly valuable to them, they tend to preach it like gospel. If you read the blogosphere with any breadth at all you’re certain to run across the word “zealot” a lot in conjunction with TDD. You’re also likely to run across people who have tried TDD and failed. And there are a lot of legitimate reasons for this. There’s a lot of ways to not get the best out of TDD: trying to retrofit tests on legacy systems, trying to test too-complex relationships/not starting out simple first, not refactoring existing designs to better designs that are easier to test and change, trying to test systems that make the tests slow, writing tests after code, etc. I mean, you could write a pretty decent book on the number of ways to fail at TDD.

Because people do fail at TDD, they tend to do what all people do when they fail: they blame the concept and the people who advocate it. Hey, we’re all smart people, right? If we can’t make “it” work then “it” must be wrong. (And I’m not excluding myself from this behavior – guilty like everyone else).

The TDD community doesn’t always help in this regard. Our response (and I put myself in this camp, because I consider myself an advocate of TDD) is to blame the user; they didn’t do TDD right. If only they had done it correctly they would have succeeded, right?

This blame-game has the same effect as in any other area of life: it causes animosity. It causes people to label (advocates for TDD quickly become “zealots”), to fight and bicker, and to dismiss each other outright. It doesn’t help the TDD advocate trying to get the message across, and it doesn’t help the poor sod who decided to go out on a limb and give TDD a try.

I’ve explained TDD to a few people and I can say this: it doesn’t help nearly as much as showing them.

When we hired the people I currently work with, they did not know TDD. We explained it to them, and the result was predictably mixed: they said the right things (because the theory of TDD sounds good), but inside you could tell they had some trepidation. Telling people about TDD and actually doing it with them (following all the guidelines that the experts have cultivated, thus allowing us to achieve some degree of success) were two completely different experiences. It wasn’t until they actually saw the process in action, until they saw the quality of the code, and the ease of refactoring, especially larger refactorings to the system successfully, with little or no bugs, that they were sold on the technique.

But you can’t sit down and pair with everyone who wants to try TDD. You can’t show the world. And even if you could, you’d still find people for whom TDD is not ideally suited. Let’s face it: there’s no one-size-fits-all religion in the world, or we wouldn’t be killing each other all the time. And there’s no one-size-fits-all development methodology. I personally think TDD is the best thing available for producing quality code, but I am in no way naive enough to think that everyone could be made to believe that. We’re human beings; getting us to universally believe anything is genetically impossible.

I think what we, as TDD advocates, must do is always be mindful that we can very quickly sound like Born Again Christians. We can sound preachy; we can sound like zealots. And when that happens, it doesn’t matter how good the message is because we tune out. We don’t like being preached to.

The “dogmatic” label may not seem true to Steve or myself, but it’s easy to see how someone could arrive at that conclusion.