This is the third and final part in my short series on tackling legacy code. Previously, I wrote about general coding techniques, and about the organizational and operational requirements.
I would like to close with some final thoughts.
Technology isn’t the problem
We developers can’t help but get enthusiastic about new technologies: languages, frameworks, libraries, techniques, etc. But more often than not, the problem with a legacy project is not the chosen technology or its age. Rather, it’s the way the older technology has been used.
If you decide to rewrite a project in a newer technology, chances are you will have a second legacy project in a few years time. And if you decide to just slap on the new thing on the old thing, the ugly stuff will still be there.
A new technology won’t solve your problem of legacy code, of brittle (or non-existent) tests, of code nobody dares to touch.
But it’s easier and more fun to try out the hot new shiny thing in town. So many developers tend to favor a rewrite. And I get it, it is exciting to try out something new. However, when using company time and money, there is more to it than personal preference (though that is not unimportant).
What’s more, it could very well be less effort to transform a legacy project, than to rewrite it from scratch. Don’t underestimate the amount of knowledge that is present in an older application.
Choose your battles
A legacy codebase is often filled with ugly constructions that frustrate you. Be careful not to take on too many issues at once. Go for the low hanging fruit first (i.e. little effort, great value), and move on towards the more difficult pieces. Having more small issues out of the way will make it easier once you start with the bigger issues.
Don’t be frustrated that this means the pace is slower than you would want. If you choose your battles, you will avoid the lava layer anti-pattern and have a higher chance of succeeding.
When tackling a legacy codebase, you will invariably introduce new conventions. Maybe there was a naming convention that is non-standard. Maybe there was a God object for data access that you want to split up into repositories. Whatever it is, try to stay consistent inside the project.
Consistency trumps whatever new thing you’re trying to introduce. You might not think combining the old and the new way is confusing, but it adds to the mental effort developers need to make in order to understand what is going on.
Consistency also avoids the lava layer anti-pattern mentioned above. You never know, maybe you’ll introduce an even better convention later.
You might not be able to introduce a new convention in one go, giving you a period of time where you have the old and the new way living side by side. That’s ok. But have a clear goal in mind and a path to achieve it.
I’m convinced a lot of projects can be salvaged and cleaned up, making them maintainable and more stable once again. I’ve personally done it a few times, and the satisfaction that you get from taming that ugly beast is amazing.
Incidentally, if you have trouble with a legacy project, I’m an independent developer that actually loves improving legacy code. Give me a call if you need some advice.