Earlier quoted context omitted.
In my own experience, it's really a must to go through both over- and under-engineering phase yourself: only then I found I got a really clear view on what's good and bad in approach, allowing me to default to somewhere in between (with outliers when useful) and in any case with focus on simplicity (but again, if needed for e.g. performance that can be violated). All of this is the basic 'learn from your mistakes' pr…
I never went through the over-engineer phase personally. I am a very very lazy person, which leads to me to correct balance most of times: Not enough abstraction, I suffer because of too much change to the code base, too much abstraction, and I feel pissed about my risk management. Since I suffer greatly when I suffer, I avoid suffering in my own code as much as possible. What also helps is that I plan most of my alg…
Interesting, so it's not a phase for you, but for the rest it sounds exactly like my point, i.e. learning that over-engineering (too much abstraction) is a mistake and as such trying to avoid it.