Beware the allure of rewriting code

I was recently reading some code and there was a subroutine that felt about twice as long as it should have been.  As I pondered this subroutine, and wondered why nobody rewrote a shorter version of it, I remembered a great line from a Joel Spolsky article (Things You Should Never Do, Part I):

Back to that two page function. Yes, I know, it’s just a simple function to display a window, but it has grown little hairs and stuff on it and nobody knows why. Well, I’ll tell you why: those are bug fixes.

Those are bug fixes!  I first discovered this article over ten years ago, but as I progressed in my career this advice rang truer every day.  Some code may truly be unmaintainable, but the fact of the matter is that more bug fixes, more complexity,  and more edge cases are built into any system as it matures.

It takes patience to examine code in this careful way, rather than declaring a rewrite is necessary.  I used to think the desire to rewrite code was entirely tied to NIH (Not Invented Here), but Spolsky truly gets to the root of it.

We’re programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We’re not excited by incremental renovation: tinkering, improving, planting flower beds.

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.

None of this is meant to say that all code you inherit is perfect.  Quite the opposite, in fact.  After you take a fair stock of the pros in the inherited code, it’s completely reasonable to address the cons.  Refactoring is the best way to improve code while retaining its best characteristics.  This is made much easier when the code is covered by a high-quality automated test suite – I am so glad we have more of these now, compared to the bad old days before test automation was popular!

Spolsky addresses several forms of refactoring: for cosmetics, for performance, and architectural refactoring.  This advice was as true at its publication in 2000 as it is now.  The architectural advice has changed a bit – maybe you want to wrapper or refactor some code out to a microservice.  Refactoring a monolith to microservices is a much better approach than simply rewriting the monolith from scratch.

Lastly, consider that while you are rewriting code, you are probably not delivering value to your users.  Work in progress delivers no value – and a major rewrite causes major work-in-progress.

Software code can always be improved, and it’s rare that a complete rewrite is the way to improve it.  Consider the above advice before changing more than you need to.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.