1. Buy SICP and put it on your book shelf.
2. Don't read it, instead read random StackOverflow posts talking about the content.
3. Spend the next 10-50 years trying to understand what people are talking about on various related forums.
4. Add more legendary books to your shelf over these 10 years, like The Art of Computer Programming. Fawn over their greatness. DON'T READ THEM.
5. Go on long walks, take spirit journeys to harsh natural locations, put your life in danger while you meditate on the concepts.
6. Blog profusely about your experiences.
7. Optional: actually write code.
Data structures are how programmers describe reality in the Wittgenstein/Sapir-Whorf sense and they shape our understanding as much as we use them to encode it. The right data structures drastically simplify problems and the wrong data structures turn them into nightmares of bugs and spaghetti code. Database schemas are the natural extension of this at the application, rather than module, level.
I don't have a specific recommendation because data structures is such a broad field, but an MIT OCW data structures and algorithms course is a good place to start. Oh and the book Designing Data Intensive Applications for a higher level overview of how data structures and algorithms are used in the field.
- Structure and Interpretation of Computer Programs
- How to Design Programs (easier)
In reality, it strong depends on your specific domain and how old your company is. Doing embedded projects at home vs. quickly prototyping systems in Ruby vs. modifying an API for a large SaaS vs. lowering latency for trading vs. ensuring compliance at a bank... The demands are all very different, yet generally we don't write algorithms or implement data structures too often. Our languages and libraries typically offer optimized versions, we just have to know when and why to use them. And after it's built, adding extra features won't change that model.The way everyone actually learns is by doing many projects, like an apprentice of old. Such a book could interest you (after) though: https://aosabook.org/en/index.html#500lines
You'll be forced to learn new approaches, new tools, perhaps even new languages to solve these problems if they're challenging enough, and don't worry, you'll almost always assume something is easy when it turns out to be a lot harder than you could ever imagine.
Get exceedingly good at breaking down difficult problems into smaller steps you can actually achieve. Try and estimate how much time these steps will take so over time you can get better at estimating how much work is involved in something, which can inform which approach to take or which tool to use.
Above all else, when you learn something and want to know more, learn both in terms of deeper fundamentals, but also in a more strategic sense, like how it is applied, and what are the ramifications of this knowledge, how it fits into the bigger picture.
Remember, it's abstractions all the way down, but also all the way up!
That could mean web applications deployed online, or CLI tools that people can install, or data science projects that result in a report you can show people, or mobile apps shipped to an App Store.
The key thing is to build actual working software, and ideally to get that to a place where other people can try it out. This will help you learn SO much, and will make it a whole lot easier to attract the attention of hiring managers as well.
You'll find you will rarely need to ask that question, just keep solving problems and learning what you need to know for that problem. You'll build good experience and though that experience you'll learn a lot.
1. Genuine interest
2. Ability to focus/concentrate and overcome frustration (there will be plenty)
3. Understanding of the basics: conditionals, iteration, functions and function calls, variables, basic input/output in any form. I would add on memory/pointers here, as understanding it will greatly improve your comprehension of what's going on even if you use a language that attempts to abstract that away.
It's worth finding a tutorial on these and do as many exercises as necessary. I'm not going to recommend any specific language as I think they all are bad for beginners in their own ways. You need not concern yourself with practicality or popularity of the language you pick though as your focus is on the basics. These skills are transferable, important and yet a tiny kernel of all your future progression. Then you'll be able to combine these basics to build some simple programs. Print a string backwards, guess the number, guide a cursor on a canvas by keyboard or similar.
From that point you can branch out to explore and comprehend actual CS concepts, and start with writing small practical applications.
I started writing minecraft plugins[0] and now I can write software as low as ioctl firmware and as high as web development. The more you write the more patterns you will start to notice and the better you will become.
Do not seek answers, do not seek solutions[1]. Stack overflow and guides are your enemy (documentation is fine[2]).
Want to learn x86 assembly? Throw a random exe (notepad.exe) into x86dbg (or CheatEngine) and start debugging[3] from the beginning. See what each instruction does and how it affects the hardware registers. Look at it long enough and you will start to understand assembly and be able to write it.
Programming is special for me - I was the dumbest person you could find as I even struggled with basic multiplication at school, but with years of programming I've also noticed how I've started doing much better at school without putting in the extra effort usually required.
So in the end - just write code, see where it takes you. Follow your interest and see where you end up.
[0] With no education, no knowledge and a slow computer with a free eclipse IDE. The only guides I ended up using the most were on how to setup bukkit plugins in eclipse.
[1] For specialized software, otherwise try to figure out what the library does that you want to use yourself by looking at what it does and how it does it. Finding out how to use any kind of particular software is typically fine, but it's better to play around with it and figure it out yourself.
[2] Unless you're reinventing a wheel (don't invent a sorting algorithm).
[3] Single-step program entry-point until the application is running and you notice a repeating loop.
What is your language? Maybe people here could give you ideas of a good first project to try :-).
Someone else mentioned data structures and algorithms. Algorithmic complexity is particularly important. The Algorithm Design Manual is a great book in this space.
As a low level developer, I've also found the following topics way more useful than I expected:
- Finite State Machines (These are the basis for everything from inter-device communication protocols to simple video game AIs.)
- Binary arithmetic and boolean logic (Rarely relevant, but absolutely essential for diagnosing certain types of parsing errors, buffer overflows, etc.)
- The Halting Problem and P = NP (Useful when a manager tries to get you to do something that is actually impossible.)
I learned these from intro to Computer Science classes in university, but honestly Wikipedia is probably a good place to start. I think the (middle grade) book Lorem Ipsum also covers most of these concepts.
It's become very popular to learn how to assemble code by following step-by-step tutorials and watching YouTube demonstrations. It does get the job done for a lot of people, but it usually doesn't develop very strong or deep foundational knowledge. As a result, people who don't make a point to leave that world generally end up stuck under a low skill ceiling.
So whatever suggestions you find in other replies here, favor books (and perhaps deep courses) over anything more shallow. And among those books, favor those that are heavy on prose and explain things over those that just guide you through doing things. And then when you get the books, sit down with them and really work through them.
It is a collection of short essays on particular skills that are applicable to programmers of different levels.
The introduction starts with:
> To be a good programmer is difficult and noble. The hardest part of making real a collective vision of a software project is dealing with one's coworkers and customers. Writing computer programs is important and takes great intelligence and skill. But it is really child's play compared to everything else that a good programmer must do to make a software system that succeeds for both the customer and myriad colleagues for whom he or she is partially responsible. In this essay I attempt to summarize as concisely as possible those things that I wish someone had explained to me when I was twenty-one.
I will also point out that "How to debug" is the first thing in the list. It starts out with:
> Debugging is the cornerstone of being a programmer. The first meaning of the verb "debug" is to remove errors, but the meaning that really matters is to see into the execution of a program by examining it. A programmer that cannot debug effectively is blind.
> Idealists, those who think design, analysis, complexity theory, and the like are more fundamental than debugging, are not working programmers. The working programmer does not live in an ideal world. Even if you are perfect, you are surrounded by and must interact with code written by major software companies, organizations like GNU, and your colleagues. Most of this code is imperfect and imperfectly documented. Without the ability to gain visibility into the execution of this code, the slightest bump will throw you permanently. Often this visibility can be gained only by experimentation: that is, debugging.
Start a greenfield project. Something that isn’t huge in scope. A basic text editor, a mini redis clone, an asteroids game. Try something harder for your next project.
Theory-wise I think type theory is a good start. Along with with Software Abstractions; a great book on the design of software systems using formal methods. And a book or two on data structures and algorithms. Discrete maths essentially and combinatorics. That will get you far.
If you choose a language that’s not widely used or no one is hiring for, don’t worry about it. You’ll find that the concepts you learn in any language are portable to all languages. Once you learn those, it will be easy to pick up new languages when you need to.
Bonus advice: when you find a language you’re good at, stick with it and get really good at it.
Ask it to act as a mentor that is teaching you how to program, ask it to give you an problem to solve, and give it a shot.
Then paste back your code you wrote (keep it simple) and ask it to explain your approach, provide advice, describe patterns, and explain tradeoffs between different techniques.
Initially, learning how to talk about code is important, then identifying patterns and approaches.
Coding isn't about memorizing things, it's about understanding the advantages and disadvantages of different approaches.
Have fun!
Plus a certain amount of raw intelligence, but less than many people think. If you're asking, you've got that one covered.
The temperament, though. Can you spend hours to weeks trying to find the stupid and obvious thing you did wrong, and feel good about it afterward? If so, welcome to programming. Enjoy your stay.
Edit: also did 200 Codewars katas to practice, then started to build things.
Use c to build some very minor things, so you can get a better feel for how memory works.
Don't build any mobile apps, you'll go down a rabbit hole. Don't worry about algorithms or any theoretical books for at least a year.
Though, these fundamentals are more theoretical (though worthwhile). You may want to just build a couple of things first to get some muscle memory.
No need to finish them, as long as you make it over a few hurdles before you move on.
I recommend picking an area of interest and diving in head first.