Fixing Legacy Code — The Obstacles and Solutions

Jan Dudulski

Fixing Legacy Code — The Obstacles and Solutions

There's a red alert in your mailbox and you know exactly what it means - the system is down and you have a 500 error on a specific action. Your response is clear - you find the bug and fix it as fast as you can.


In most cases, refactoring legacy code - particularly someone else's work - involves adapting to the multitude of styles and errors that you will discover upon reviewing the code.

We adjust our habits to fit what's already been created because it's easier, faster, and frankly, trying to deconstruct someone else's mistakes is an exercise in patience.

The foremost issue remains, however: you didn't fix the problem. You are actually encouraging the errors by increasing the technical debt for everyone involved in the project. Perhaps this manifests by adding another condition to a long if-else block or by adding a new line to cover another special case in a 100-line long method.

Regardless of the issue being perpetuated, another developer (or you) will struggle because a new bug has been created. Now the developers will need to understand both the old code as well as the new addition. It's possible that, even if you don't add much complexity to the code, you've still created an issue for the other team members. Perhaps you've misunderstood a certain component and you've added code that doesn't make a ton of sense.

The myths that prevent you from fixing legacy code

The first major myth of revising legacy code is thinking in terms of code ownership.

While in the editing phase, code is very much person-agnostic. When you dive in to edit code, you are not fixing someone else's mess, you are just fixing a mess. Your primary responsibility is to leave the place better than when you arrived. It's not about feeling better emotionally, but about taking responsibility for your actions. An engineer can't get away with not fixing the problems in a plane's engine, so why should a software developer get away with not fixing the bugs in code?

Another problem is the mythical term one day - integral to the art of pushing tasks to an unknown future date. One day, when I have more time, I will refactor this. As you probably already know, such a day will never come, but what will come is a more complicated mess.

And the last myth of all - it takes too much time (and money), and we don't have the resources. We just cannot do this!

Bullshit! Nobody insists that a complete redesign is made - if you can come up with a better name for a method, add some tests, or extract code, then do it! It truly won't take forever (most likely just a couple of minutes). You've already spent some capital to get everything running efficiently and effectively. Nobody is going to yell at you for spending a bit more to make even more improvements. But there is a chance that the next developer would be thankful for the changes.

The profits of doing the dirty work

I already mentioned that you can simplify everyone's future workflows simply by improving the code with each edit. Worse code means more bugs. Better code means fewer bugs. I've encountered this personally a number of times while correcting legacy code bases and finding broken links in the code chain before the customer did. And, of course, I just fixed them. An obvious win.

Sometimes you think that you understand how things are progressing, but if you try to improve upon what you already know, you will find that nothing is obvious or inflexible. You can make your life easier and strengthen the project from future perplexing errors that would result from improper code editing.

If you just add to the project's technical debt by failing to fix code errors as they are discovered, the same bugs will probably pop up again and again. And again. And again. And the one certainty is this: your customer will not be happy.

The fear of change also plays a role in perpetuating code errors. When you're fixing code and you come across a complete mess that looks like a house of cards, you're afraid to touch a single line of legacy code for fear of crashing the whole system.

Incrementally improving the code base through step-by-step edits means that everyone involved with the project will have less fear. 

How should I?

First, always develop your work with a margin for improving the code base. There will always be misunderstandings, frustrating days, and a better approach to address a task. Any code becomes legacy during the time it was written. If you don't need to worry much about the time that you spend on such tasks, then just add it to your estimates.

If you are really in a hurry, but you see something that needs improvement, add a comment to yourself and return to the problem as soon as you can. The same day would be the best.

Read Working Effectively with Legacy Code by Michael Feathers and Clean Code by Uncle Bob. And always leave things better than when you found them.