Clean up the code you work in every day, by being vigilant.
We build software based on our current understanding of the problem, requirements, and technology at hand. Software engineers are all (for now) human, meaning we make mistakes. This leads to missed bugs and code smells. Even small messes compound over time leaving a huge, tangled code mess. If you don’t actively work on keeping your codebase clean you will end up with a sloppy and hard-to-maintain system.
This is what is known as code rot.
As a codebase changes with each new feature or refactor can lead to unused code, missed warning messages, and tightly coupled code. Adding up to a time-consuming mess to understand or change. We try to address everything but deadlines stack up and tech debt gets pushed for business goals. So how do we get ahead of this mess and keep our codebase free of rot?
The 20% rule for handling tech debt. Allocate time in your sprint to address tech debt.
There is a war that goes on in a codebase, the fight between pumping out features and tech debt. It can be hard to convince your product manager how addressing tech debt can actually benefit the team and increase productivity, but code rod is real and will spread unless it’s addressed.
A lot of times it’s hard to notice that you have tech debt as more hands dip into the code base. We can only monitor so much of the pull requests and even if we do there are unnoticed side effects that cause console errors, unused code, or bugs that might take months to surface.
Once we address that code rot is real, we must figure out how to cut it from our system. This can be done multiple ways and depending on who owns the product you might have more trouble getting it done then others.
At Google, they have the 20% rule that allows you to spend 20% of your time working on something that benefits the company outside of the normal product work. This is a rule that shows they value an employee’s autonomy to do work on something that interests them and helps the company at the same time.
This is a rule you can apply to your code base to take a specific amount of time out of your day to address tech debt or code rot. These include smaller refactors, ridding your app of warning or error messages, or even adding unit tests. The goal is small wins that will keep your app healthy and your team proud of what you own.
I hear some of you asking what if my manager or product owner doesn’t want to prioritize these tasks. Well, this is your job as an engineer to convey how important a clean and well-maintained codebase is. If you can’t tackle tech debt it will inhibit the team to implement feature work and push project deadlines because it’s harder to make simple changes.
On one of my teams, we had an agreement to allot 20% of story points to tech debt(nonproduct-related items). As long as we had tickets labeled and pointed we could use those in our sprint to tackle items we want to get to. Allowing us to maintain our App’s cleanliness, infrastructure, or even developer tooling.
20% is an idea.
Maybe 20% is too high, and 10% is all you need for your app. The idea is that you and your team are prioritizing the health of your app so that you can code easily without tech distractions
This one is harder to implement as you will need to identify ways to mitigate code rot from entering the code base but will save time in the future.
I was once on a team where we repeatedly had issues of console errors and warnings piling up. I’m talking dozens of innocuous warnings and potentially problematic errors continually entering the application. This made it hard to develop as it was hard to distinguish if those errors are “expected” as in they already are in the code base.
As a result, the team came together to identify the issue and try to rectify it. Now part of our QA process, we added the console check in order to keep errors and warnings from sneaking into the app.
This, of course, is a manual process and anytime we can automate something we save ourselves time and add a level of consistency to the check.
Integration tests are a great way to keep bugs and other issues from entering the code base. Run these on every PR to prevent them from getting merged.
another example of preventative measures is linting.
“Always check a module in cleaner than when you checked it out” — Robert C Martin (Uncle Bob)
Uncle Bob the author of Clean Code made an analogy to the Boy Scouts’ rule to always leave a campsite cleaner than you found it. He proposes to apply this to your codebase as a proactive way to tackle code rot.
As you implement features you will undoubtedly see issues that should be fixed.
We should look for changes that get missed, a common one is documentation.
JSDoc is a handy way to add information about a function in order to give more context to the inputs and return values. But this can get out of date quickly as it is modified.
Even if you are not modifying the parameters of the function, fixing a typo or incorrect value will help developers in the future who are looking to understand what is going on.
This has its limitations.
When we are cleaning up the codebase we have to balance our feature work with the cleanup. If there are too many unrelated changes your reviewers will have a hard time understanding what is going on and it will lead to a longer review process and confusion.
My personal experience is if the cleanup changes grow enough to confuse the purpose of the PR then the schools be broken up between feature work and campsite cleanup.
Your job as an engineer is to solve business needs. This means if you want to be successful you need to make it sustainable by building processes and planning out how to accomplish these goals time and time again. We want to keep our codebase clean and easy to maintain so that you can perform at the level your company expects.