"This code is terrible, we have to start over"

“I’ve been involved with dozens of software upgrade projects over the years, both in my cubicle days and later as a cartoonist and entrepreneur. And one thing you can always count on is that whoever is hired to work on the new version of the software will call the person who worked on the last version an idiot.” — Scott Adams

If you’ve ever tried to replace a software developer or small team, you’ve almost certainly experienced this. The previous developers probably weren’t terrible at their job, but they were likely facing constraints that are now invisible. 

A codebase is a reflection of not only the people that created it but of the structure of the organization that created it (Conway’s law), shifting constraints (time/budget/specific needs) faced throughout the lifecycle of the codebase, and of the path that the business requirements took to get to where they are today. Many of these things are visible on the surface of a codebase, but where they belong is in the version history, hidden just behind one or more “refactor” commits that clarify the story of what the application should be doing today.

One crucial-yet-rare skill needed to prevent a codebase spiraling into “legacy” status is developer empathy, a concept whose name I learned from the wonderful folks at the Turing Academy. They teach a whole class on this, and it is one of the (many) reasons they turn out such great developers. The basic idea is that you can learn more about the organizational structure and constraints directly from the code if you can withhold judging the author.

That “ugly” code was “pretty” once, but then someone fixed the bugs in it. When software interacts with the real world, you discover edge-cases: exceptions to rules, scenarios that come up infrequently, etc. Advocates of “test driven development” have a mantra of “red, green, refactor.” That breaks down into failing test, passing test, re-organize the code to succinctly state what’s happening. 

When you have a culture of refactoring, it will also happen on a larger scale: when a feature is, augmented or changed, it becomes harder to read for new members of your team. When time and budget constraints rear their head, the refactor step is almost always skipped. But as Uncle Bob says: “The only way to go fast is to go well.”

The solution to your velocity problems may be the same as the solution to your reliability problems. Before you act on the advice to “throw it out and start over,” be sure someone has actually read the code and can describe every wart and hair they want to throw in the trash. I say this from experience: if you try to use old software as a spec for new software without digesting it into a well-crafted description of goals, you’ll be lucky to ship anything at all.

I’ll end with an excerpt of an article you should read:

“There’s a subtle reason that programmers always want to throw away the code and start over. The reason is that they think the old code is a mess. And here is the interesting observation: they are probably wrong. The reason that they think the old code is a mess is because of a cardinal, fundamental law of programming:

It’s harder to read code than to write it.” — Joel Spolsky, Things You Should Never Do, Part I