Earlier quoted context omitted.
THIS: It's very much a novice mistake (one that I've made a dozen or so times, sigh) to think that you can jump straight to your "ideal" architecture without any of the steps or missteps along the way. Code evolves as the problem evolves and NEEDS to be adapted. Is impossible to foresee the future.
This approach generates regular expensive rewrites that a typically slightly more flexible and/ or modular solution would avoid. The key words are slightly. The trap is to overgeneralise or apply a technology or approach like a hammer without understanding its limitations. Out is impossible to foresee the future, but trivially easy to see current requirement and extrapolate a bit.
I can't count the number of times I've "trivially extrapolated a bit", showed my boss or VP, and then gotten back "actually, we don't want to put any more effort into X. I appreciate how you went above-and-beyond, but priorities have changed, and it turns out we really want Y instead," followed by much handwringing when I go back to the code and find out that the flexibility and modularity that I built into the system expecting we'd do more of X next actually impedes progress in making it do Y.
Lest you think this is just bad management - I work for myself now, on a startup, and I have the same problem (or would had I not beaten this habit out of myself). Very often, I'll think "Woah, there's a much more elegant approach that will let me do Y and Z much better at relatively low engineering cost", and then I'll finish X, and put it in front of potential users, and they'll say "Actually, we don't care about Y and Z at all...why would we want them? We want to do A and B instead", where A and B take the product in a completely different direction from Y and Z.
There is a place for planning a little bit ahead, but that place is to plan to reach the next milestone as quickly as possible. You should never try to guess what the milestone beyond that is without checking in with users or management.