Revised 2024-07-07.
This is a document I’ve been thinking about writing for quite a while. A lot of people that want to learn about programming or computer science today tend to take a certain path through it and I would like to provide some framing that a lot of people might find useful. It’s important to understand that computers are not magical and everything is simple if you look at it long enough from the right direction. So what I’m sharing here is many of the topics I’ve had experience with when learning to git gud, so that you can too.
This article is pretty opinionated. It’s not meant to not be. But it’s probably a lot different than other guides/roadmaps/etc you’ve seen before.
This document isn’t meant to teach you, it’s meant to guide you. You can take a different path, especially if it means you’re more engaged in the content and feel more enriched. Learning is always good. You will have to Google many things along the way, half the work is learning how to learn!
These steps aren’t even meant to be taken linearly, if you achieve all of them then I consider you to be “pretty good” and someone I would be happy to hire. But if you specialize in a different direction, that’s great, your skills are still improving and your time is more valuable. This isn’t even exactly what I’ve experienced, it’s just enough to cover all of the skills I think are valuable to have.
I’m saying this prescriptively, not descriptively. If your goal is to jump in and get a professional job as quickly as possible, you could take an easier path and just go to a bootcamp for webdev. But the odds are you wouldn’t be as broadly enriched, will be put into a standard-sized bucket when looking for jobs, and will have a pit to dig yourself out of by relearning skills that weren’t properly taught to you in the first place. Focusing your education on just what’s trendy to get a job doing is not the strategy you should be taking, because if that’s your priority you’re going to compromise on rigor in order to achieve some short term goal. This article is meant to guide you to do the opposite.
Computer science is not really about computers or programming. It’s about studying the way we model and transform data. But the primary context we talk about these ideas is in the context of programs, which are ran inside of the computers made out of silicon and copper. And people have connected those computers together in interesting ways with strands of copper and glass. So unfortunately when we talk about computer science, we also tend to talk about computers and programs and networks.
So to effectively use common languages to solve interesting problems, we have to have solid understanding of the theory behind it to design effective programs. And to apply abstract ideas to real-world problems, we need to be competent at programming languages that give us the tools to express our ideas. In this way, there’s a dual nature between computer science and software engineering. It’s hard to be skilled at one without the other.
In any case, there are two ends of the spectrum and many areas that exist along it. To start off with, a very “practical” language that everyone should know is Python (and I mean everyone that has to spend a lot of time on their computers for their job, not just CS/software people). It’s very commonly used in teaching and has very broad applicability so it’s an invaluable tool to have in your belt. But to develop a more thorough appreciation of the abstract side, a good language to do that through is Racket. See more on these below. It’s important to understand that these are just the starting points. While you can write fairly sophisticated programs with them, you should always be looking to expand your horizons once you’ve gained some comfortable level of competency with them.
But more generally, there’s many areas of skills that a competent computer person might be interested in beyond narrow programming skills. You don’t have to have all of these to be an expert at some specific domain, and there’s a huge amount of overlap between these so there isn’t really a “jack of all trades, master of none” effect.
But to summarize these areas non-exhaustively, and under each point how you’d approach it:
By “case study” here I don’t mean formal analyses of some subject. I mean this in a super unstructured way. Tech blogs from startups that write projects we write. Something somebody in their basement might have figured out. It’s fun.
In case you haven’t realized it yet, a lot of these points involve “do something that depends on it”. Something unique about software design as a discipline is that we get to practice it in our bedrooms. This is unlike disciplines like chemical or civil engineering, or to a lesser extent ones like mechanical or electrical engineering. The extents to which you can practice these at home with your own resources is very different than the extent and nature you’d do it at work. With us, the scale is often smaller, but many bedroom projects became wild successes, like Linux.
For a very first-principles introduction that gradually introduces you to a very good understanding of some fairly abstract topics, I suggest learning Racket through How to Design Programs. It has wonderful documentation. Racket is a Scheme-like languages, and HTDP is inspired by the older Structure and Interpretation of Computer programs. These books start slow, but it’s because they’re being very principled about it. HTDP is used to teach every freshman at my university and the teaching faculty have taken a very principled approach to designing the courses. You might never learn Racket/Scheme/Lisp to a professional level, but the concepts you learn from it will be useful in everything else you do.
At the other end of the spectrum, for the more practical topics that you can focus on in the process of learning Python, there’s
With some overlap, there’s also The Missing Semester of Your CS Education that covers a lot of great topics. But of this, these lessons are the big ones to focus on I think:
And for something more self-directed:
Please suggest me more if you have others!
Here’s a list of blogs, people, channels, etc that are interesting characters to check out, wherever they happen to crop up, since they’re either really informative or have interesting perspectives.
Also, here’s some specific articles and stuff that I think are pretty interesting that aren’t accounted for the above groupings:
These lists are far from complete, will add more as I get to them.
Talks from conferences can get very deep. I constantly used to watch talks I simply did not understand any of the details of, but gave me some broad understanding of some area that I came back around to much later with a greater appreciation for. On the other hand, they can also can be very thought provoking and prompt you to think about issues you may not have considered otherwise.
Linked below (near the bottom of this section) is a large list of project ideas that I moved onto its own page. These are just starting points, don’t treat them as a list of tasks you have to check off. If you find some other related idea interesting or have some novel problem you just thought of that you think you can solve, you absolutely should explore it!
Also, not all of these involve actually writing code, some only involve learning some new CLI tools or service you should learn to configure. I mostly avoid discussing use of specific languages, too. This is because knowing the right tool for the job is something that’s useful to learn on your own. You might want to attempt some project multiple times using different languages to get a more natural feeling for which languages are better suited for different use-cases.
If you’re a beginner then looking at this section might seen intimidating. That’s kinda on purpose, they’re not all meant to be introductory. But at least a couple of these should feel approachable to you if you’ve dipped your toes into programming enough to get a feel for it. You’ll probably have to read some documentation or Wikipedia articles, but once you work through a couple things then read over the list again and see what seems more approachable now with the new skills you’ve learned.
Python is so incredibly useful because of how multi-domain it is. So for a lot of these projects it’s a good starting point. But it might not be the ideal language for some of them, as I mentioned above, so you’ll eventually want to learn others.
Beyond Python and Racket, these are the main languages that I think you should focus on:
Other languages that are more niche that you may want to work with at some point that could be worthwhile:
Other languages you may want to learn to study their mistakes and flaws:
If you’ve read other guides, you’ll probably see more focus on the web stack, including JavaScript. It’s useful to know it, but it’s very often overused, and building everything to run in a web browser is limiting. I don’t think that we should be encouraging new programmers to learn JS until they’ve reached a certain level of competency. It’s very approachable with little background and there’s a lot of resources for doing that, but naively learning it teaches you a lot of bad habits and its idiosyncrasies mislead you.
// TODO finish and link js article
If you’re someone that wants to work with computers every day, then you need to care about your tools. Tools help us get our work done, software tools are just as important as physical tools. And how are tools are designed has a big impact on us and how we do our work, so it’s important we put a lot of thought into them.
Prefer FOSS wherever possible. It’s hard to avoid proprietary software in all cases, especially if you want to play video games, but we can set ourselves up such that we’re not reliant on it.
You should make it a goal to switch to using Linux as your daily driver. This isn’t an unreasonable request, it’s 2022, you don’t have to be a technically-minded person to use it anymore. The benefits you get out of it are not only being able to have more direct relationship with your system, but you also take a big step to free yourself from the corporate-owned software world and embrace the community-owned world. It’s more than just about its technical merit, what’s more important are the power relationships and the underlying principles.
You don’t have to start here. You can get pretty far if you’re on Windows. While you don’t have to open a shell to get stuff done anymore, you should expect to to do many of the projects I’ve suggested later in this article, so you might want to familiarize yourself with it on Windows first and then switch. Or not, if you’re enthusiastic you can jump right in immediately.
It’s easier to daily drive it today than it ever has been, in part thanks to work by Valve (one of the few not obviously evil corporations) you even can play lots of “officially-Windows-only” vibeo games on it, in many cases right out the box in Steam.
MacOS is potentially more acceptable, and you could go farther with it without hitting limits to your skills, but in this case you’re still within Apple’s grasp and you’re subject to their corporate agenda.
On mobile, similar thinking applies. Make your next phone be a Pixel and put an Android ROM like CalyxOS, CopperheadOS, GrapheneOS. I’m not an expert on Android so you should do a little of your own research to find the right balance of de-Googling for you, but CalyxOS suits me well enough.
If you’re a high school student, I suggest making the switch over the summer before you start the next school year, especially if your next school year is going to college. Just before college is when I switched over to it as my daily driver and it was a great choice. If you’re already in college, then doing it between semesters like during winter break is probably a good time.
Chrome is owned by Google. That shouldn’t be a surprised. Chromium is an open source software project managed by Google. I say open source, but only in the strictest sense of the word. Google makes unilateral decisions about the direction of the project, to serve their corporate agenda. There’s a few browsers such as Brave that are based on the Chromium codebase, so Google indirectly control these too. Since Google basically controls this much of the web market share, they also basically control web standards and have a large say over the World Wide Web Consortium that, on paper, is supposed to decide things.
Additionally, Chrome phones home to Google everything about your browsing activity and JS heap dumps, even in incognito mode.
Mozilla currently has some troubles, and only really exist due to funding from Google as a tax writeoff and so they can have a defense against antitrust lawsuits. But Firefox is really the only mature web browser that is justifiable to use. There’s a few tweaks you have to make to get it to really respect your privacy, but this is a one-time-setup.
As for browser extensions, the most important single one is uBlock Origin, most of the other adblockers take bribes to not block certain ads. If you want to support creators that seem to rely on advertising revenue, then it’s better for everyone if you just pay them directly through Patreon, Liberapay, OpenCollective, or whatever other system they use. Advertising is parasitic in nature and we should not accept being distracted by it.
The other browser extensions that are useful:
// TODO elaborate
Avoid VS Code, for many of the same reasons you should avoid Google Chrome. If you really want that style, then use VS Codium intead to actually be using free software and not the clever bait-and-switch Microsoft pulls.
Personally, I use Emacs, but it’s not right for everyone. Vim is also decent. Both take some setup and getting used to but are more powerful and give you more control than today’s mainstream text editors.
// TODO elaborate
Choosing the right hardware can make daily-drivering Linux easier. Some high-end laptops even come with Linux preinstalled! My rough reccomendations are:
The important thing to be aware of is to avoid Nvidia graphics cards. Their driver support is terrible and while they’ve taken steps in the right direction recently, the weird setups you’d find on laptops don’t make configuration easier. You probably don’t need high-end graphics on a laptop, you can get by with the integrated graphics on modern CPUs.
If you really want high-end graphics, I would suggest buying a cheaper laptop and saving your money to build a desktop with an AMD graphics card.
I don’t know of any regular desktop motherboards that support Coreboot or Libreboot such that we can have privacy-respecting firmware, but that’s a whole different battle and kinda hard to try there yet. Obviously it’s more reasonable to use a less freedom-respecting laptop that you already have than pay for a new laptop that does, but not everyone is as purist as I aim to be or you might have more money to spend than I do.
Don’t buy an Apple computer. They’re nice and pretty, and the newer ARM ones are very competitive with Intel/AMD based laptops, but that’s not what matters right now, it’s an issue of ethical consumption. Watch Louis Rossman’s videos on YouTube if you really want to go into the sheer degree of anticompetitive bullshit they’re capable of.
If you already own a Mac then that’s totally okay, but but look into using Asahi Linux when it’s more mature.
If you’re planning on doing anything with cryptocurrencies, you should also buy a hardware wallet to store your funds on if you have more than a couple hundred dollars worth. This is kinda orthogonal to the other stuff, but it’s just way safer and it needs to be said. Plus, some of them also can work a U2F device!
It’s easier to switch the software you rely on that you run locally, but it’s harder to switch out the software you rely on that runs somewhere else. So it might take more of a lifestyle change to reduce your usage of those.
Generally you should look towards using self-hostable services, or at the very least services that have fully free software clients.
Try these replacements:
There’s some more detailed discussion on how to go about this in the Projects section above.
// TODO elaborate
Computers are powerful. If someone uses your software, they’re trusting you in a certain way. That trust can be abused in various ways. If you control the software someone runs, you have some kind of power over them, and power can be abused. One of the better ways to ensure power cannot be misused is to give the user the opportunity to take the power back if needed. This reduces the impact and risk of coercion.
// TODO elaborate
The consequence of this is that all software should be free software and all information should be freely available.
Most large corporations are evil and want you to be dependent on them to ensure their continued existence and profitability. You should avoid them and take steps to reduce your dependence on them.
It’s unreasonable to expect to fully divorce ourselves from the surveillance capitalist state without giving up some nice things and alienating ourselves from our friends, but we can reduce the kinds of data we leak and work to establish viable alternatives (kinda like dual power).
It’s difficult to describe how quickly computers have dramatically all of our lifestyles. It’s possible nothing in the history of humankind has caused as dramatic of a shift as computers and modern telecommunications have. For both good and bad. Trillions of dollars of wealth have been accumulated as a result of this shift, and private corporations in control of our infrastructure have power that rivals that of governments. So trying to inoculate ourselves against coercion by these actors I see as a moral imperative.
These are pretty important to read/watch, and heavily informed my own opinion on technology and our relationship to it.
// TODO more