In my previous post, I gave some insights into how you can start turning the legacy ship around. In the end, I talked about preconditions that should be fulfilled before you start. I’ll dive into those now.
First and foremost, the organization must agree that tackling the legacy code is something they want to do. “The organization” can be defined on several levels: from the team to upper management. But the more support you have upwards, the better. Because you will be investing time, and thus the company’s money, into this.
If your organization sees no hail in tackling the legacy code, try to understand their reasoning. The application might be generating money and here you have these developers wanting to rattle the cage. You will have to explain the concept of technical debt and how it is something they pay for daily, gets worse and worse unless tackled, and in the long run even makes developers leave.
This is a hard one for most developers, because it requires them to get out of their technical comfort zone and talk business terms. Tools like NDepend can help here, I’ve found, because they have a way of calculating technical debt and translating it into real numbers. Or see if you can point to specific bugs that occurred and how much they cost to find and fix due to the technical debt. Or show them how much time it took to implement a trivial change.
On the other hand, if the application is running fine and doesn’t need any new features, ask yourself if it’s necessary to refactor. Maybe not.
Finally, depending on the complexity of the legacy code, the organization must be OK with mistakes being made. Continuous integration, automated tests, staging environments, and other techniques can all help to reduce the amount of mistakes being made. But you must take into account that they will happen. So keep in mind how mission-critical the application is.
Before you even start to change that ugly code, you better have the basics in place.
Make sure you have a decent system of source control. More than just having it and using it, make sure your team uses it well. This means using descriptive commit messages. You should state what changed, but it’s often very useful to also mention why you changed it. This is true in general but especially for legacy projects, it helps explain the reasoning behind the change. Weird code often means weird changes because you can’t fix it all at once. And you’ll regularly be looking at commit logs weeks or even months later to understand why a piece of code looks like it does.
Next up is a continuous integration and deployment pipeline. Start with the integration if you don’t already have it. Make sure every commit is built and any tests are run. Let the build fail if something doesn’t compile or tests fail. Be sure to notify the team and, very important, fix the build when it fails.
When you have source control and a build server set up, work on an easy deployment pipeline. If you’re still copying binaries to the server, you should look into automated deployment methods. Most build servers will support this. There’s no need to deploy immediately on a successful build, but you should at least be able to deploy with a single click of the mouse.
So, you have the build and deployment pipeline set up, and all is going well. What happens when you deploy something that severely messes up data? You do have backups in place, don’t you? Even in projects without legacy code, backups are important. So if your application doesn’t have regular backups yet, take the time to put those in place.
Finally, after the dust has settled, how easily can you diagnose what went wrong? Be sure to write useful statements to a log file or service. Maybe send an email or text message in case of errors, so that you can quickly intervene.
The organization must be OK with tackling the legacy code, but it can take some negotiating before this is accepted. This makes it all the more important to minimize the risks. This is done by optimizing the way you work.