We’ve all been there. One of the main systems has grown and evolved over many years and due to a series of rubbish programmers who’ve all moved on to do their damage elsewhere, and incredible time pressure to get stuff delivered, the codebase has become more and more difficult to work with.
There are very few tests, and the ones that are there are flakey as anything. Code is copy and pasted freely all around, hurting your eyes as your IDE moans about duplicated fragments. Things are so bad that you can’t even start the monster locally, which means for every change you have to go through an arduous deployment cycle, which leaves you with an awful lot of time to catch up on the news and sport whilst things compile and deploy.
Eventually you’ve had enough and the time comes to escalate. This a key piece of system infrastructure! With these outrageous feedback cycle times it’s going to take forever to get any features implemented, there’s a lot of risk something else will break every time as there are no tests, and you’re in tears at the sheer complexity of the code as even simple tasks are spread over 10 different classes, each of which is almost 1000 lines long and have no concept of the word cohesion.
So the crunch comes — do we rewrite the thing from scratch or spend some time fixing it up?
I’ve yet to meet a developer yet who wouldn’t want to rewrite it. We love rewrites! We get a fresh codebase to play with, unencumbered by those who came before who clearly had no idea how to write code. Think how fast we’ll produce the new system! And how easy it will be to understand.
The problem is, the moment you start writing code, it becomes legacy. Although there are undoubtably some bad apples out there, most developers aren’t bad, and they all go out to write good code. But then time pressure happens, and deadlines, and badly specced out requirements, and hangovers, and suddenly the team size gets doubled to get things done faster, and the codebase goes downhill rapidly.
Despite all your best intentions, the same thing is almost certainly going to happen to your rewritten system, no matter how good a programmer you and your team are.
Worse than that, no matter how brilliant your new system is, it will be functionally inferior to the old one. If your system is say 5 years old, that’s 5 years of ingrained knowledge — bug fixes and requirements and nuances which now only exist in the current code base. No matter how much you try you will miss idiosyncrasies and your business will have to suffer groundhog day as you create new bugs that were fixed in the old system 3 years earlier.
Although there are certainly valid times to rewrite a system (perhaps to move away from a dead or dying programming language), the vast majority of the time you are much better grabbing a copy of “Dealing with legacy code” and going on a full frontal assault of your existing code base. Write tests, refactor, repeat. You’ll still miss things (no one’s perfect), and it will be nowhere near as much fun as a greenfield system, but the end result will be a much better solution for your end users and will come at a much cheap time cost.