Of all the computer science classes I took in college, there were three that I’d recommend, without reservation, to someone who wants to do my job. Each taught me something that relates to programming as an activity and a way of thinking. There’s nothing terribly domain-specific (like networks or databases, which I will cover in the next post) here, just stuff that helps you build programming muscle.
This is the third post in a series about learning software development outside of an academic computer science program. Last week, I shared my general roadmap and talked about algorithms. Today I’ll cover programming, and over the next few days I’ll discuss other important skills, and the importance of community.
1. Intro to Engineering
This class had one assignment: Use an Agile process to build a video game with the Greenfoot game engine. Amazingly, this small class taught me four extremely valuable programming skills.
Agile development is the answer to the question: “How do you organize a complex software project such that development could stop unexpectedly and it would still work?”
Though it is meant primarily for collaboration, you might find it helpful for keeping track of your progress during learning-oriented projects. If you have a mentor, you can also use a lightweight Agile process to create a regular feedback loop where you can seek and receive help.
There are as many ways to organize a small project with an Agile process as there are people who use it (see this thread on Quora). The gist is that using a formal process will help you take on an appropriate amount of work without getting overwhelmed.
Version control provides a way to let different people change the same code at the same time without screwing up everything. Git is the most common version control tool. It is not a perfect tool, and I think it can be especially difficult for newcomers. It was for me!
In any given hiring process, you will be asked what version control system (VCS) you use, and you probably want to have a good answer. If you use GitHub to publish your Git repositories, you can slay two proverbial birds with one stone: You’ll gain a skill (version control), and you’ll publish your work (displayed on GitHub).
You can learn some really valuable lessons by revisiting code you wrote and finding a way to fix it. It fundamentally changes how you write software. The longer I write code, the longer I spend thinking of good names for variables, classes, functions, and modules.
The only way to gain experience with this is to put yourself in a situation where you have to deal with emergent complexity, such as requirements changing after you’ve already written a bunch of code. One of the best resources for understanding how to approach refactoring is Clean Code by Robert C. Martin , which I reviewed here.
This may seem silly, but when you have a problem you don’t understand, it is important to be able to punch some words into Google and find an answer. This is a much deeper skill than you might think (read this excellent and candid blog post on the subject by Umer Mansoor).
I could write a whole blog post on this subject, but I’ll sum it up by saying you need to identify where potential answers might come from. Three that come to mind are:
- Stack Overflow answers – These can be needlessly terse and unhelpful, but they are often a good source when you start looking (and don’t neglect the comments sections!).
- GitHub Issue threads – An Issue in GitHub is basically a bug report that allows a user of an open-source library to report a problem with the library. The wonderful thing about this is that most people who think they’ve found a bug are wrong; they’ve got a bug in their environment or some dependency, and it is the answers to these issues that will likely help you.
- APIs and Documentation – Not all APIs are created equal, and some require creative searching to get the answer you need.
You’ll need this context when creating your Google search: Where is your problem most likely to be addressed? What words might people be using or not using when asking a similar question? Look around and find other ways (like this article) to level up your Google-fu.
2. Discrete Math
Learning discrete math was the second biggest growth period for me as a programmer, even though the class involved no coding. I had two big takeaways here:
Proofs == Programs?
First, you learn to write mathematical proofs. When you get good at writing proofs, you also get good at writing code. This is extremely helpful for writing algorithims, which I talked about in part 2 of this series.
Learning an algorithm (or creating one, for that matter) and writing a proof are very similar. If you’re really good at one, you’re likely to excel at another. Do you need to be able to write formal proofs in order to make software? No. Is it helpful for learning to think in a more organized and logical way? Yes.
Second, this area of study will introduce you to lots of valuable mathematical concepts–things like number theory, cryptography, permutation, combinatorics, set theory, graph theory, and probability. As a programmer, you will encounter lots of problems that are best described by the language of these domains. The fundamental concepts of data structures rely on a lot of these concepts, too.
Conversely, after you’ve programmed for a few years, you’ll gain an instinctive understanding of a lot of these topics. I’d say that the time you invest in a class like this would pay off very quickly. It did for me.
As someone who needs a lot of help and human interaction in order to learn math, the only way I can recommend learning these concepts is to enroll in an academic class.
3. Programming Language Concepts
In the introduction to Concepts of Programming Languages, author Robert Sebesta describes a motivation for programmers to study programming languages:
It is widely believed that the depth at which people can think is influenced by the expressive power of the language in which they communicate their thoughts. Those with only a weak understanding of natural language are limited in the complexity of their thoughts, particularly in depth of abstraction. In other words, it is difficult for people to conceptualize structures they cannot describe, verbally or in writing.
To expand on Sebesta’s words, you need a vocabulary for describing the tools you use that isn’t a part of the tool itself. This is especially important when learning new frameworks so you can look under the hood when things don’t work (and it helps your Google-fu). Separating semantics from syntax is something that junior programmers struggle with a lot, and studying other languages definitely helps with that.
You can learn this by exploring Sebesta’s book, which I think is really good, or finding one like it, maybe from No Starch Press.
Other Languages You Should Learn
If you are a bootcamp graduate, you likely have graduated with a fairly narrow knowledge-base that enables you to work within a specific tech stack. Likewise, if you are a self-taught Pythonista, you might have the same problem as a bootcamp graduate: You know how to do some stuff, but you can’t talk about it outside of the context of that language or tech stack.
The best thing you can do is to learn a fundamentally different language, which will force you to divorce syntax from semantics. How do you know if one language is fundamentally different from another? Familiarize yourself with programming language paradigms.
Your goal should be to find something that is very different from the language you know and learn it really well. It will help you better understand fundamental ideas about programming, deepen your understanding of the language you already know, and stand out to hiring managers on a resume.
If you’re working on becoming a software developer, get in touch! My home email is [email protected]. Let me know how it’s going, what worked for you, or even where you need help.
You should also check out the rest of the series:
- A Roadmap
- Understanding Algorithms
- Learning to Think Like a Programmer
- Expanding Your Skills into Other Domains
- Finding a Community