The increase in the complexity of systems is relentless, oppressive and ultimately crippling. For me as an older generation programmer, it is also bitterly disappointing.
I've been programming for well over 40 years, having written code in 50-100 different languages or dialects, and become expert in 5-10. The reason I can claim so many is that mostly they're just the same language, with tweaks. The tweaks add complexity, making every language just a little different.
I have implemented the same algorithms innumerable times: collections, conversions, sort and search, encode/decode, format/parse, buffers and strings, arithmetic, memory, I/O. Every new implementation adds complexity, because every one is just a little different.
I wonder at the magic wrought by the high flying trapeze artists of the web frameworks and mobile apps, at how they can produce something so beautiful in such a short time. Then I realise how much they don't know, how much they will need to learn about data or communications or testing or threads or whatever before what they do becomes useful.
I learnt my craft in the era of fourth generation languages, where we genuinely believed that we would produce a succession of higher and higher level languages to progressively capture more and more of the repetitive parts of writing software. So how did that turn out, exactly?
Microsoft and IBM killed that idea by returning to C for writing apps for Windows and OS/2, while dBase/Foxpro and even Delphi languished. Then the web did it again with its ultimate trio of assembly languages: HTML, CSS and JavaScript/DOM. It's been all downhill from there. Always more languages and more libraries and more frameworks and more complexity.
We know we should be doing it differently. We know about CoffeeScript and Dart, about Less and Sass, about template to avoid having to write HTML. We know and we do it anyway. We have our frameworks, full of leaky abstractions, and we see what wonders can be done by those chosen few who learn the arcane incantations, but we and our programs are trapped by the decisions made in the past. It's too complicated to change or start over.
The result is that things that ought to be easy are not easy, and things that ought to be possible are nearly impossible, because of complexity. I can estimate the cost of making changes to implement a new feature in an established code base and be confident I'll be about right. I can estimate, but I can't justify it or explain it. It's too complicated.
In answer to your final question, I would strongly advise younger programmers to start as high on the layer cake as they possibly can, and only dive down to the lower layers as the need and desire provide the impetus. My preference is for languages with no loops, little or no branching and explicit state. Lisp and Haskell come to mind. In practice I always finish up with C#/Java, Ruby, Javascript, Python and SQL because that's where the communities are.
Final words: complexity is the ultimate enemy! Beat that and life becomes simple.