That depends on circumstances really. Yeah it's easy to fix dumb code... unless there's 10 tons of it
I once worked with about 1.5 million LOC worth of "naive" PHP code. It was one big e-commerce system. The SSOT principle wasn't followed, certain assumptions were scattered all over the place.
For example the fact that a product could only ever belong to a single size group. The task we were given was to remove this constraint. It took a few man-years of work, because it was hardcoded EVERYWHERE, from database scripts to frontend JS. And don't even get me started on how many bugs angry customers encountered before it got kind of stable.
It wasn't overengineered, just dumb, and a lot of it. I'd much prefer having to deal with some matryoshka OOP abstractions - they could be merged, simplified etc. In such case there are certain tricks in our disposal. Tricks that scale. If it's just a big ball of mud: not much you can do. It's pretty much a physical job, like counting grains of sand on the beach.
When you design a system, you always have a tradeoff between flexibility and simplicity. Extreme flexibility means over-engineering and complexity. Simplicity means less flexibility, because of a lot assumptions are hard-coded. The best design is the one which hits the sweet spot: As simple as possible, as flexible as necessary. That requires knowing the future, though.
If you want to increase flexibility later, like "remove the constraint that a product could only ever belong to a single size group", it inherently means to hunt down all the places where this assumption has been hard-coded.
Should you err on the side of flexibility or simplicity? Simplicity means the assumption hunt is costly, but maybe you never need it (YAGNI). Err for flexibility, you pay the constant cost of dealing with the API complexity, but you surely avoid some costly assumption hunts.
Usually, startup prefer simplicity because they will pivot anyways. In contrast, enterprise prefers flexibility, so they can plan years ahead and things stay in the budget.
> As simple as possible, as flexible as necessary. That requires knowing the future.
Knowing the future in this case should usually mean that you have requests for a feature from customers, but you don't have time to do it in this version. At least that is something I find useful as a rule of thumb. If that is not the case, you should really think twice before making it flexible rather than simple.
I was recently passed off a project from someone who didn't have a development background but had been working on C++... the amount of copy-paste, repetitive if statements and fixed length arrays makes the original code almost completely unusable and I was forced to suggest a total rewrite.
> If it's just a big ball of mud: not much you can do. It's pretty much a physical job, like counting grains of sand on the beach.
You can refactor as you go. It doesn't save you from sifting through the entire ball of mud, but at least it means you won't have to do it again in quite such a bad way.
I once worked with about 1.5 million LOC worth of "naive" PHP code. It was one big e-commerce system. The SSOT principle wasn't followed, certain assumptions were scattered all over the place.
For example the fact that a product could only ever belong to a single size group. The task we were given was to remove this constraint. It took a few man-years of work, because it was hardcoded EVERYWHERE, from database scripts to frontend JS. And don't even get me started on how many bugs angry customers encountered before it got kind of stable.
It wasn't overengineered, just dumb, and a lot of it. I'd much prefer having to deal with some matryoshka OOP abstractions - they could be merged, simplified etc. In such case there are certain tricks in our disposal. Tricks that scale. If it's just a big ball of mud: not much you can do. It's pretty much a physical job, like counting grains of sand on the beach.