writing

It is much more fun to cook than to clean

engineeringcode-quality
A messy kitchen covered in programming-themed sticky notes and TODOs

Cooking an elaborate meal is fun. Cutting boards everywhere, intermediary bowls, multiple dirtied pots and pans, you've got the oven going, the sink, spilled a few drops here and there. And when you're all done, if all went well, you can't believe you made elaborate meal for the first time at home! The high from eating your meal quickly turns into dread...time to clean it up.

I've developed a few strategies over the years to deal with this issue, with varying degrees of success.

The first is to try and clean as you go. This works decently well, but in my experience pretty much only for either a meal with a long inactive step (like baking, or slow cooking), or if you have a partner to help allow both tasks to run in parallel.

Another great way is to not make a mess in the first place. One-pot meals, reusing cutting boards and measuring cups, covering your baking sheet in foil, minimizing intermediary bowls, are some examples of this.

My latest strategy is to reframe the mindset. Maybe cleaning is...fun? Lately that's been my go-to strategy; find an enjoyable podcast or a great album, and find satisfaction in witnessing the kitchen's transformation.

But the good thing about cooking is that, at least for me, no matter what strategy I employ, and no matter how daunting the mess is, I will get it done. I refuse to let a dirty kitchen last long; maybe on occasion, I will deal with it in the morning, but it will get done.

We do not have this same luxury in the world of software development. Messes in the codebase have a habit of sticking around. I always chuckle a bit when I see //TODO: clean this up, or //fix this when Issue-305932 is resolved, or my personal favorite: //Temporary hack, written 10 years ago and never fixed.1 But software development does suffer many of the same problems -- most developers prefer cooking (writing code) to cleaning (maintaining or removing code).

I see variations of the same strategies I outlined for cooking play out in the software world. Not making a mess is probably the most effective; establish coding and architectural standards, a well designed and extendable system, integration tests, linting and formatting rules, and a solid review process from the beginning, and you will have a naturally clean codebase as it evolves. When working at a big company, this often requires deep expertise and judgement from the senior engineers who seeded the project. While some of the projects I have worked on have had this luxury, the majority haven't, which makes this strategy effectively impossible. If you want a clean kitchen to work in, you can't have rotting food sitting on the counter.

Clean-as-you-go can work okay. But as much as I see it preached to "follow boy scout standards, leave it better than you found it", I rarely see that actually play out in practice. If you are making a new feature or bugfix, you generally don't want to bloat your diff by attempting to fix problems of the past, unless it is extremely simple and safe. It can work quite well for smaller code-quality concerns. Say I get feedback in a PR that something could be done in a cleaner way, or something nearby should be fixed, I can quickly do a fast-follow PR while the reviewers and I have context on the issue. This avoids scope creep of the original task while still cleaning up some of the tech debt. But generally, tradeoffs and messes made in the past are not as simple as a few lines here and there, they might require cross-team coordination, deep understanding of the consequences, and I have seen many good-faith efforts result in scope exploding for the contributor. Naturally, people learn to stay laser-focused on their task rather than attempting to clean-as-they-go.

So I guess that leaves "reframe the mindset"? I do think deep satisfaction can be gained by cleaning up and simplifying code quality or architectural mistakes of the past. When advocating for work to do, sometimes it can be easy to get distracted by a shiny new project or feature. But if you know that deep down, at some point down the line, your productivity or quality of life will be impacted by an architectural decision of the present, maybe it's best to reframe your mindset and clean that up now rather than get burned by it later, when it will take you twice as long.

Sometimes I think "tech debt" as a concept can be used as a bogeyman among software developers, where engineers blame mistakes from the past on managers and business leaders for their "deadlines" and "metrics" and "money". I'm not one to pretend that we should be killing ourselves over maintaining a pristine codebase if the product doesn't turn a profit -- ultimately, the business must always come first. But often, architectural and even smaller code-level decisions can be made that legitimately burn time and money later down the line. And it's not just managers who can be blamed for this, I have seen many design proposals and code contributions from engineers that disregard some fairly fundamental truths about engineering standards, purely because it is more enjoyable to build faster than stop and think about some of these tradeoffs.

No matter how fun it is to cook, hack, vibe2, skip code quality standards, skip writing those integration tests, design an inconsistent or fragile API just this once, rubber-stamp a PR I know will cause problems later because I just want to get back to my task, I try to remind myself that I will enjoy cooking more in the long run if I keep the kitchen relatively clean.

Footnotes

  1. I would hope that AI can solve this problem; it is now easier than ever to refactor, find and fix outstanding TODOs, but unfortunately I have found the opposite problem. More than ever, developers don't care about the quality of the code they ship as long as it works. After all, why should it matter? The AI will do all the reading, the fixing of bugs, and the development of new features, so why maintain some boomer standards? I don't completely disagree, but personally I still choose to believe that some tenets of code quality and readability should be upheld whether AI is doing most of the authoring or not.

  2. I've intentionally mostly avoided discussing AI's impact on this issue in this post (besides the earlier footnote), but I do think heavy vibe coding can often give that "cooking" high while skipping the drudgery of sweating the "boring stuff", like code quality, security, testing, or actually learning how the heck the system works. I personally enjoy that last part, but I've noticed many people who just want to see their task completed and don't care about understanding the code or the system at all.