Code rot is a term that isn’t used very often anymore. You’re probably familiar with the term technical debt. Well, code rot is a form of technical debt that accumulates over time. In this post, I’ll discuss some specific types of code rot. I’ll also briefly cover the cause and consequences of code rot and what you can do about it.

What Is Code Rot?

In essence, code rot is a process where the quality of your code deteriorates over time. We’ll see some different examples and causes later, but the idea is that you have a piece of software that no longer has the same level of quality that it used to have.

That means code rot is a form of technical debt, albeit unintentionally. Technical debt can be a conscious choice, but it can also occur because of a lack of experience and knowledge or changing circumstances.

Code rot can negatively affect your team’s productivity and morale, so it’s important to recognize it and mitigate it. Let’s look at some ways that code rot can manifest.

Symptoms of Code Rot

This is by no means an exhaustive list of symptoms of code rot, but it should give you a general idea and help you identify code rot in your codebase.

Unused Code

We can identify two types of unused code: unreachable code and code that can be executed but isn’t currently.

Unreachable code is code that your developers see when they edit code but only gets in their way. Some pieces of unreachable code are easy to spot:

var includeDetails = false;
// includeDetails = req.params.includeDetails && req.params.includeDetails;

if (includeDetails) {
   ... unreachable code here
}

This code contains a toggle that used to be set by a query string parameter. Nowadays, it uses the default value (false). This means the code inside the if-clause cannot be reached. Clear enough, right?

But things may not always be so obvious. It may depend on data in the database, user input, the code configuration, or a combination of those variables. Whatever the cause, unreachable code is extra noise in a file that reduces developer productivity because they have to remove it mentally. Why not just remove the code from the file?

Another type of unused code is code that can still be reached but just isn’t at the moment. Think of APIs that no client uses anymore.

Two things can happen with code like this. One is that developers are aware of this unused code and no longer put any effort into it. This can cause hidden existing bugs to appear in the future when the code is executed again. In the other case, developers aren’t aware that the code isn’t used and feel obligated to keep it up and running. This can be a waste of time and resources.

Another type of unused code is code that can still be reached but just isn't at the moment.

Unreadable Code

When code is edited often and without regard for quality, it becomes unreadable, making every following change harder to implement. What seem like simple changes take a long time, frustrating all stakeholders.

This is code rot because it is a process that happens over time: the first version of the piece of code was quite readable. But after hundreds of edits, things have become a muddled mess.

Inconsistent Data

Over time, an application may start to accumulate inconsistent data in its database. Business rules may have changed, or maybe someone fixed some bugs. But data entered into the database before the changes occurred may no longer satisfy the developers’ assumptions. This can be old data that is no longer read so that it causes no harm. But if the data is occasionally read, it can lead to mysterious bugs many months after the breaking change.

Outdated Documentation

When I say documentation, I mean all kinds: from variable names over code comments to wiki pages and manuals. When documentation gets out of sync with the code, it’s hard for the reader to know its correct behavior. Developers need more time to figure out how to perform their tasks, and users may become unhappy with the product.

Active vs. Dormant Rot

In the examples above, you may have seen two causes of code rot: either the code isn’t updated enough, or it’s being updated without regard for quality. The first is dormant rot, and the second is active rot.

With dormant rot, our code isn’t updated while its environment evolves: APIs we depend on no longer work, other options offer better solutions, hardware and platforms are no longer supported (or stop working entirely!), users stop using features, etc.

Active rot happens when our code does evolve but in the wrong way.

Active rot happens when our code does evolve but in the wrong way. While we fix bugs, add features, and modify our design, the quality of the code may deteriorate. As we change our code, we need to watch for quality—things like maintainability, readability, testability, documentation, usability, reliability, and performance. Disregarding these makes our code “rot” and end up in a state that seems unsalvageable.

Causes of Code Rot

In short, code rot arises from failing to maintain quality in our code and our architecture. We might cut corners because of lack of experience, pressure from management or users, or external changes. Whatever the cause, it takes a considerable amount of effort to avoid code rot. We need to keep our documentation up to date. We need to monitor external dependencies for updates and changes, and if there are any, we need to update our code. Our team will also need to refactor existing pieces of code to adhere to new guidelines or improve the quality.

If you’re interested in learning more about the causes of code rot and technical debt, check out this video:

Consequences of Code Rot

Avoiding code rot takes away time from what many businesses like to focus on: new features. But efforts to curb code rot are important because code rot can seriously damage your code, your users’ trust in you, and—let’s be honest—your bottom line. Let’s briefly look at some consequences of code rot.

More Bugs

Obviously, the above types of code rot can lead to bugs. Code rot can hide existing bugs from developers and make it easy for developers to introduce bugs when implementing new features. Because the code is unclear or data is inconsistent, bugs occur more often in codebases with lots of code rot than in cleaner projects.

Slower Development Pace

Projects with code rot are often harder to navigate by the developers. Consequently, trivial features can take longer to implement. A feature might also need more code than necessary, increasing the code rot already present.

Take a look at your cycle time to see how long it takes a team to implement a feature. Doing so can help you identify bottlenecks: is it the code and the implementation, or are there other factors that cause a long cycle time?

Lower Morale

Developers don’t like to spend more time than necessary working with bad code. They don’t like fixing bugs all the time. They want to be proud of their work and deliver a quality product, both internal quality (well-structured code) and external quality (a good user experience). Projects with lots of code rot are harder to work on, which can lower morale, decrease productivity, and increase the likeliness of developers leaving the organization. In that case, you need to find someone new and go through the lengthy and challenging onboarding process.

Paulo Rosado, Founder and CEO of OutSystems, explains how this works in the Dev Interrupted podcast (see the full episode here):

Fixing and Avoiding Code Rot

Now that we know what code rot is and why we should manage it let’s look at identifying, fixing, and avoiding it.

Testing

While automated tests don’t avoid code rot directly, tests help developers feel confident changing and deleting code. This allows them to keep the code quality high and code rot to a minimum.

Metrics over Time

Several metrics can help identify code rot and its evolution over time. Metrics like cyclomatic complexity, code churn, cycle time, and code coverage don’t necessarily point to code rot. Still, the code fragments they do point out are great candidates for further inspection.

Fix It!

Fixing code rot is simple in theory: ensure you have a good test suite and encourage developers to refactor and improve their code. But while simple in theory, the reality is often quite harder. That’s why you will need to be patient as the team tackles code rot bit by bit.

Avoid code rot by keeping a close eye on your metrics and automating. You could have the CI/CD pipeline fail if the cyclomatic complexity goes over a certain threshold. Or if the code coverage drops below a given percentage. High numbers for code churn and cycle time might warrant an open discussion with the team.

Don’t Panic

If you feel like you have a big task ahead of you, that’s OK. Every company does. Luckily, you’re not alone. Tools like LinearB and the metrics that it provides can help your team slowly but surely start reducing the code rot and the technical debt. Rome wasn’t built in a day, so allow for ample time. But know that it’s possible to improve the situation while still delivering new features and business value.

Improve your engineering organization at every level with LinearB
Want to improve your engineering processes at every level? Get started with a LinearB free-forever account today!