Take every opportunity to improve legacy code

Jordan Chapuy
5 min readSep 8, 2020

--

Living with a large legacy codebase is not pleasant. Changes are long, bugs accumulate, understanding is lost. However, nothing forces us to suffer these inconveniences forever. We can act, at any time, and right now. There is no need to start a big project for that, nor to plan a plan to go to the Moon. We can do refactoring in small steps and do it regularly. Take advantage of every opportunity (an evolution, a task, a correction) to improve the code around the changes. This simple concept allows us to improve the quality of the code over time.

This summer, I had a bug to fix on a part of the application I hadn’t worked on yet. After a short walk through the code, I encountered the RoadMapBlock. The famous RoadMapBlock. It certainly doesn’t speak to you, but in our teams, this name has a big reputation. I heard that name in my early days. Its evocation aroused nervous laughter and despair. It’s even known to the non-technical people. But what is it then?

The RoadMapBlock is both a central component for one of the most important screens of the application and one of the big pain areas of the project. This element was created years ago and has since been modified by dozens of developers. To give you an idea, the class has about a hundred functions. The method that contained the bug was about a thousand lines and had a great complexity (a hundred ifs, several levels of nesting, loops, …).

A nightmare at first glance, but also a huge opportunity for improvement.

Refactoring legacy code progressively

I started my work session by locating the error in the code. I felt that something was happening in a part of this function, but the area was hard to understand. So I started doing some quick refactoring to gain understanding. I did several refactoring operations to improve the code, to make it my own, and to see more clearly. It’s a quick way to understand legacy code that I like to use (I wrote more about it in my previous article). It was a great help. Soon after, the cause of the bug was obvious to me and I was able to fix it easily. The correction was a single line. But was it over? No!

I was there, in the middle of all this legacy code. I had taken time to understand some of it, to analyze it, to load it all into my head. I had even made some changes here. Why not improve the code while I was still deeply involved in this context? Understanding legacy code is often difficult and time-consuming. It’s not something that motivates most developers either. We must seize the opportunity to improve it. We’re not likely to wake up one morning and say “I’m going to do that part just for fun”. If we don’t do it right now, we’ll probably never do it. This code that hurts us so much will remain a thorn in our side.

So I started refactoring again cleanly. My gain in comprehension allowed me to do it better. I renamed some variables and methods. I extracted methods to start splitting and structuring. I decreased the nesting levels of if, switch, and for. Simple actions which will help a lot in the future. We read a lot more code than we write. Doing refactoring now will help us to better understand and change this code every other time.

It is also a foundation for wider refactoring. The succession of small improvements facilitates a more consequent refactoring. One day, it will be easy to rewrite everything. The refactoring of a complex function of a thousand lines requires a huge effort. But this same function, divided into several small simple functions, better named, better structured, is much easier to modify. Maybe it will not even be necessary anymore, the structure of the code may be good enough to be understood and to evolve.

The improvement of the code surrounding our modifications can be done very quickly. I guess I didn’t take more than an hour. One hour on the life of a product is nothing. And yet, it’s a big gain. We act now, we start doing. It’s easy to complain about legacy code, it’s also easy to make improvements in small steps. However, complaining won’t get things done.

Know when to stop

We’re finally engaged in this refactoring. We want to do it well. We may want to do something perfect. Or to rewrite everything. But the important thing is to start improving, in small pieces, and to do it regularly. It is easier to be regular by doing small refactoring. With time, it will become an automatism. I make a change here, I will take this opportunity to improve there. The overall quality of the project will gradually increase.

The goal is not to make something perfect. It would take too long. In some cases, the legacy is so huge that many adjustments have to be made. Unfortunately, some changes are long and complex. Breaking dependencies. Changing the code structure. And what is perfect code? We can always improve and do things differently. The design of the code may annoy you, but that’s okay, it’s better than before.

The goal is not to rewrite everything. That would be risky and also time-consuming. If we want to rewrite everything at one time, the work will be huge and probably risky. We can make big mistakes, screw up the refactoring. We can discover many problems along the way and take much more time than expected. Worse, we can give up before we’re even finished. All the work will then be wasted. The team or management may find it harder to trust us on other subjects. It’s best to focus on the part we want to improve at this moment.

So we have to be able to stop at some point. Focus on small improvements. It’s already better than before. If we come back to it later, we can improve it again. Even in a more macro way. I hope that my refactoring of a small area of the RoadMapBlock is the first step to improving the whole thing. This work will continue and inspire other developers.

Get started, now

All improvements are interesting. From simple renaming or dead code removal to method extraction or restructuring. Improvements can be simple and done quickly. There is no excuse to avoid changing legacy code. There’s no need to rewrite everything or spend whole days on it.

Make small improvements and be regular. This is one of the keys to reducing legacy gradually. Take advantage of a bug fix or a new feature to improve the surrounding code. Take action now.

And you, what are you doing to improve legacy code? What are your strategies?

--

--