I would also like to add one more thing: hesitation. From my own experience, in my programming career, the most time my team wasted was on redoing something from scratch. Why redo it? Because the previous design was not comprehensive enough to meet subsequent requirements. If everyone could spend more time researching and discussing the plan before starting, and get things right in one go, in my view, this is much mo…
YAGNI.
Hesitation to avoid unnecessary work, sure. But not to anticipate future requirements.
The number of times I've had to fight a fancy design that left expansion points / abstractions for future features that were never needed (or not in the form the designers expected) enormously outnumber the times any such thing was useful.
Just make the code do its current job in the simplest way possible. That's the easiest design to expand later.