Resources for learning more programming fundamentals
Hi all - I was hoping to get some input on finding good resources for more fundamental programming concepts. I kind of feel like I'm in a (self taught) rut lately.
I understand things like variables, arrays, functions, and to some extent objects, but I'd like to take it to the next level. I've written a fair amount of applications using PHP/Laravel and Javascript, but I feel like I spend too much time finding code snippets on stack overflow, versus being able to really understand what I should be writing, and how it all works.
What would your suggestion be on where to go next? Algorithms? I've seen a lot of mention of data structures as well, but it seems like when I go down that road, it just leads me back to arrays and variables. Any good resources to help me take things to the next level would be greatly appreciated (and hopefully others in the same situation can benefit as well). I'll also throw out there that my math skills are not great - I took calculus many years ago, but unfortunately I'd be starting from scratch on that front.
Thanks!
This is more of a meta-suggestion, but I'd suggest that you simply pick a project that is challenging and get programming -- if the problem you choose is complex enough, you'll eventually be needing specialized data structures to make it work (or at least to make it work fast). Learning about algorithms and data structures in a vacuum is much harder in my experience. Be sure to choose something you can be passionate about, that you actually want to work on.
One suggestion I've seen is that people should start writing a blog-backend. Yes, it is kind of pointless since there are so many different hosted solutions, but it is a problem that is easy to scale up in complexity. You can have something working in a couple of hours, but that doesn't stop you from adding more bells and whistles. A blog engine could, for example, lead into writing a spam filter for comment submissions, which means you could be learning about HMAC, Naive Bayes, Feature Hashing, the Count-Min Sketch, the basics of machine learning, etc., etc. Just follow whatever trail seems most interesting.
You can also drill down fairly easily with such a project by replacing things you would normally use a library or external application for, e.g. "how do I do this without using MySQL?", "How does the markdown parser work? " (Parsing is a whole rabbit hole on its own...)
In order to decide on appropriate algorithms and data structures, you should probably at least learn the basics of Big O-notation if you haven't yet.
Personally I like programming competitions like BattleSnake for programming practice. Writing a bot for these competitions can be as simple as glueing together a few if-statements, but if you want to climb in the leaderboard, it can become more complex than a chess engine. At the very least you'll likely learn about search algorithms (A*, Dijkstra, Depth-First, Breadth-First, Best-First) and the required data structures (stack, heap, queue, deque), as well as game tree search, how and when to cache stuff using transposition tables/hash maps, etc.
One last comment: math skills aren't necessarily required to begin with -- my math skills are still atrocious, but I understand a lot of the mathematical notation now, simply through having seen them often in different contexts.
Thank you for the reply - I've somehow never heard of BattleSnake (or Leetcode that was mentioned in another comment). That would be right up my alley, as I definitely will sit for weeks just trying to think of something to build.
I think I'll work on rebuilding from the ground up an application for managing apartments that I wish I had (basically a knock off of quicken, maybe?).
There's more out there to learn than a person can in a lifetime, and the sort of structure/format of education that works for one person may not be appealing or amenable to the life of another.
If you want a standard comp-sci education you can find curated resources for topics that use a language you already have some comfort with, organized in a way that some world class universities decided they should be and with accompanying MOOCs taught by their professors.
If you want to learn a technology like Laravel or a role like a full stack web dev, a front end designer, etc., you can look for a roadmap on Github/Reddit/etc. that looks appealing. Stars are a loose proxy of what other people found valuable.
A lot of people find it most useful to find a goal and learn what's needed for that. You can do enhancements (e.g., "I'll add export support for toml instead of json") for existing code bases to learn how more experienced developers structure projects. You might start your own small project and add on to it over time, learning from mistakes.
Some people recommend programming challenge websites like Leetcode or Hackerrank, optionally grouping the challenges into the concepts.
Some people take a "top down" approach, taking advantage of all the tools and frameworks out there that make productive coding easier, digging deeper as needed or using a real-world example to show the need for some concept.
Others take a "bottom up" approach where you might be learning assembly, theory of computation, programming languages, operating systems, etc., stripping away anything extraneous and showing how concepts build on top of each other.
At a minimum algorithms, data structures, and software engineering/design/architecture are good to understand a bit of. There's diminishing returns (at least if your goal is to code, vs. be an academic) or situational usefulness of most things you can learn.
You should understand asymptotic complexity of algorithms/data structures and how to figure out where a bottleneck might be. Knowing the basics of SOLID design or some common design patterns is useful. But you can get the gist of how big-O works in an afternoon, and you may never need to use a trie or kd-tree and probably shouldn't be implementing your own.
On the other hand, occasionally you learn something that fundamentally opens doors you didn't even know existed, like ways of solving meaty problems with ML or functional programming, or optimizing with linear algebra. It's good to keep learning and get out of a rut, but there's a lot of perfectly valid ways to go about that.
Good luck!
Thank you for the tips! All of the comments here have been great - a lot to dig into.
I think that one of the thing that throws a lot of people through a loop when it comes to programming is that a lot of concepts are a whole lot more simple than they appear to be. Data structures are a pretty good example; the term basically just talks about how data is put together. While there are a few low-level generic data structures that are nice to know, generally the only kind of data structures you need to worry about are the higher-level objects and classes you'll be dealing with (Edit: this is a really bad generalization that may not apply to your particular domain).
One thing I have found useful is to be able to understand at least a portion of how any given programming language works 'under the hood'. Most programming languages will have an official manual or something simelar that will go into the gritty details and cover the kinds of stuff that "learn to program" materials either gloss over or don't cover at all.
One thing I do when I'm stuck on something instead of looking up solutions on the internet is that I'll lookup the definition of the object that's causing me problems. Many modern programming projects are full of frameworks that introduce abstractions that in theory make things easier to do because you don't need to worry about the implementation, but in many cases not understanding the implementation makes debugging difficult.
I've noticed this as I dove into Laravel - all the sudden arrays seemed to be replaced with objects, and instead of passing an object and it's type to a function, you're passing some sort of helper function. It's great in theory, and for getting things up and running quickly, but can be incredibly confusing for when you want to learn how things work (though it has also forced me to read more documentation, which leads down a rabbit hole of googling terms from that documentation).
Thank you for the suggestions!
If you're interested in how (some) computer languages work, Crafting Interpreters is a great read.
If you're interested in learning about the barebones of how a computer works at a really low level, I'd highly recommend Ben Eater's series on building a 6502 computer from scratch. Ben's a super entertaining presenter and explains every detail, which keeps things beginner-friendly.
One book which takes up fairly fundamental topics is Structure and Interpretation of Computer Programs (SCIP). Going through that book and implementing the concepts will give an understanding of LISPs, data structures, abstraction etc. It is by no means an easily digested book, but it is definitely eye-opening and gives you a richer understanding of computation.