As someone who has previously taught computer programming for nearly a decade, I’m often asked questions that involve “what’s the best way to go about learning to program computers,” or “what’s the best way to get a software engineering job,” or “how can I learn to build mobile or web apps?”
Most of the readers of this blog have probably faced the same question at some point in their career. How did you answer it? I’ve seen many different responses: “come up with an idea for an app and build it,” or “get a computer science degree,” or “go read The Little Schemer,” or “join an open-source project that excites you,” or “learn Ruby on Rails.”
The interesting thing about these responses is that, for the most part, they can be classified into one of two categories: top-down approaches or bottom-up approaches. Top-down approaches are informed by the opinion that it’s better to be thrown in the middle of an application or a framework which encourages the learner to piece together knowledge in that context. Many books and online tutorials use an explicit top-down approach, often starting with the basics of a popular methodology, framework or technology. The most visible example of this are books on Ruby on Rails — they almost always inevitably begin with a description of the Model-View-Controller design pattern, but defer the incredible number of non-obvious ideas that make it up (Object-Oriented Programming, for instance).
On the other hand, a bottom-up approach starts with the basics/fundamentals of programming and then slowly builds your knowledge over time. In contrast to top-down approaches, bottom-up approaches try to minimize the number of these non-obvious ideas that the learner has to take for granted. Khan Academy and Code Academy are two examples of online sites that use a bottom-up approach to teaching programming. For the most part, they completely leave out any specific framework and focus on fundamentals of programming.
Likewise, undergraduate computer science degree programs ostensibly teach using a bottom-up approach, but the proliferation of objects-first teaching methodologies and the Java programming language lead me to classify the programming-related portion majority of these programs as top-down (I have much more to say about this, but I’ll defer it for now).
Assuming you agree with me that these are two broad approaches to learning software engineering, it’s a little easier to classify the pros and cons of each. For example, proponents of the top-down approach often cite the fact that it’s easier and quicker to get something meaningful up and running within a couple of days (or even hours) which, in turn, motivates a person to want to learn more. They argue that learning a framework or a specific technology from the start make learners more employable more quickly. Critics counter that it’s difficult to understand and internalize top-down approaches, and that this can often overwhelm beginners leading them to give up.
Proponents of bottom-up approaches argue that it’s easier to grasp small chunks of knowledge that can then be built upon and that this approach tends to provide a more solid foundation on which more meaningful learning can happen. Opponents would say that most of the programming examples that are shared in a bottom-up fashion are contrived, and because of this beginners will get bored and give up.
In my mind, there are good arguments for and against both of these approaches. But my experience has shown me that bottom-up approaches tend to be better for the vast majority of beginners, while only a select few beginners can easily excel at the top-down approach. My hunch is that most of these folks who excel at learning via top-down approaches have some kind of prior experience with programming, or have some natural inclination towards being adept with technology.
So what does this mean if you’re a learner? I am of the opinion that for most people a bottom-up approach to learning software development is far superior to a top-down approach despite the fact that it takes a little longer to be able to actually turn your ideas into a reality. This should not be surprising — you can’t expect to write an incredible novel in a foreign language while you’re just learning the language!
How can we turn this into a concrete approach to learning for beginners? First, if you’re a beginner and you’re evaluating a tutorial, a book, a bootcamp, or any other purported method of learning software development, the absolute first thing you should do is ask if the material follows a bottom-up approach or a top-down approach. And, unless that you have some background in computer programming, you should almost always prefer bottom-up approaches.
Once you find a solid learning tool that teaches using a bottom-up approach, what’s the best way to learn? I have a pretty controversial opinion on this: I think it’s absolutely essential that beginners start memorizing the basics as soon as possible. I think that memorization is quickly becoming a lost art-form when it comes to higher learning. You’ve probably heard people speak of it disparagingly (“don’t memorize, internalize”, “i suck at memorizing stuff”, “I hate tests where I have to regurgitate memorized facts”).
On the other hand, when you’re in elementary school you’re largely forced to spend time memorizing your multiplication tables. Why? Because your basic multiplication tables are building blocks of more complicated algorithms like long division. This isn’t much different from memorizing syntax in a programming language: the more natural it is for you to write an if-statement or a for-loop, the easier it is to use those as building blocks for more complex programs.
I’ll admit that memorization is not always the best way to learn every topic, but I believe that when just starting out with programming it’s absolutely essential that you practice it. Why? Because it reduces friction, and if there’s one thing that leads to frustration for beginners, it’s friction.
With that in mind, here’s some concrete advice for people just starting out and looking to get into web application development. In fact, I’d go a bit further and say that this is a good plan to get started learning any type of software engineering. Obviously, this isn’t a one-size fits all plan, but I think it’s pretty good for the majority of learners just starting out.
- Learn the basics of a weakly-typed language, and avoid languages that force or strongly encourage object-oriented programming with classes. Seriously — if someone mentions “classes” or “inheritance” to you, it’s a good idea to run the other way. While I agree that these topics are essential to software development in general, I strongly believe that they should not be taught to beginners.
- learn how to print something out (console.log)
- learn how to declare and define variables
- learn basic arithmetic operations (including the remainder operator)
- learn loops (focus on “for” loops)
- learn abstracting repeated code as functions
- learn strings and basic string manipulations using for loops
- learn arrays, and array methods for looping (focus on “forEach” loops)
- learn to create and manipulate objects as aggregate data
Memorize these things and practice them every day by writing a program that does something simple (FizzBuzz, for instance) from memory.
- Learn the basics of Git, and learn to use it from the command-line. This means starting with four basic Unix commands first (ls, pwd, mkdir, cd). When doing this, learn to mentally represent your filesystem as a ‘tree’ (or a hierarchical structure).
Once you’ve mastered the *nix commands and have some practice navigating your file system from the command line, learn a few basic Git commands. Specifically focus on git init, git status, git add and git commit). Practice visualizing the repository as a simple linked structure of commits, even if that means drawing a picture occasionally.
Once you’ve memorized the basics of Git, integrate it into your workflow when learning the following things.
- Learn the basics of HTML. Be able to create a simple HTML page from memory. Learn about the DOM and how to think about HTML as specifying a hierarchical tree structure. Spend some time thinking about how this relates to the hierarchical model of the file system that you learned in the previous step.
- Learn CSS selectors and how they allow you to zero-in on certain parts of the DOM. Learn about the relationships between DOM elements. Learn what it means for a DOM element to be a parent or a child of another DOM element. Learn how this differs from a descendant or an ancestor relationship. Memorize selectors that allow you to select elements via these relationships.
- Learn JQuery, and focus primarily on its DOM manipulation abilities (sure, it’s not necessary anymore with querySelect, but it’s still widely used and — quite frankly — it’s fun). Learn to insert and remove elements from the DOM using JQuery, and practice visualizing how this affects the tree structure that’s defined by the DOM.
- Practice event-handling and DOM manipulation in JQuery (e.g. practice making manipulating the DOM when a user clicks on something, or at a specified time interval).
At this stage, building a simple slideshow that cycles through Flickr images is an incredible project that will really test your ability to make things happen using all of the fundamentals learned previously.
I think if you make it this far, you’ve mastered a large number of essential concepts in programming and Computer Science. Specifically, you’ve learned the most essential elements of computer programs (if and if-else statements, loops, variables, objects, functions, arrays) and you’ve learned to think in terms of important data structures like linked lists (Git commits) and trees (the DOM and your file system). At this point, you’re definitely ready to move on to more advanced topics.