Code that's not well compartmentalized and is full of complex dependency chains and flawed abstractions is hard to work in, and more importantly to the topic at hand: extremely hard to refactor well.
Once the abstractions are shuffled to their own "corners" of the codebase, and you've got well defined modules/services/microservices/foobars... you'll find refactoring to be far less of an investment. It also becomes far less attractive, as a well abstracted module is easy to ignore and forget about.
Of course, it's always best to make these things right the first time. Whenever I kick off a greenfield project, my first code-style objective is to make things easy to delete/remove.
Addendum: I find the worst spaghetti code comes from very dynamically typed languages. All the "easy" coding makes skipping interfaces/abstractions effortless, thus nothing's "doing just one thing well" and it snowballs from there. On the flip-side, when done right, it's quite a joy to write delete-able code in Python, and it makes prototyping and defining boundaries a breeze.