There are many good reasons to rewrite a legacy application, but most of the time, the cost outweighs the benefits. In this article, I try to balance the pros and cons of rewriting applications from scratch and articulate why it is almost always a bad idea.
Many developers, including myself, can live with a legacy application for only so long before they want to kill it, burn it with fire, and rebuild it from the ground up. The code is so hard to follow and understand, methods a hundred lines long, unused variables, conditionals conditioning conditionals on the different levels; it’s so terrible, Sandi’s squint test would make you dizzy.
Why rewrites are so alluring
You get to use the newest and shiniest tools.
It’s hard not to wish for a rewrite when you see places you could improve in many ways by just using a new best practice, framework, or package. Why would you stay back in time struggling to do great work with shovels and hammers and other medieval tools when today you have access to all kinds of well tested and battle-proven tools?
You have all the facts
“We have access to the current application, we can see all how the previous developers went wrong, and the clients themselves have more experience and know what works and what doesn’t and what they actually need. Rewriting the app will be a piece of cake done in a heartbeat!”
Easier to write tests
Most legacy applications subject to a rewrite don’t have tests. Adding them now is hard. Not only are there countless dependencies and execution paths to follow, often you don’t even know what to test! You’re left playing the detective, carefully following every method trying to guess what it supposed to do. When you start from scratch, you get to test your own code, which is a million times easier.
Why rewrites are a bad idea
Rewrites are expensive
The application won’t rewrite itself. You have to pour hours and hours into getting it to the point where, well, it does pretty much what it was doing before, maybe a little bit better.
One would make a good argument by saying, “you’ll be losing the same or even more time and money by not rewriting it, due to the inability to ship features as fast.”
That is true. Holding a legacy codebase together, fixing bugs, and shipping new features at the same time is no walk in the park. You can’t be rolling out feature after feature like you used to. But at least it’s not impossible; which is the second point:
You can’t put out new features
When you go on a rewrite, you are unable to release anything new for months. Depending on the nature of the business, responding to users and shipping new features might be critical. Your client might not even be in business by the end of the rewrite.
No, you don’t really have all the facts
After years and years of changes, no one knows precisely how the app reacts in every situation, not even your clients. Go ahead, ask them. They might have a general idea of how the app works and what it does, but there are still many unknowns that can only be uncovered by looking at the current codebase. Go into a full rewrite unprepared, and you will waste hours and hours on client communication and dead ends.
You risk damaging your relationship with your client
Let’s say you get your client to accept all the costs of the rewrite. You promise them, in the end, all of this will be worth it. The app will be faster, bug-free, better designed, and easier to extend.
If there’s one thing we know about software development is that at some point, something somewhere will go wrong: the server, the database, a misconfigured service, some innocent update. No matter how much you plan, something somewhere will go wrong. It’s like a law of nature.
When that happens, your client will start questioning his decision to rewrite. Even though the new application is 10x better, they don’t know that. They don’t care if you are using the latest and greatest tools, best practices, frameworks, and packages. All they know is they agreed to spend a ton of money and precious time on something that looks and functions quite the same. Every hiccup you go through will damage the relationship you have with your client.
When you should consider a rewrite
Apart from the case in which the application is small and straightforward, and you can rewrite it from scratch in just a few months, there are two more situations when complete rewriting the application can be a great idea:
When shipping new features is not a priority
When business is steady, with most work revolving around customer support and a few bugs here and there. If there’s no time pressure and you want to do a rewrite for performance reasons and maybe to stay up to date with the latest technologies. A rewrite will put you in a good place in case you need to shift gears and change direction towards something else.
When trying a different approach
The business has been great, the clients are happy, and the current application is well tested and crafted, but it has gotten a bit old, and you want to try a fresh approach to attract new customers.
Basecamp is the best example. Every few years, they completely rewrite and launch a new version of their product. New customers are coming in for the shiny new approach, while the old ones are given the choice to upgrade or to stick with their current version. Everyone is happy.
Having to work on legacy codebases sucks. You are terrified when clients ask you to add a new feature. You feel like you can’t touch anything without breaking something else in some obscure corner of the codebase. The only reasonable solution you see is to give up and rewrite the whole application — anything to make the madness stop. Hell, sometimes you feel you’d be willing to do it in your own spare time.
But sadly, rewriting is rarely a good idea. There are too many unknowns, you have to put a hold on launching new features, you risk damaging your relationship with your clients, and the time and money invested might never be earned back.
Refactoring, on the other hand, might be just enough to save you.