Leave the code better than you found it

I help product teams build quality software and lead engineering efforts. Currently working at OpenSpace as a Senior Software Engineer.
Search for a command to run...

I help product teams build quality software and lead engineering efforts. Currently working at OpenSpace as a Senior Software Engineer.
Thank you for the article. This was vivid and very practical. Your tone was drawing and very concise.
Nice tips! I'm used to applying them in my work, clearing old code, and making some features easier to understand. It feels good to see coworkers doing the same.
Thanks for your comment!
Great article Tomasz Gil. I'm sure it will fly well as long as most team members are like-minded about it. Do you see it as a challenge in reality?
Thanks a lot! Yes, for sure it might be a challenge. Thankfully, currently I'm working with people that already share this mindset. But typically you would need to work towards this with other team members.
Last month I built a regression-testing harness for a single library upgrade — React Query v4 → v5 in one of the front-end apps I'm working on. It's about 800 lines of code across four packages. It ru

Images are heavy. When you're building offline support, storing them alongside your application data is tempting — and eventually painful. I hit this wall building support for image attachments. The n

Deciding how to approach offline support can be challenging, especially once you move beyond the basics. So far, I focused on persisting data that was already fetched as a result of user actions. This

Software engineering is changing faster than most of us can comfortably adapt to. The capabilities of LLM models change almost monthly. New tools appear every week. Advice that felt solid three months

This is the eighth post in my series about offline support in web applications and the fifth focused on the foreground queue. In the previous article, we covered error handling and retry strategies. A

You are happily working on a feature. You add a bunch of new code so that it works according to the acceptance criteria. At some point, you decide to reuse some existing code. So you start looking around and then, all of a sudden, you end up in a different part of the codebase where the code begs for refactoring. What now? Should you address this or leave this as is?
Most of us find ourselves quite often in this situation. I recently got asked what's the best approach here and, to me, the answer is one of the rules proposed by Robert C. Martin, which is the boy scout rule . In the context of software engineering, it comes down to the following.
Always leave the code better than you found it.
In theory, it seems pretty simple and straightforward, but let's look at this in practice.
Someone might say - "if I refactor this other part of the system, I'm making changes unrelated to the feature that I'm adding" - and they would be right. But you're not just producing a feature. You are an engineer responsible for both how the product works and how easy it is to maintain. I assume you try to make the code you're adding clean, simple, and well-abstracted so that you don't have to repeat yourself. At some point, you will inevitably touch some existing part of the system. All previously mentioned rules should still apply here. Otherwise, with every new functionality added, your application will be slowly degrading.
Ultimately when faced with smelling code, you have two choices. Either address this right away or count on the next developer to do this when they enter this place. And let's be honest, option number two might never come to fruition.
You decided that you want to address the issue. Great! Now, before you jump into refactoring, there are a few things that work for me especially well, that you might want to consider or keep in mind.
Take notes and revisit them once you're done with a significant portion of your current work. Going straight into refactoring some other part of the system will be a distraction. You need to switch context, perhaps get familiar with what's around. It might be better to leave a short comment and get back to it once you finish writing the code related to the feature you're working on.
Think about the return on investment. Is the change you're trying to add simply stylistic? Or will it allow you to reason about the code more easily, reuse some existing functionality or make the infrastructure more robust? It pretty much boils down to whether the change will make your work in the future faster. Is the answer yes? Awesome, let's move on!
Assess the size in comparison with how much time you have. Will it take you minutes or hours to do the changes? Perhaps it's more like days or even months? Do you currently have this much time? Even if you don't have any time, you might mark whatever smells as deprecated, create a separate ticket for refactoring and make sure it doesn't get lost in the backlog.
Check if the code you're about to interact with is well-tested. Before doing any changes in a new area that you're entering, it's key to understand this area and check the tests. It might be worth first writing or increasing the confidence that existing tests give you before applying any changes. The last thing you want is your good intentions backfiring at you.
Don't fall into a rabbit hole. One improvement can lead to another, which then can lead to yet another one. Make sure you set some limit for yourself so that you don't end up forgetting what was it that you were initially implementing. The goal here is not to make the place perfect. It's to have it a bit better than it used to be.
Make it easy to review and test. Similarly, as you don't want to break things, you don't want your colleagues disliking you for giving them extra work to do. Clearly outline what the refactored parts are. I don't think there's one way to do this right, and it all depends on the scope of the changes you're adding. You might add appropriate comments to guide other developers through the changes, which might be enough for simple things. You might deliver those changes in a separate commit. Finally, you might create a subsequent merge request to handle refactoring.
You've done a terrific job by making things a little better. But where this approach shines is when other developers share the same mindset and do this consistently. The best way to encourage other's to do this is by sharing what you did and pointing out what in it for them. When you see that someone has done the same in their merge request, tell them that it's awesome and that you appreciate this. Once everyone adopts the same frame of mind, the effect multiplies. You can effectively prevent the codebase from degrading or collectively address issues that are scattered all over the repository.
These incremental improvements will not replace planned refactoring processes - it still might be the only way to deal with more complex problems or some specific parts of the system. That said, it should, over time, make a positive impact on your codebase. Give it a try!