DEV Community

Discussion on: Refactoring a Legacy Project

Collapse
 
avalander profile image
Avalander

I've spent a good deal of the last year refactoring a few poorly written backend services. Here's how we did it.

Start where you make changes more often

You probably will have to build new features and fix bugs. When you have to work on an area of the code, start by refactoring that area and then implement the new feature. The point of refactoring code that works is to make it easier to add new features in the future. If you don't need to touch that code for the next five years, spending a week refactoring it is just waste.

Add integration tests first

When you start refactoring an area of the code, the first thing you should do is add tests to validate the current functionality. That way, when you are done with the refactoring you know that you haven't broken anything.

Measure code improvements

Usually, our definition of legacy code is code that the previous developer wrote and I don't like, which is quite a weak argument for spending time rewriting it. If you are going to spend a large amount of time refactoring code, you should measure that you are actually improving it, and not just writing code that the next developer will want to rewrite.

We used Sonar Qube's cognitive complexity as a guide to see if we were actually decreasing the complexity of the code we rewrote. It is not the only way to measure quality improvements, but I can't stress enough how important it is to have a somewhat objective measure of how your codebase is improving.

A warning on rewrites

Rebuilding a project from scratch is very tempting for us developers. It's tempting because we get total freedom to build it in whatever way we want, we get to make all important decisions, and use the tools and frameworks we like the most. However, I have never seen a rewrite from scratch succeed on any codebase larger than 30k lines of code.

The problem with rewrites is that they take way longer than you think they will. While you are rewriting the project from scratch, you are not adding new features and fixing bugs in the old codebase. Besides all the business concerns with not building new functionality for a long period of time, there are a few issues from the development point of view.

The main problem is that your users will not switch to the new thing until the new project has feature parity with the old one. Which means that you will not get feedback on whether you are building the right thing or not in a long, long time. If the time comes that you are actually ready to replace the old thing with the new, issues start to flow because the old project had evolved to handle hundreds of corner cases that you didn't account for.

Everybody is frustrated that the new thing doesn't work as it should, management gets nervous. You start adding hacks and duck tape because you realise you hadn't designed the project to handle certain cases and it's too late to change early architectural decisions. Finally, you burn out, you quit, and the next developer who inherits your codebase starts talking to management about doing a complete rewrite of the project.

Collapse
 
itachiuchiha profile image
Itachi Uchiha

I'm using Sonarquce in a different project. It is really useful.

All the things you said are right.

I can't add a new feature or I can't fix a bug. Actually, I need to rewrite because the invoice module has many bugs. The sales module has many bugs.

For example, there is a variable like that;

String a = "";

a = a1.ToString();

I don't know exactly what this variable does.

Collapse
 
avalander profile image
Avalander • Edited

That's why we write tests before refactoring a piece of code. That way we can be reasonably sure the new code is not critically broken after the refactor even if there are things in the old code that we don't understand.

Plus, we are able to deploy the new code to production quickly and the users start using it, so if we missed anything or changed some behaviour, we will get feedback on that quickly. If you do a rewrite of the entire application before your users start using it, how long will it take until you realize you missed something?

I get the impression that you are more confident in doing a whole rewrite than refactoring bit by bit, but I wonder why that is. If you don't feel confident to refactor an area of the code because you don't know what a variable does (that's what I understand you are saying in your comment, please correct me if I'm wrong), why do you feel confident you can write a whole new application that will fulfill all the requirements of the old one?