Many programmers I’ve talked with are a fan of the Boy Scout Rule: leave the campsite a little cleaner than you found it.
For the most part I think this is a good guideline. I follow it myself. There are certain ways in which it’s insufficient, though. There’s also a way in which the Boy Scout Rule is actually harmful. I’ll discuss each individually.
When the Boy Scout Rule is not enough
In the analogy of “leave the campsite a little cleaner than you found it”, this case is a little more like a national park containing dozens of individual campsites. Maybe I’ve discovered that none of the campsites have a proper firepit. I can’t just build a firepit on each campsite whenever I happen to do some other work on it (if I ever happen to do some other work on it at all). This is the kind of change that needs to be discussed among everyone and then applied as a distinct project as opposed to haphazardly over a period of who-knows-how-long.
What I want to leave you with is this: many cleanup tasks are campsite-level tasks. These can be done on one’s own without team involvement. Other cleanup tasks are park-level tasks, and are not in fact tasks but projects. These projects need to be done with the involvement of all the appropriate team members.
When the Boy Scout Rule is harmful
If in the course of building a feature or fixing a bug I make little improvements as I go, I’ve gone from doing just one thing—completing an issue in the backlog—to doing two things—completing an issue in the backlog and improving a piece of the code.
A lot of the time this is fine. Sometimes it’s problematic though. If I mix writing a feature with refactoring the code, my pull request will be harder to parse. It will be harder for any pull request reviewer to tell what exactly changed between the old code and the new code. Some of what I’ve done is refactoring, changing the code without changing the behavior. Other parts of what I’ve done change both the code and the behavior. How can someone tell which is which? It’s not quick and easy to tell which is which.
If a feature or bugfix is mixed with code improvements, my change is no longer atomic. Sometimes when I’m writing a feature or performing a piece of refactoring, I realize that I’m headed down a bad path and I want to revert what I’ve done. Or a few days after I introduce a change, it’s revealed that the change contains a bug, and the fastest and least risky fix is just to revert the entire change. If a feature/bugfix and piece of refactoring are mixed into one piece of work, it’s impossible to roll one back without rolling back the other.
If I discover that the area of code in which I need to change is hard to understand, my go-to move will often be to refactor the code as a separate, atomic piece of work, before I make my change. First I make the code easier to change by refactoring, then I make the change (to paraphrase Kent Beck). Preferably the refactoring step happens as a completely separate PR from the step that introduces the behavior change.
To me, “leave the campsite cleaner than you found it” makes it sound like I’m supposed to just kind of casually clean up a few things in the course of doing your regular work. This is often fine, but I’ve found that being more thoughtful and methodical about the cleanup work can bring substantially better rewards.