Mastering something is hard. No one said the journey was going to be easy, and it most likely won't be. But that doesn't mean you should give up. I have solid work experience, with 3 internships and coming up on 2 and a half years of full time work. And while all of that has been helpful, it has been the journey in between all of that that has made the difference.
"In fact, by the age of twenty, the elite performers (violinists) had each totaled ten thousand hours of practice."
Malcolm Gladwell, author of Outliers, said it takes 10,000 hours to master something. To put it simply, you need to put in the time to get to the next level, and the next, and the next. I wouldn't say 10,000 hours is a hard and fast number, but I do agree that it takes time to achieve the senior level and beyond of software engineering. I'd also say that you can't put a number on it either. My take on it is more that you should practice, as opposed to a hard and fast number. The more you practice, the better you will get. And while practice is important, it is more than just that. One question I always ask is "Why do you want to be an engineer?". Make sure you can answer that, because besides practice, you have to want to do it too. I won't preach the "You will never work a day in your life", but you should enjoy what you do. And the other part is to find someone to be your mentor. This person should be someone who can guide you in your practice, and can steer you in the right direction if you are going off course.
During my internships and school, I became fascinated with coding, so I made it my mission to learn all I could about it. Coming from an Electrical Engineering background, I didn't have the theory part of Computer Science, so I took the "let's just build things" route. I started writing code, and with every iteration I improved upon it. From my experience, as an engineer our job is to build things. So build something. It doesn't have to be the next Google, and you don't have to be the next Linus Torvalds, but build something. It could be something as simple as the ever persistent Todo app, whose tutorial is rewritten everywhere and in every language.
The first thing I built was a comic managing site. I love to collect Star Wars comics, so I built a site to track everything. That V1, looking back, was terrible. It was written in PHP, and used the LAMP stack. There is nothing wrong with either of those things, but it was my code that ended up being written badly because I was at hour 0 of my mastery. Over the next year, I learned about Angular, and MongoDB. I felt it was time to rebuild my comic site into something better, so I rewrote into V2, this time using the MEAN stack. It was better. The code was cleaner. Between those 2 versions, I learned a lot. I learned about SQL, and NoSQL, simple HTML with Bootstrap and a now full fledged front-end framework, and of course NodeJS and Typescript. And then V3 happened 4 years after V1. I switched Mongo for Postgres because it fit the data better, kept Angular and now used the redux pattern for state management. I still used JWT's, but they were now signed with an RSA key instead of a secret, making the tokens more secure. Everything is written in Typescript, because typing simply makes it easier to find bugs before they happen. The entire application is containerized and deployed with Docker, making it easy to run on my MacBook all the way to the production server on DigitalOcean.
That last bit got beefy, but I wanted to show the progression. In the beginning I chose PHP because that's just what I chose to start with. By V3, I was making conscious decisions while building the application. I was able to put reason behind my choices. And the only difference between V1 and V3? Time. I simply had more knowledge when I wrote V3 than when I wrote V1. Work code is great, because you learn how to work in an environment with others, and the processes involved with all of that. But your fun code is where you will learn the most.
We're engineers, we are meant to explore and learn and build. So use your time to build, and explore. Mess things up, break things. Make a choice, and figure out why or why not that's a good way to do something. Make that todo app. Make it again, but add more security, a database, or a cool feature like color-coded todos. It wasn't easy, and it will never be easy. I still have plenty of days where I bang my head against the wall because it doesn't work. But those moments have been reduced. And don't forget to step back sometimes. Sleep on the problem, but never give up, and never stop building.