What is a legacy system? It is old software that is very hard to maintain, to extend, and to improve. On the other hand, it is also a system that is working and is serving the business, otherwise it would not have survived.
Perhaps, when it was first created, a legacy system had an excellent design, a design so good that people started to say, “Okay, maybe we can use it also for this, and this, and this.” It becomes overloaded with technical debt, but it still works. These systems can be amazingly resilient.
Still, developers hate working on legacy systems. It can seem there’s more technical debt than anybody could ever repay. Perhaps we should just declare bankruptcy and move on. Much easier.
What if you really have to maintain it? What do you do when you have to fix a bug?
Solution number one: duct tape. Hold your nose, fix the defect — “Okay, we may regret this one day, but let’s do this copy–paste now, just to fix it.” From there it will only get worse. Like in an abandoned building, it may stay undamaged for a long time, but as soon as there is a single broken window, it will soon be left without any windows intact. Just seeing a broken one encourages people to break others. This is the law of broken windows.
Solution number two: forget the old system and rewrite from scratch. Can you imagine what the problem with this solution is? More often than not, the rewrite will not work or it will never be finished. This comes from survivor bias. You see the old system code and say, “Oh, come on, if whoever wrote this terrible code was able to make it work, it must be quite easy.” But it’s not. You may consider the code horrible, but it’s code that has already survived many battles. When you start from scratch, you don’t know the battle stories, and you’ve lost a lot of knowledge about the domain.
So what should we do? In Japan, there is an art called kintsugi. When a precious object breaks, instead of throwing it away, it is put back together using gold powder along cracking lines. The gold emphasizes that it was broken, but it’s still beautiful.
Perhaps we are looking at the legacy code from the wrong point of view? I am not saying we should gold plate the old code, but we should can learn how to fix it in a way that makes us proud of it.
The Strangler pattern allows us to do precisely this. It is named for a fig tree (not for homicide!) that wraps around other trees. Its growth progressively surrounds the host tree, which withers away until all that is left are the fig vines around a hollow core.
Similarly we start removing a smelly line of code with a new clean one thoroughly tested. And then proceeding from there to create a new application that creeps on top of the previous one until it completely replaces the old one.
But even if we don’t complete it, the mix of new and old is much better than letting the old one rot. It is much safer than a complete rewrite because we will validate the new behavior continuously, and we can always roll back the latest version in case we introduced bugs.
Legacy code deserves a little love.
Learn faster. Dig deeper. See farther.
Join the O’Reilly online learning platform. Get a free trial today and find answers on the fly, or master something new and useful.
Uberto Barbini is a JVM and Kotlin independent consultant. Passionate about Code Quality and Functional Programming. Author, public speaker and OpenSource contributor.