TDD or Test-Last? Exploring Metaphors
Attempting to Capture the Essence of the TDD in Familiar Terms
This post is part of a series. The series consists of:
Don’t want to miss new instalments as they are published? Hit subscribe, and you won’t miss a thing.
The Magic of Metaphor
Metaphors are everywhere. Our everyday language is full of them, mostly for good reason. They allow us to understand something novel by framing it in terms of concepts with which we are familiar.
I can think of no better way to explain how I perceive TDD compared to Test-Last Development than through metaphor. Since I intend to use the metaphor throughout the series, it’s also a convenient first stop on our journey (yes, this is also a metaphor).
A First Attempt: Bowling Bumpers
As a kid, I used to go bowling just about every week. Not because I practiced it as a sport but because it was a popular activity for birthday parties.
I still remember it vividly: a bunch of hyped-up kids throwing bowling balls in every imaginable way (except for the proper way, of course). Without help, we would probably knock over a bowling pin only once every few turns. I cannot imagine that to remain motivating for young me. I wanted to see pins fly!
Luckily, bowling alleys account for this by offering bowling bumpers: gates positioned in the gutter, making hitting the mark almost a certainty.
This embodies TDD to me. It guides you toward the “pins”: clean code that works.
End of post. Metaphor established, right?
Unfortunately, no. I came to realize this metaphor is fundamentally flawed.
A potential pitfall of metaphors is that they can evoke the wrong assumptions. Even though this metaphor is helpful, I realized it conveys the wrong message.
You see, bowling guards are removed when you’ve outgrown them, similar to training wheels. They also turn bowling into something hardly requiring any skill. You just need to throw the ball in the right general direction.
I do not believe TDD is a set of “training wheels” on your way to becoming a skilled software engineer. Something you simply discard once you get the hang of riding a bicycle. On the contrary, TDD remains useful regardless of skill level when applied in the proper context (more on this later in the series).
Neither do I think TDD magically solves all your problems, ensuring you always hit the mark. Instead, I like to think about TDD as Dave Farley elegantly puts it:
TDD is a talent amplifier. It makes bad developers better and good developers great.
Back to the drawing board then. Let’s explore a better metaphor.
A Second Attempt: Navigation System
Do you remember going on road trips for the holidays? If you’re old enough, like me, you might remember the days when you would plot your route upfront by hand. And when you were making the trip, you would constantly hope there wouldn’t be roadworks, traffic, and the like foiling your plan.
Fast forward to today, and this scenario is hardly fathomable. Nowadays, we have the luxury of navigation systems built into our cars and phones. You enter the destination, and off you go. Each step of the way, there is an arrow pointing you in the right direction, in addition to the spoken directions. If you take a wrong turn, the system calculates a new route (after annoyingly shouting at you for a while, that is). Is traffic particularly bad? The system can offer alternative routes. These inventions are incredibly convenient when we don’t know how to reach our destination.
This captures the essence of TDD for me. TDD, like a navigation system, provides feedback every step of the way to our destination: maintainable code which solves the problem at hand.
Take a misstep in your design, and TDD will make you notice. And just like the navigation system, you can opt to ignore it. You'll feel the pain the entire time, just like the spoken commands being hurled at you when you take a wrong turn.
Navigation systems also shine when we need to get to unfamiliar destinations. It just so happens that most software we write is precisely that: unfamiliar territory. Most software we write tends to require novel solutions. TDD offers guidance in uncertainty.
But what if you are navigating familiar grounds? I still use my navigation system every time I go to the office. Why? To account for traffic and to get an ETA. Similarly, TDD remains useful for me, even when dealing with "known" problems. I can still use the feedback but take larger steps since the risk is smaller.
Time to Hit the Road Again
Hopefully, that provided a glimpse of what TDD means to me. It certainly is the best metaphor I could come up with so far. Don’t worry if it doesn’t make that much sense yet. Throughout the series, we’ll revisit the metaphor as we dive into more specific aspects of the practice.
Now that we've found a good enough metaphor, it’s time to hit the road again. (You didn't think I'd let this opportunity to sneak in another metaphor get away from me, did you?) But before we do, we must set the destination in the navigation system. After that, we're all set for the journey ahead.