@sixohsix I can quote the great Joel Spolsky on this one:
"When great thinkers think about problems, they start to see patterns. They look at the problem of people sending each other word-processor files, and then they look at the problem of people sending each other spreadsheets, and they realize that there's a general pattern: sending files. That's one level of abstraction already. Then they go up one more level: people send files, but web browsers also "send" requests for web pages. Those are both sending operations, so our clever thinker invents a new, higher, broader abstraction called messaging, but now it's getting really vague and nobody really knows what they're talking about any more.
And if you go too far up, abstraction-wise, you run out of oxygen. Sometimes smart thinkers just don't know when to stop, and they create these absurd, all-encompassing, high-level pictures of the universe that are all good and fine, but don't actually mean anything at all. "
I believe one way to fix this is to do the simplest things that could possibly work (as in a MVP) + TDD and trying to avoid what I call premature abstraction (the root of all evil just like its optimization cousin).
From what I have observed, you don't lose the hang of things because of the abstraction, but because you're not able to map the abstraction into the world anymore. When the abstraction is born out of experience, you already have the means of mapping it into world properly. You start having some personal guidelines (a sort of reliable one for me is what I call the rule of 3: if it's duplicated > 3 times, it's time to put it in a function or abstract it somehow) and know what works and what doesn't. Too many beginners see things like MVC or whatever the hottest thing is in JS and don't think about why that abstraction is the way that it is and we end up with lasagna code. Try everything and get nowhere.