1. It's much harder to read other people's code than to code yourself, so it's very easy to get put off by the apparent complexity of other people's work.
But you don't know why their work is like that. You don't know if their coding is actually good, you don't know what odd OS/browser/language version bugs are being fixed by the weirdness there, you can't see all the work that went into the program before... It can be misleading, and make you feel like you 'don't get it'.
2. Tutorials being very heavily slanted towards the beginner and expert ends of the spectrum. It's harder to go from intermediate to expert than from beginner to intermediate or learn more as an expert, because few tutorials are written for that level of expertise.
3. Similarly, figuring out why something may work the way it does on a fundamental level can be tricky. Tutorials often have a 'just trust us on this' attitude towards explaining tihngs, and don't really go into why different types of variables work, why loops work, why say Redux works the way it does, etc.
4. And I guess for some people, just the whole mindset can be difficult to get into. Programming is a very precision driven exercise, and for people used to the 'good enough' way that most of society works, that can feel jarring and awkward. It can feel like being the world's strictest dog trainer, with the computer or language or compiler or what not being a pooch that can't figure out what you want from it unless you teach it in the exact right way.
If you work in a large company like Google, then there's lots of code and design documents you can read and, moreover, many helpful colleagues you can ask for advice (and who will provide detailed comments on your design documents).
If you're working on your own, or in a smaller company, then you might do things in a suboptimal way for a very long time just because you didn't see someone do it a better way. You might re-invent the optimal solution, but that's not the usual case.
Another way to look at this problem: "it's difficult to avoid having 1 year of experience 10 times"
I frequently find myself in the second situation and only a handful of times have I been in the first situation.
1. Go to a local meetup group for your favourite language, take your laptop along, and show some folks what you've been working on. Show them what it does, and then walk them through the code. You can do this over beers. You will end up learning something either by explaining things to others, or by receiving questions and feedback from more experienced developers.
2. Ask a more experienced friend to meet you one weekend, for a couple of hours, to look at some of your code. Getting a code review from someone outside your normal environment will likely result in a few valuable tips.
3. Read books about architecture, like 'Web scalability for startup engineers' or books targeted at intermediate developers, like 'Powerful Python', and immediately go back to some past work to figure out where those patterns might be of use.
4. Ask any and all of your friends who are engineers about what they've been working on, what difficult problems they've had, and how they are working to solve them.
5. Read open source code. (This is a bit hard, as not all open source code is of high quality, and it's hard to know if it's good unless you're already a great developer.)
You learn a lot from other people by looking through their code, and you learn ways to improve your code by having people with more experience review your code.
Maybe find someone who is familiar with the language/application you are interested in and is willing to review your code.
But I think the hardest was the very first threshold I had to cross, when I first started taking legitimate CS courses. It had more to do with just the sheer ability to hold onto complex thoughts, data structures, algorithms, in my head.
I think a lot of engineers take this for granted, including myself. But I remember, just starting off, and realizing I felt like I was running out of working memory in my mind. It was almost like hitting a threshold where I really felt like I was stretching my mental ability to go through processes, run through algorithms, visualize concepts, etc. Eventually, as with anything, you get better and do these things faster and thinking about CS becomes second nature. But i specifically remember feeling like I reached my mental limits till I and enough practice to get good at thinking about CS and holding many things in my mind as I thought through algorithms.
Same goes for writing vs reading code. Maybe we teach and learn programming all wrong. For instance, when learning a natural language you dont read a manual on the grammar and then go off and try to write a novel looking up vocabulary along the way... There is absolutely no way you would be succesful with that approach, you would invent your own messed up version of the language that seems absolutely strange to everyone else. But that is sort of what we expect people to do when they learn to program.
It might be better to spend a year reading and dissecting good code of varying complexity in a debugger before you ever even write a line of code.
Realising that in x days/months/years your own code will be the legacy and viewed by other developers and yourself. Your code will represent your understanding at the point in time you write it. It's natural if it looks horrid or incomplete or bad or that you missed something obvious. Don't beat yourself up over it.
Look on any code with the understanding and compassion with which you would have the next developer look on your code.
That and making sure to get up, stretch regularly and look out the window and get out the building. Smell the roses. That sort of thing.
* Knowing my own knowledge gaps. I know there's a lot I don't know, but it can be difficult to pinpoint _what that is_ exactly because if I don't encounter it in a project I may not even see the gap until I _do_ encounter it one day. Supplementing with short structured courses like Pluralsight, Safari Books Online, etc has helped in this regard.
* Being confident that you're solving things in a good way. "This approach works, but is this really the best approach or is there some existing pattern or data structure I should be using for this that I just don't know about yet?"
Both of these things have become easier to address with time and practice.
Writing code is hard, but confidence and persistence will get you a lot closer.
For me personally, the hardest part was having the patience to actually manage to build something useful other than the sample toy programs that came with the textbook.
You need to have the patience to read tons of documentation, google for example code, ask questions on Stackoverflow when stuck, so on and so forth. Once you do this for a single project and get something useful built, it gets much easier :)
If you are language fluent then you can read the source code and know exactly what is going on, otherwise you are stuck trying to make sense of someone's hyped up abstraction of a basic programming design pattern.
I eventually got frustrated with books and courses and instead just visualized what I wanted the page/site to look like and do.
I then googled a lot of problems I was having ("How do I sort columns in an HTML table using JS") and then made code work.
For especially tricky problems, I would ask my friends how they would approach a problem.
a) things don't work b) it is hard to say why they don't work
Annecdotaly, from looking at my mom, a 50+ year old economist working on insurance backend platform, any sort of error would be hugely discouraging.
That's why people talk about it being "easy" to write a program that compiles and runs, but hard to write good code.
worrying you are doing something wrong - you probably are but remind yourself you just have to start somewhere. As you get it more you will learn of better ways to do stuff. There will be times when you paint yourself into a corner and have to redo just about everything, common even for experienced programmers.
Then I would say getting your brain trained to understand what you can do with a language, how the computer reacts to different program tasks, and how to write stuff so the user gets what they need.
probably consistency and dedication. there is so much to learn. so finding that area you love is the key.