What is legacy code? Best practices for working with legacy code.
November 13, 2018

8 Tips For Working With Legacy Code

Coding Best Practices
Static Analysis

Dealing with legacy code can be a chore. But, unless you’re starting a project from scratch, it's inevitable. And that means you need a better way to work with it.

That is why we have included guidance that explains what is legacy code, best practices for working with legacy code, and how static code analysis can help with refactoring legacy code.

What Is Legacy Code?

Legacy code is any code that is maintained by someone who didn’t write it. However, legacy code can also be any code that you don’t understand and that’s difficult to change. This can refer to code inherited from someone else. Or to code inherited from an earlier version of the software. Or it can refer to code without unit tests.

Why Is Legacy Code a Challenge?

The biggest challenge with working with a legacy codebase may be your assumptions about it.

You may think the code is bad. Whoever wrote it didn’t know what they were doing. You could have done a better job.

But the truth is, there usually is a reason why the code is how it is. And, if you didn’t write it, you might not know that reason.

That’s why care needs to be taken when making improvements to the legacy codebase. You can’t just put a quick fix on one area. There might be some dependencies you’re unaware of.

And that’s why it’s important to know when to maintain the legacy codebase and when to change it.

8 Tips for Working With Legacy Code

You can’t improve the legacy codebase overnight. But you can take gradual steps to improve it.

Whether you’re just getting started with a legacy codebase — or you’ve been working on one for a while — here are eight tips for working with legacy code.

1. Test the Code

One way to understand the code is to create characterization tests and unit tests. You can also run a static analyzer over your code to identify potential problems.

This will help you understand what the code actually does. And it will reveal any potentially problematic areas. Once you understand the code, you can make changes with greater confidence.

2. Review Documentation

Reviewing documentation of the original requirements will help you understand where the code came from.

Having that documentation handy will help you improve the code — without compromising the system. Without this information, you could accidentally make changes that introduce undesirable behavior.

3. Only Rewrite Code When It’s Necessary

Rewriting the legacy codebase can be tempting. But it’s usually a mistake.

It takes too much time and too many programmers to rewrite everything. And even if you do it, rewriting code can introduce new bugs. Or it can remove hidden functionality.

4. Try Refactoring Legacy Code Instead

It’s better to try refactoring the legacy codebase rather than rewrite it. And, it’s best to do it gradually.

Refactoring is the process of changing the structure of the code — without changing its functionality.

This cleans the code and makes it easier to understand. It also eliminates potential errors.

When refactoring legacy code, it’s best to:

  • Refactor code that has unit tests — so you know what you have.
  • Start with the deepest point of your code — it will be easiest to refactor.
  • Test after refactoring — to make sure you didn’t break anything.
  • Have a safety net — e.g., Continuous Integration — so you can revert to a previous build.

5. Make Changes in Different Review Cycles

Don’t make too many changes at once. It’s a bad idea to refactor in the same review cycle as functional changes.

Plus, this makes it easier for code reviews. Isolated changes are much more obvious to the reviewer than a sea of changes.

6. Collaborate With Other Developers

You may not know the codebase very well. But some of your fellow developers probably do. It’s much faster to ask questions from those who know the codebase best.

So, if it’s possible, collaborate with someone who knows it better than you do. A second set of eyes on the code may help you understand it better.

7. Keep New Code Clean

There’s a way to avoid making the code more problematic. And that’s by ensuring new code is clean. It ought to be written to adhere to best practices.

You can’t control the quality of the legacy codebase. But you can make sure that the code you add is clean.

8. Do Further Research

Working with a legacy codebase gets easier with time. A junior developer may not understand why a codebase hasn’t been refactored (and may be keen to refactor it). But a senior developer will know when to leave it alone.

Learning more about the codebase will help you improve it.

A good starting point is “Working Effectively With Legacy Code” by Michael C. Feathers, which contains some good examples of how to make changes to the codebase.

Another good source is “Refactoring: Improving the Design of Existing Code” by Martin Fowler. This book offers many tips for effectively refactoring code.

Tools for Working With Legacy Code

You’ll always need to work with a legacy codebase — or work around it. After all, the code is there for a reason. It works. And its results may be good enough that you can let known issues go.

There are good reasons for making changes to code, too. You might be adding a feature, fixing a bug, or improving design.

In a perfect world, you’d continually rewrite that legacy codebase until it’s fully debugged. But chances are, that won’t be practical.

So, what you need to do is figure out what you can change — and leave the rest alone.

Static Code Analysis and Legacy Code

One way to do this is by using a static code analysis tool. You can set a baseline and then run analysis on the new code to make sure it’s clean. And you can suppress results from your legacy codebase.

Helix QAC, for example, makes this very easy to do.

Analyze Legacy Code

Helix QAC can check your legacy codebase against rules, typically from a coding standard. You’ll get diagnostics of violations. And you can prioritize them by severity. This means you can focus your attention on fixing the most error-riddled pieces of the legacy codebase first.

Explore coding standards >>

Set Baselines

You can also set your legacy codebase as a baseline. Maybe the code is fine as-is, and you want to leave it alone. Setting a baseline means that the legacy codebase won’t be pulled into your diagnostics. Instead, you can focus on finding issues in new code — and ensuring that’s clean.

An example of a baseline for legacy code in Helix QAC.
Helix QAC makes it easy to set baselines.


Use Suppressions

You can also use suppressions to create exceptions for your legacy codebase. So, you can essentially dismiss violations in it. You might set your suppressions on specific rules or violations within a particular category.

An example of a baseline with suppressions for legacy code in Helix QAC.
Helix QAC lets you suppress diagnostics found in legacy codebases.


Ensure Compliance

In some cases, you may be reusing a legacy codebase from one project to another. But, some weren’t developed with coding standards. And if you need to achieve compliance (such as with MISRA), this can create problems. By using a Perforce static code analyzer — like Helix QAC for C/C++ or Klocwork for C, C++, C#, and Java — it’s easy to see where the errors in your code are.

Improve Legacy Code With static analysis