We'll respond shortly.
I want to go fast forever.
Let me back up. My client wants a new feature for their software. I’ve been doing this long enough to know that there’s a good chance they’ll want to change what they see, once they see it. So I want to show them something as quickly as possible – before I waste time building the wrong thing.
But sometimes I can’t show them something quickly.
Sometimes the code is just plain indecipherable. It takes me a long time to understand it, because the writer did not think about someone ever reading it. And that slows me down.
Sometimes it’s downright tedious. Sometimes lots of parts of the system have to stay in sync, because they all know something – and when that “something” changes, they all have to change with it. And that slows me down.
Sometimes it’s frustrating. When I make one change, ten other things break, for reasons I don’t understand. This slows me down. I have to build a vast mental model of the software in order to keep track of everything. That takes a long time, and it’s exhausting. And that slows me down.
I want to go fast forever.
But I can’t. I can’t because my code isn’t clean. I need to clean it.
How do I keep code clean? I change it. Every new feature of the system changes my understanding of the system, and of the problem domain. And my code needs to reflect that. I need to make the code the clearest, cleanest, simplest, and most obvious expression of the problem domain as I currently understand it. Every time I add new behaviors to the system, I need to update the code, refactor it. Every time.
But fear keeps me from changing it. What will I break when I change this code? When I don’t change my code, it rots. And I go slower, and slower, and slower.
I lack confidence. How can I feel confident that my changes haven’t broken any of the expected behaviors of the system? I need a magic button that I can press at any time that will instantly tell me if I’ve broken something.
I haven’t found a magic button. So what do I do instead? I write tests. And those tests, if written well, will quickly tell me if I’ve broken something. Depending on how I write them, they might also tell me other things about the design of the system. But that’s a different story.
Tests are an implementation detail for a feature of your team: the ability to go fast forever. They don’t come for free. They’re hard work. They’re not an end unto themselves. They’re a means to an end. There are other ways to implement this same feature. But from what I’ve seen, they’re more expensive, slower, and less reliable. If I find a cheaper way to implement this feature, I’ll gladly try it. I still want that magic button. Till then.