I've often seen opinions to the effect that a program should never be entirely rewritten, supposedly because this won't work, and will merely be a waste of time; this is wrong, the opposite being true.
All of the dramatic improvements in all of my programming have resulted from finishing a program, to then observe those issues, flaws, difficulties, mismatches, and other such things that resulted from it, and to then entirely rewrite the program from naught, and taking all of this into account. That primary exception to this I've noticed is minor revising done to a recently rewritten program, which can still result in heavy improvements equivalent to the rewriting, but this isn't possible without.
It's not good enough that a program should work perfectly. It should work perfectly, and also well.
There are many adjustments which can and should be made to a program before entirely rewriting, such as adding features to see compatibility, along with noticing and adding new abstractions or routines found to be useful or that result in better code. Mulling over how to do it again as if it were the first time is effectively effortless, and it's certain there should be a healthy interim beforehand.
Working to rewrite code until it's in an idealized state encourages writing libraries, and this is a good method to avoid a redesign from becoming too arduous and long; I'm not including such libraries in my refining advice. Importantly, interfaces should, ideally, be given such forethought that they don't need to modified in any reasonably observable way, allowing any implementations to be ignored. It's certain rewriting follows priorities, and a library written well enough may be best left alone.
Avoiding rewriting encourages the slow accretion of functionality, resulting in an unfortunate mess, likely only truly using an unfortunate intersection. It also encourages complications. It's rather easy to accumulate complications when they're constantly shoved aside; rewriting and redesigning may help avoid this. Several terrible programs and standards have resulted from not wanting to discard.
It's not surprising how all of the disgusting systems still in use can trace histories back decades; if there be no need to actually understand everything, it encourages people who are incapable in any case to only add, never questioning. This is reflected by tools which encourage thinking of changes solely in terms of additions and deletions, as opposed to a whole; it's obscene to consider millions of lines of code maintained in this way, over decades; I liken this to observing a monolith closely.
Software can reach a state where it becomes crystalline and mathematical, and so needs no changes to remain forever useful. Most software never reaches this state, but a nice second place is rewritten software which has merely not been rewritten again, not yet crystalline, but certainly near to this.
It's common to compare software to architecture, and the current mess of the world results from that ability to seamlessly build over previous structures, unending, whereas physical architecture can't. Following the analogy, it should be more common to demolish and rebuild anew, as the cost is nowhere close to that for physical. Of course, this analogy isn't usually taken so far, being inconvenient.
That advice against rewriting tends to only concern itself with business matters, which is sensible, when it's realized businesses aren't in any way concerned by building working software, similarly to how a business mass-producing food isn't concerned with edibility or nutrition. This advice I share is for human beings, and also intended to regard software not built on a tower of unending nonsense.
It's very comforting to rewrite in a way which preserves a general high-level overview, this leaving the programmer able to more mindlessly implement piecemeal, which is a heavy aid. If such a program becomes smaller and more comprehensible with each rewriting, it will only become easier to redesign.
For these reasons and more, I'm convinced that rewriting, refining, and redesigning a program may be the only means for heavy and significant progress, and only becomes ever easier when done correctly.