When I started programming professionally I thought that creating a mess was unavoidable. You code a module, it is beautiful and does exactly what it’s supposed to do, and it does it well. But then someone else makes a change and it’s a little different from how you would have made the change. Then The Business starts requesting more and more features and it drives the design of the system in a different direction than you intended. It gets harder and harder to shim that code together. Too bad the business didn’t know everything they wanted right up front, then the code would still be beautiful. Oh well, maybe next time.
After a few years I got better at refactoring (as opposed to rewriting) and realized that the mess didn’t have to be lived with. The business would make last minute decisions, myself and the rest of the team would make a mess getting it where it needed to be, then we’d spend some time cleaning it up. It wouldn’t be perfect as we’d never get much time before The Business wanted to do something else but it would buy us some time before the code base became all but unmanageable.
I read a blog post a while ago that was passed around at work where the author draws a parallel between software messes and a mess in the kitchen. Just as it’s hard to start adding a feature in a messy code base, it’s hard to start a meal in a messy kitchen.
Just like the kitchen; It’s OK to cause a creative mess while cooking, but clean it up right after the meal. That way you make space for the next creative mess.
This sparked some good conversation and I generally agreed with it. A messy kitchen with stuff on the counters and dishes piled in the sink is enough to make me go out to eat instead. Trying to start a meal that way is always a pain and creates all kinds of unforeseen problems like burning or overcooking as you hurry to wash off a utensil that you needed. It’s much more pleasurable to clean the kitchen first, then start the meal.
But as time went on I noticed something about how I actually work in the kitchen: The first thing I do is put away any clean dishes, wash any dirty dishes, and clean off the counter. Now I’m ready to start getting out ingredients, measuring them, preheating ovens, etc. But as I go there are little breaks in the process where I have to wait for the oven to come up to temp or for the water to boil before I can add something to it and then it has to simmer for 10 minutes before adding the next ingredient. During these in-between-times I wash measuring cups, utensils and pots that I’m done with. I wipe up spills on the counter. By the time I’ve eaten there are only a few pots and pans which are easy to clean up and there is nothing but a clean sink and counter and dishes in the rack drying. There’s no big mess at the end that I have to clean up before leaving the house.
With practice I’ve been able to get closer to this with software development. In the early days of getting good at cooking you’re very frazzled as you learn a new domain. There’s no time to clean anything as you’re trying to juggle the details of what you have to do next. It’s the same with software. There are so many languages, stacks, libraries, and frameworks to learn that you feel you have no time to cleanup. But as you get more comfortable at writing software there are less stretches of time where you’re doing nothing but furiously writing code. There are pockets of time where you can reflect on the problem and, while doing that, do some quick cleanup.
And that’s the hard part. It takes practice. One of my early problems was that, like that blog post, I wrote off messes as inevitable and so never strove to do anything about it. It doesn’t have to be that way. I’m at a point now where I can write code just as fast, if not faster, while maintaining the integrity of the code base. There’s no need to clean up afterwards and there’s no need to cleanup before the next feature. If this seems doable to you, I recommend striving for it. It’ll take time and effort but the journey is worth it. Look for those little time slots where you need to take a break from the problem domain and refactor that design that became obsolete or extract a method where you’ve got some runaway code.
Some may read this and translate “mess” to “technical debt”. I avoided the term deliberately. Back in those early days I mentioned I never thought I was creating a mess, I thought I was creating technical debt. Creating technical debt sounds a lot better, as though you’re making an investment. I went on thinking this way until a little while ago when I’d notice people using “debt” to refer to what looked like laziness. They either knew what to do and didn’t do it or didn’t know what to do but wouldn’t take suggestions from other developers. I had been guilty of both but it became obvious to see it in action from the outside. I searched around and sure enough people like Robert Martin and Martin Fowler had written about the difference between a mess and technical debt.