Rewrite or refactor? How I decide
Rewrites are tempting because old code is annoying. You open a file, wince, and a quiet voice says "I'd do this so much better from scratch." Sometimes that voice is right. Often it isn't. This post is a heuristic I use to decide, a list of traps, and an example from my own work where not rewriting was the right call. Why rewrites seduce us You understand the problem better now than when you…
Rewrites can be tempting due to an old code base feeling outdated or clunky. A writer may feel they could do a better job from scratch. However, often this isn't the case. This article outlines a heuristic to decide whether to rewrite or refactor, outlines potential pitfalls, and shares a personal example where maintaining the existing code was the right choice.
Rewrites are seductive because they offer a clean slate. When reading old code, every flaw in the existing design seems glaring, while flaws in the proposed new design are unknown. Early progress feels fast, as the first 80% of a rewrite is often enjoyable. The risk is that the last 20% stalls, where edge cases present in the old code are lost and must be rediscovered through bug fixes.
In general, refactoring is recommended when the code works, has users, and the issues are concentrated in specific areas that can be addressed in small, working steps. Rewrite is suggested when the core design makes new features impossible, when a significant improvement in understanding the problem exists, and when the change can be completed quickly.
Before embarking on a rewrite, the author suggests writing down what the old design cannot do. This includes specific functionalities that are missing and why the new design would allow those functionalities. If these gaps can't be filled with concrete statements, it's likely a refactor rather than a rewrite.
Another approach is to copy the project and then refactor the copy. This allows a stable original to remain functional while changes are made to the copy. This method is useful when the original must continue running, when making ambitious changes without risk is desired, or when generalizing code for different cases.
A step-by-step replacement approach, known as the "strangler" pattern, is recommended for larger systems. This involves gradually replacing pieces with a thin seam in front of the old piece, building the new piece behind the seam, routing some traffic to it, growing the new piece, and then retiring the old piece. This allows for maintaining a working system throughout the process and provides a clear way to revert steps if necessary.
Before making a rewrite decision, it's important to ask key questions:
- What specific functionalities can the old design not do?
- How long would the rewrite actually take?
- What edge cases does the old code handle that would need to be rediscovered?
- Can I deliver value in the middle, or only at the end?
- Who depends on the current behavior?
- Am I rewriting because it's needed, or because I'm bored?
The author advises writing down specific aspects of the old design that can't be done. If this can't be done, it's a refactor. The scoring sheet provided helps in making the decision. Refactoring scores higher when the code works, issues are concentrated, small steps can be made, tests exist, and the team understands the current behavior.
Points toward rewriting include the core design blocking a needed feature, the technology being outdated, being able to state exactly what the old version can't do, and the scope being small enough to complete in days. If scores are close, a smaller change is recommended.
Overall, the key takeaway is that rewriting should be approached with caution, and refactoring should be favored when possible. Writing down specific issues with the old design and considering the potential scope and impact of the change are crucial steps in making an informed decision.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.