I'm of a similar mind but tend towards avoiding rewrites, mostly because I find refactoring more efficient.Interesting choice of phrase. What would you say is the difference between refactoring and rewriting, assuming we’re talking about keeping the externally observable behaviour of the affected part of the system the same in each case?
This shouldn't be happening in a sufficiently tested or sufficiently understood system
Perhaps, but as systems and the teams that develop them evolve over time, it is all but inevitable that some knowledge and understanding are lost. You’ll never have perfect documentation. You’ll never have tests for every possible case. You’ll never have an unambiguous and readily located comment for every subtle detail in the code that someone seven years ago spent a couple of hours thinking about before they put finger to keyboard, when three other people have since refactored that code, generalised its interface, and fixed a performance glitch in a dependency so some aspects of the original design became unnecessary. Preserving knowledge and understanding as well as possible is one of the challenges facing any team with a long-lived system.
Those losses are a form of technical debt, and as it accumulates, two things happen. First, the original code becomes harder to maintain and develop. Second, the original code becomes more risky to rewrite. So unfortunately, there’s a fairly high probability in practice that a part of a system that has become sufficiently difficult that a large-scale rewrite is being considered will also be a part of the system where the current development team have incomplete understanding of the current implementation.
If you can't figure out a peicemeal way to refactor what you have into what you want you want, you have no business discussing what a rewrite should entail.
But how do you do a piecemeal refactoring exercise if, say, you’re moving to a new programming language? I had to rewrite a large part of a relatively complicated web UI a few years ago, like for like. Although it had been working reasonably well to that point and the design was quite clean and had stood the test of time, it was built around a Java applet. That design made sense when we were first implementing that system, at a time when JS was slow and many features we take for granted in browsers today weren’t yet widely supported. It was less helpful when the great and the good of the browser world decided that Java applets were a liability and they were going to make them harder and harder to use until eventually they killed them off completely. Now, we did have a clean, careful interface between the applet and the various other parts of the page that were written in JS, so we only had to redo that part of the system. However, we had no choice but to reimplement everything the applet did, using alternatives like JS and SVG, starting from scratch. This is the sort of scenario I was talking about before when I mentioned changes in the foundations of a system.