As Alex mentioned in his last post, we’ve been practicing test-driven development quite diligently on most of our new projects for a while now. It’s something that I’d experimented with before, but I hadn’t made a strong commitment to it until about a year ago. And as a result, it’s only recently that I started to really experience some of the benefits.
There are several advantages to test-driven development, and I’ve largely found those to be true in our case. Typically, those include:
- Significantly decreased regressions
- Refactoring becomes easier (and large, sweeping refactoring becomes possible)
- Interfaces are better-designed
- And resulting implementation tends to be simpler
In addition to those, though, I’ve noticed three other advantages. I’m not sure if these are universal, or just that TDD is helping to fill in areas where I’m less strong, but I’d be interested to find out.
Faster ramp-up time
A lot has been said about the time it takes to get into the flow of programming after even a short interruption. It’s a difficult problem to solve, but the rhythm of test-driven development has made it a little easier to take. The fact that I have tests charting a clear path forward means I don’t spend so long wondering what I need to do next. And since the tests encourage me to develop in smaller increments, I can use the time between other commitments to complete a (tiny) nugget of progress; whether that’s adding a test for an additional edge case or refactoring something I wrote earlier, it keeps things moving forward.
More clarity in code reviews
When a coworker asks me to review some code, I now tend to look at the tests before the implementation. Doing so gives me a much better idea of what their code does before I see how it does it. When reviewing code, I generally go through the following stages:
- What’s the purpose of this change?
- How does it do it? (And what are all these parts for?)
- Ah-ha…that makes sense… Now, what could go wrong with it?
In code reviews, those first two items might compete for attention. I find myself inferring what something does from looking at how it does it, and then trying to judge how it does it based on what I now realize it does. It’s all a bit self-referential and probably not ideal. However, this seems to happen less if I’ve seen the test cases before the implementation. It makes it easier for me to ask questions about why the implementation was done this way versus some other way that I would have tried. (There is usually a very good reason, and I try to not take that personally.)
More daring programming
“Daring” and “programming” are not words you’ll normally see close together in a sentence. But sometimes you’ll have an idea for something potentially very cool — but a little bit trickier than you’d normally attempt — coupled with a strong hunch that the difficulty is really going to pay off. And that can be a good thing. I’m convinced that in order to grow as a programmer (or as most anything else, for that matter), you have to seek out tasks that lie just beyond your comfort zone. Those that are too hard are asking for failure, but when it’s too easy you aren’t likely to learn much.
I’ve tried to follow this for a long time, so what does test-driven development have to add? It simply makes it easier to tell when something works. If I’m unsure about an implementation, I can code the requirements into tests and then experiment with the implementation to find out which parts behave the way I’d hoped. And the ease of refactoring means I can build a simpler version first that lacks some characteristic I’m trying to get at with the more challenging one (say, increased performance). That way I can build my solution incrementally, learning as I go and comforted by the fact that I always have the simple one to fall back on if I need it.
These are some things that I’ve grown to enjoy about test-driven development. To date, I don’t think I’ve encountered any significant downsides to it, but I’ll certainly be keeping my eyes open for that. In the meantime, I’d be very interested to know how this compares to other folks’ experiences.