I have a friend who likes to talk about testing, specifically TDD, using a car analogy (What would a good software development story be without a bad car analogy?). He likens TDD to breaks and seatbelts. The car functions without breaks and seatbelts and you can go really really fast. With breaks and seatbelts though you can go really really fast safely. What does this mean? It means that just because you can go 90mph it doesn’t mean you’re going to want to go 90mph around a 90 degree curve, you’re going to want to slow down enough to make it around the curve. The same thing applies in software development and TDD. TDD allows you to make changes relatively quickly, while at the same time knowing that you’re not going to break anything in the code and splatter yourself against that 90 degree curve.
Now I like this analogy as far as it goes, but I don’t feel like it tells the whole story. For one thing, TDD is only one aspect of Software Craftsmanship. For another I don’t feel like the concept of “fast” has a singular dimension. Going fast isn’t always going 90mph. In fact, going 90mph is usually incredibly dangerous in most situations. Fast also doesn’t always equate to your ability to go from 0 to 90mph in four seconds if you can’t sustain that pace. Is going “fast” even valuable?
Instead of talking about going “fast” in only one dimension, let’s talk about it more holistically, obviously with another bad (s/car/vehicle) analogy.
A Bad Vehicle Analogy
Let’s say we have two teams that are going to take a trip around the world. Each team has a vehicle and an unlimited supply of parts to use on the trip. Sounds like your standard “Around the World in 80 Days” story so far, right? At this point we’re going to throw the teams a couple of curve balls. First, they don’t know their exact route ahead of time. They know in general that it is a worldly trip, so they’re bound to hit a couple of rough patches along the way, but their actual route might change from day to day based on certain conditions. They can use the parts they have to add functionality to their vehicle to allow them to cross various obstacles. There is an ocean in the way of their trip? They can add wings and allow the vehicle to fly a short distance, or maybe they’ll choose to make it sea-worthy instead. Second, they have to disassemble and reassemble their vehicle every day before they can continue their journey, and it still has to function. Third, they’re not allowed to remove functionality because (and this is the important part) the sponsors who pay for the trip are going to use their vehicle to make the same trip after they are done. This means that the vehicle has to be able to cross all the same obstacles again. This also means the team doesn’t get to cross an obstacle, rip out the parts afterwards, and simply continue on.
On to the teams.
At the start of the trip one team tears across the starting line and they’re making good time initially. They add features to their vehicle as they come across obstacles. When it comes time to go off-road they add better shocks and tires. When it rains they add heavy-duty windshield wipers. When they hit a muddy patch they add four-wheel drive. They don’t bother creating a checklist or instructions for adding the features because what they have done so far is simple; they figure they’ll remember what they did and be able to put the vehicle back together easily from memory each day.
As for the team, each person takes turns navigating when they come across landscape that they are familiar with. One person drives on the roads, another person captains when it comes time to cross a body of water, another person pilots when it is time to fly. All is well in the beginning, and they are moving “fast”.
The other team starts at the same time, and makes equally good time until they hit their first obstacle. Instead of simply adding the required feature to their vehicle and moving on they check to make sure the new feature will actually get them past the obstacle, and they record what they did on a checklist and set of instructions. They repeat this at each obstacle. They also spend some time making sure that it is easy to add and remove parts to make changing the vehicle easier.
Another difference this team has from the first team is that no one person is responsible for navigating. When the landscape changes there are at least two people who are responsible for navigating, and this responsibility rotates periodically. As the other team isn’t following these patterns this team falls behind in the beginning.
As the trip continues each team follows their own practices. After a couple of weeks though something has changed, and the first team is not moving nearly as fast as they did in the beginning. What happened? Why isn’t the first team moving “fast” anymore?
It turns out that when it comes time to reassemble their vehicle each day the team occasionally forgets how to put it together. Worse, sometimes they think they assembled it correctly, but when it comes time to use a feature they created to cross an obstacle the vehicle malfunctions and breaks down. They can’t cross that ocean because the gears to change the vehicle from a car to a boat didn’t work right. They now need to frequently spend time fixing things.
The members of the first team also have issues. There are long stretches of landscape that only one person knows how to navigate, and after a while they get tired, or sick. When another member steps up to take over for a while they make mistakes and get stuck in the sand, or they burn out a motor when they try to go really fast to “keep the pace”, something the other team members know not to do in those stretches.
As for the second team, when it comes time to reassemble their vehicle they follow the checklist and instructions, which they’ve been updating along the way. When they have to add a new feature it takes a little longer, but they know that when the trip is over the vehicle will be usable. The vehicle breaks down much less frequently, and they make steady progress.
As for the members of the team, because they’ve been pairing and rotating the responsibility for navigating, any of the team members can cross a given stretch of landscape. They learn from each other’s mistakes, and they can navigate with confidence even if someone gets tired or sick. They also don’t try to push their pace so hard that they become too tired, because they know that will only cause more mistakes to be made, and will slow them down in the long run.
Both teams eventually cross the finish line of the trip. I’d like to tell you that second team, which took its time doing things right, finished first, but that isn’t what happens. The first team realized they were falling behind and started working around the clock, frantically trying to fix what’s broken and driving constantly. The team is exhausted and broken by the end of the trip, but they come in first. They hand their vehicle over to their sponsor, who is happy to get their hands on it.
The second team comes in shortly after the first. They’re tired, but in good spirits and confident in what they’ve built. They hand over their vehicle to the sponsor as well, who is less than happy that it took so long to complete the trip.
The sponsors now start using the vehicles to make the trip themselves, and quickly discover a difference between the vehicles. The first one breaks down frequently, costing time and money to fix. The second vehicle works as expected, and only breaks down once or twice.
Which team “won”? Was going “faster” worth it? Did the first team win because they crossed the finish line first? Sure, the sponsors were happy that the first team got done faster, because it cost them less money for the initial trip, but was that an actual cost-saving when compared to the repair costs afterwards?
When we talk about software development we should ask ourselves what “fast” means, and what the value of “fast” is. After all, “fast” is relative term which means different things to different people. Was it valuable to be done quickly? Many would argue that this is true, and maybe they would be right in the short term. Does going fast mean not taking time to safely make changes and upgrades to your software? What does going “fast” mean if what you’re building isn’t fully-functional when you’re done?
The practices I described above (TDD, pairing, and continuous integration) are just a few of the techniques a craftsman uses to build software. These are not tools that necessarily help you to go “faster” in the sense of going 90mph. They are, however, tools that let you go faster in the sense that you’ll save time by not having to go back and fix things repeatedly, and you’ll be able to deliver code working software early, often, and reliably. Think about this the next time someone tells you they need you to go “faster”.