The best code is code you don’t have to worry about. And you don’t have to worry about code if it doesn’t exist.

Think About It GIF by Identity  Find & Share on GIPHY

In this post, I’ll get into the details of what dead code is, why it happens, and how you can resolve it.

Table of Contents

What Is Dead Code Anyway?

Dead code is code that is executed but its result is not used. Another term that is closely associated with dead code is unreachable code. These are often mistakenly confused as the same phenomenon, but that’s not the case. Dead code is executed without its result being used, while the unreachable code, as the name suggests, is never executed in the first place. (To fix that, you can use a flow analysis tool to map our your control flow and find unreachable branches.)

An example

The difference between dead code and unreachable code is illustrated in the following example:

1 int foo ( int x ) {
2 int y = 100 / x ; // dead code as its execution does not affect result
3 int z = x * x ; 
4 if ( z >= 0 ) {
5    return x * x ; 
6 }
7    return -1 ;
8 }

Here’s a breakdown of what you can see here:

  • Dead code: In this example, line 2 will always be executed, but y will never be used.
  • Unreachable code: The return statement in Line 7 won’t be executed because the query z >= 0 in line 4 is always true.

Why Remove Dead Code?

Dead code usually does not get enough attention, as dev teams have to deal with lots of other problems related to functioning and execution. Dead code isn’t breaking anything, so why fix it?

Because dead code is a major source of technical debt. A small amount of technical debt is inevitable and is perhaps even healthy because it indicates that your team is moving quickly. But like financial debt, technical compounds really quickly. Seemingly overnight, your team’s progress can halted in its tracks because you struggling to navigate through all the tech debt you’ve accumulated.

It’s important to monitor technical debt so that you can stay ahead of it. To do this, there are 4 main metrics to leverage. The first two are coding time and review time, both of which are components of cycle time. Technical debt is harder to work with, which means it will take more time to build on top of and the resulting code will be more complex and therefore take more time to review.

With LinearB, you can track each of these, as well as the rest of your cycle time. And with our One Click Context functionality, you can instantly see the individual issues driving bottlenecks in whatever stage.

Cycle time breakdown. Dive into your data.
Get context around cycle time bottlenecks in one click. Diving into your data has never been this easy. Get started with our free-forever account today!

The other two metrics are related to code churn: refactor and rework. They both look at how of a delta is code replacing existing code. The difference is that refactor looks at older code while rework considers more recent code. A high rate of code churn indicates that your team is paying off technical debt. However, a high rework rate also signals that you are accruing technical debt that is promptly causing problems in production and has to be fixed.

In LinearB, you can not only track your team’s rework rate but you can also compare this to industry averages, thanks to the engineering benchmarks we established by analyzing almost 750,000 branches from almost 2,000 dev teams.

Dead code harms the performance of your application. An unusued variable here or there will be negligible, but as applications grow in scale and sophistication, code optimization becomes increasingly important. Removing dead code that eats up runtime and memory is the easiest way to improve performance because it can be deleted and the application’s functionality won’t be impacted.

Dead code also makes your source code unnecessarily complex. This makes the code harder to maintain and build upon. When a developer wants to make a change to the codebase, they have to understand what the existing code is doing. It can take a long time to determine that some code is dead, especially as the program size increases. This is all time that could’ve been saved if that dead code had been cleaned out before.

Another major disadvantage of dead snippets of code is that the interactions and errors they cause must be taken into account even though the affected lines are no longer executed at all. The removal of dead lines of code greatly reduces the susceptibility to errors. It also puts developers in the comfortable position of not having to deal with compatibility issues and compilation problems as much.

Dead code usually does not get enough attention, as dev teams have to deal with lots of other problems related to functioning and execution.

Why Does Dead Code Occur?

The biggest cause of dead code is that it is risky to remove code. No developers wants to be the one to crash the entire app by deleting that one line that actually was needed. Even if something looks like dead code, it’s hard to say for sure.

There are other reasons why dead code arises and goes unnoticed. Often there is simply a lack of the necessary know-how to correctly assess the service life of code.

Another reason that dead code persists is that sometimes it is assumed that the old snippets that don’t serve any purpose can be used again later. Instead of keeping the old code snippets, it is better to use version control in such cases. It is important to note, however, that code that has been deleted is rarely referenced.

Finding and Removing Dead Code: Here’s How

It’s obvious that dead code hinders efficient work and that removal benefits not only the developer but the entire team. However, the question still remains as to how such code can actually be removed.

Static Code Analysis

Since the mid-1990s, it has been state of the art for compilers and static code analysis tools to detect and remove unused sections of code. This optimization technique is called dead code elimination. Since the mid-2010s, similar technology has been used in IDEs to highlight lines of unused code even when editing. Compiler optimizations are typically conservative approaches to removing dead or unreachable code. If there is any ambiguity regarding program behavior, the code is not removed. Therefore, relying on compiler optimizations and static analysis is not a complete solution.

Dynamic Code Analysis

Dynamic analysis tools work by running the program to see which lines are executed. Run-time tools can also be used in such a way that they check which modules are used and which are not during normal operation. There is no need to search the standard libraries or installed packages to find dead code in your project with such tools. A number of open-source tools are available for detecting dead code. Unfortunately, most of them are specific to a programming language.

Code Reviews

Code reviews are the most effective tool for maintaining a high bar of code quality in your teams. Unfortunately, they’re time-consuming and therefore harder to implement than the code analysis tools which are automated.

In order to create an effective code review process, you need to get the buy-in from your team. Simply conveying the benefits of code reviews will only go so far. If you expect them to make a change, you need to give them the tools to actually make that change.

LinearB’s WorkerB bot automates the tedious parts of code reviews that make developers dislike them. WorkerB handles notifying engineers when a PR has been assigned to them, and it will even remind them when they have maybe forgotten about one. WorkerB even enables devs to review PRs smaller than 5 lines from right within Slack.

PR left on read? Not anymore.
Promote your pull requests to merge 10x faster. Get started with our free-forever account today!

Final Words

The saying goes, “If it’s not broke, don’t fix it.” This logic gives rise to dead code. For a while, dead code won’t cause any problems, but technical debt accumulates quickly. If dead code isn’t pruned, it will eventually hobble your engineering team. Your devs will be forced to take time away from shipping new features to clean up the codebase.

You can stay ahead of technical debt by leveraging metrics in a platform like LinearB. You can also leverage automated tools that will identify dead code. But they won’t detect all of it. This is why you should also rely upon an effective code review process.

LinearB offers an integrated solution that helps developers optimize their workflows, team leads optimize team processes like code reviews, and engineering leaders to plan more accurately.

To learn about how you can leverage LinearB to create high-performing engineering teams, set up a demo today.

Start improving with LinearB. Sign up for our free-forever plan or get a free trial of our full product. Get started today.