The idea is that you can’t always fully refactor some sprawling hairy thorniness all at once. Instead, try shepherding it into one part of the code you can put a fence around. Blackbox everything inside the fence – everything outside the black box is nicely refactored and only inside are things done the old gross way. Later, you can replace that black box with a white box that does things the new non-gross way.
@DRMacIver had this to add:
What I like to do is a mix of refactoring to modularity by taking terrible things and moving them into a relatively well defined interface where I don’t have to care about the internals, and then once I’ve got relatively well defined interfaces I can think about replacing what lies behind them […]
One nice feature of this is that you get continual improvement and can deploy it in stages, so you don’t have to deal with changing all the things at once. You can also mix and match – if you’ve done some rewriting, you now have more flexibility to add features even if you haven’t finished, because the code has got easier to work with.
In summary (mostly thanks to @kenoubi again):
- From-scratch rewrites are bad, because even a bad code base encapsulates a huge amount of knowledge you’ll be forced to rediscover the hard way.
- Isolating bad components and then replacing them (“wrap-and-scrap”) is better.
- Sometimes wrap-and-don’t-scrap is ok: if it’s small and stable you can leave it as a bit of sealed evil in a can, as @drmaciver puts it.
We recently talked about this a bit more in the tech-nerd channel of the community Discord (called the apiary, btw) and multiple people (@narthur, @larsivi, @rperce, @lanthala) concurred that this is all wise and good and correct and definitely wants a handy concept handle.