Even thought this is basically the most common thing everybody tells you when you are growing up, I've seen that most people still don't internalize it and when they start learning something new, their first instinct is to grab a bunch of tutorials and books and that's it. This post is mostly aimed at the software development engineers who I've seen too many times to get lost in the Tutorial Hell and spend too much time and effort "learning".
So, what's the actual problem? I have not problem with going to some tutorials when you are learning a new technology or starting a tech career altogether. But tutorials will only get you so far. Will teach you a very limite set of instructions that are not going to be relevant in real-life scenarios.
Building an application from scratch involves a lot of moving parts that are usually not covered in tutorials. The tutorials only scratch the surface.
The Tutorial Hell is the trap I've seen a lot of beginners fall into. At first, they have no idea what to learn, because to become a software developer you need to have knowledge on a lot of subjects.
So they google "random programming language tutorial" to get started with something. And they pick up some tutorials that teach them the basics. Then they search more tutorials. They do them, they feel a rush of dopamine by completing each one, feel smarted and feel the progress.
But after some tutorials, the actual learning stops, but they keep looking up tutorials, buying them from different learning platforms, and fall into this continuous circle of completing one tutorial after another.
This is the Tutorial Hell. A psychological trap newbies tend to fall into, where they learn the same thing again and again from tutorials, unaware that the actual growth is missing. The same concepts are reiterated in different formats, offering the illusion of progress.
Tutorials are not enough. They are good enough to get you started and build something very specific the tutor wants, giving you an explicit list of steps you follow blindly. At the end you have finished the lesson and built something your tutor wanted you to build. But in reality, you haven't really built anything on your own.
To break free, what would be the next steps? In my opinion, software engineering is much more than writing code. Sure, writing code as a career is a good enough choice for many, but the growth stops after a while if that's all you know to do.
Software development is about building solutions to problems, analyzing said problems, breaking them up into steps, build algorithms that gives the desired results, and ship something usable.
This is a tricky part because it's a matter of opinion. Opinions differ from person to person based on their personal experiences, and occasional disagreements might occur based on whether math is useful or not.
In my opinion, a software engineer that is successful what they do should have approximate knowledge on most fields that are related to a computer, in order to see and understand the big picture and work their way around it.
The areas that are the most crucial are:
Math - yeah, a somewhat unpopular opinion, but I consider math being a crucial part of software development. Not because the formulas and calculus might help you build web apps, but the critical and structural thinking you develop my doing math is crucial in how you approach problems. In a way, math is all about tackling bigger problems, splitting in smaller more approachable problems and combining the results. Basically inventing, following and combining algorithms.
How can you learn it?
Well, the answer might not surprise you: do math problems. Remember all those math homeworks you didn't do or tried to weasel your way out of doing them? All of them would have contributed to building your algorithmic thinking when your mind was set on learning-mode most of the time. It still should be, but now your time and energy is more limited.
The hardest thing to accept about software engineering is that you actually have to enjoy math to some degree to be successful at your job, or just to be passionate about problem-solving. If not, software engineering is probably not the best career choice, and you'll end up either burning out or just hating your job.
Low level programming - basically knowing your way around C/C++, what is compilation, memory management, file descriptor management, even some knowledge of Assembly would be useful. Having some knowledge on this would definitely help you debug and identify issues with the code you are building, when you see them. For example, a memory leak would be hard to fix if you don't know what to look for. If you have some knowledge of low level programming, you'll know that you have to look around for un-freed memory, stale references that prevent some data structures to be deleted from memory or unclosed file descriptors.
How can you learn it?
Actual studying and building small programs in C/C++. Having to deal with the real case scenarios of allocatinng memory and watching out for illegal memory access and working with pointers will definitely teach you a lot. Diving a little into Assembly might be worthwhile because you would see the code that the processor sees, and not the code you write, and you'll ultimately understand that everything you write becomes a bunch of lame instructions for the processor (such as moving data around, managing the execution pointer, and pushing and popping things from a stack all the time).
Operating systems - since every piece of code runs on an operating system and every moment you spend on a computer you are basically using an operating system, it's crucial to know what you deal with. How do disks, files, directories work? What's an user, what does it mean when a program suddenly closes, what does it mean when suddenly the fan starts blowing hot air and making a lot of noise? Where would you look to gather more information?
How can you learn it?
Here it gets a little trickier. There is no correct way to tackle, it, but there are some choices that
will certainly make it easier for you. The most impactful way to learn about Operating Systems is to get on Linux,
and start implementing in C the basic commands you find in Linux:
Reinventing wheels is the next best learning experience to building something original.
Networking - although a hard topic, knowing how processes communicate is crucial in the current software development climate. The age of a singular app on a single server is over, and the age of cloud computing is here. You'll need to know how these moving pieces fit together and most importantly, how do they communicate with each other? I've often been asked how do I know the router's address by memory, even if it is brand new? Networking. A lot of errors you will get in a software project are related to networking, such as connections being closed all the time, timing out, being refused, figuring out what configuration is needed for a database connection to work, etc. All that lie in the networking space.
How can you learn it?
The short answer is the same as the one from the operating systems bullet point. Build some clients for popular open source applications, such as databases, email servers, even SSH if you feel adventurous. It will provide a great learning experience.
Design patterns - it's a topic that you don't really need to study for, because you'll gradually learn it from building and as you get more and more experience. The most powerful way to learn such things is to build something the wrong way, using absolutely no design pattern, and then refactoring (or re-building from scratch) to integrate them. Seeing a firsthand example on how they help your code become more manageable will guarantee a deep understanding of the "why". And that's the most important thing: to figure out why you use certain design patterns, and recognize the problems they solve, so that you can get the "feel" of the problem before it actually becomes a problem.
How can you learn them?
By experience and with patience. You will make mistakes. Everybody does. And it's fine. The code doesn't have to be perfect from iteration one. An application/project is never finished and its codebase changes continuously. Each change should strive to either add features, or reduce technical debt.
Another way to learn design patterns is by using frameworks and exploring open-source code: they already incorporate good practices and design patterns, and it will be useful to experience the advantages and drawbacks of those design patterns in the wild.
See how programming languages are not in this list? I don't consider knowing a particular programming language to be a crucial skill for a software developer. After all, programming languages are tools we use to resolve a problem, and tools can be switched. Sure, over time we will become more proficient with one tool than others, and will prefer using a particular language most of the time and build a career on it, but it shouldn't be the thing to define your career. Eventually you'll need to grow out of it and see languages as mere tools, the actual challenge being the whole application. Great things can be built with any language (even PHP).
Back to the original idea: learn by doing. It's important to build something from scratch to experience the full set of problems and challenges that will appear in a real-life system. When you work in the software development industry, you work on real applications/systems that resolve real problems.
Learning only omn the job has some very big disadvantages: the learning rate and the flexibility to explore solutions are very limited, as there are real stakes in play, people will oversee your work, you will be limited only to the scope of some ticket, bigger refactoring sessions will need a lot of planning and will be split between multiple people, so the knowledge gaining is also split.
To really sky-rocket your software development skills, you should have some personal projects you are passionate about. You should build something outside the work hours, and use it a as a playing field where any mistake is allowed and is risk-free. The only resource you need to put in is time, and instead of surfing social media, you could invest at least an hour a day in building your projects.
At first, it will be tedious and there is where most people give up and pick up doing tutorials: you start with nothing, and you need to figure out what the steps are.
So, let's say you want to build a Twitter clone. What are you supposed to start with? Users? Tweets? Mentions?
It's a hard decision, but it's surely the kind of decision that needs to be taken at the start of any project. In corporate environments, there is a whole process dedicated to this, and takes a lot of time and manpower.
But as a solo developer, it's fine to just dive head in at first and figure things as they go. Mistakes create learning opportunities.
For example, I am currently building Amethyst Platform and I restarted the project five times. Each time, I started from a place where I knew more than before, and eventually, with each iteration, there will be more progress.
Building personal pet projects gives you space to experiment with anything: new technologies, new techniques, new design patterns, new frameworks, new approaches.
My advice to any software developer that wants to keep their careers on an upward trajectory is to embrace the vastness of the software development industry and focus on building personal projects.
By building our own things, we acquire new skills, we are able to experiment and make a lot of mistakes risk-free and without the pressure of the boss and deadlines.
To understand the bigger pictures, it is necessary to have a grasp of the building blocks of the internet, from the machines that run our code, the way the data moves around the world to the architecture and structure of our code, so we navigate it easier.