The Self-Taught Engineer
13 min readOct 4, 2016

I have many times tried to articulate what I feel is wrong with the majority of beginner programming books and tutorials. This often involves a lot of long-winded sentences that trail off, hand gestures, and punctuating with a hearty “you know?”. It remained vague until I heard an interview with celebrity performance coach Jim Kwik. In it he described a life-changing injury he experienced in college that inspired him to completely change his life. While recovering in the hospital, he was trying to figure out how to turn around patterns in his life of struggling to learn and failing in school. He describes looking through the course catalog for his college and the thought that occurred to him.

There were hundreds and hundreds of courses on what to learn. There were zero courses on how to learn.

Bingo. Most tutorials will start by teaching you what variables, loops, functions and if statements are and what they do. They may walk you through some contrived examples intended to emulate real development. What I and those I have talked to seem to find is that this style leaves the student with little to no understanding of how to apply this knowledge on their own. Worse, they tend to be boring. If learning to code feels like work, it is unlikely you will stick with it long enough to become proficient. This is why I believe true learning has to be self-directed.

What I find with most students is that they are stuck in a state of passive learning. They are waiting to find the right book, class or video that will finally teach them to be a developer. In this state they do not feel ready to start creating things on their own, because they believe that they lack the knowledge. As you may have guessed, they have it backwards. Creating programs is the act of learning.

These are the five things I tell anyone who tells me they want to learn to be a developer. I applied these when I was starting out, and I believe this is the true formula to attain success.

1. Motivate Yourself with Creativity

If your only goal is to “learn to program” it will constantly feel like a chore. You will return over and over to the same books, tutorial sites, etc and wonder when the magic switch will be flipped that will turn you into a developer. Eventually your motivation will wane and you will start putting off or avoiding your learning. Sound familiar?

To be a developer, you must have the natural impulse to create and invent. In order to learn programming, you must not only want to learn programming but you must have things you want to create. This is the foundation of self-directing your learning. At best, most tutorials will walk you through building a generic, stripped-down version of a blog, social network, or forum. The worst will ask you to model something completely random like cars or animals in code. Have you seen a tutorial like this?

pinto = new Car(“Ford”, “Pinto”, 20, 100, #0AA8F5);pinto.drive();

I’m sorry, but what the hell does this have to do with anything? The student here is left extremely confused as to how Object-Oriented Programming should be practically applied. By over-simplifying, the author is actually misleading you.

If you are setting out to learn programming you probably want to learn to create applications. This means programs that perform a useful function, that you can interact with. Most tutorial authors try to be so general that they avoid the topic of applications altogether. In my opinion, they do you a disservice by doing so.

Think of something simple you want to create. It should only have one or two basic functions, but still be something interesting that you can use. Don’t worry if it already exists — this is for your own education, and you can always come back to it if you want to add more. If you can’t think of anything, here are some suggestions that can be created on a single web page using only HTML, CSS and JavaScript:

  1. Speed Reader — Check out Spreeder. This is a simple app that runs in a web page and flashes words from a text on the screen at a configurable speed. With an app like this, you can train yourself to read faster than you probably thought possible.
  2. Numerology Calculator — Check out namecalc. This is a project I completed in an afternoon. It calculates the total numerical values for a given name or phrase. Some people believe these numbers have special meaning. This is a react.js application, but still runs only in the browser.
  3. Dummy Text Generator — Check out Hipster Ipsum. Designers use dummy text like this when creating a website mock-up. You can create something similar just by randomizing arrays of words and phrases in a mad libs-like fashion, with sometimes hilarious results.

These are all small ideas I have used to test out different technologies or simply for the thrill of finishing a project. Of course, the best idea is the one you come up with. As you work on your idea you will break it down into pieces — take the dummy text generator, for example. To create this, you must write arrays of words and phrases. Then, you need functions that will select randomly from these arrays and combine the results together. Finally, you take your combined text and display it on the page. You can find out how to do all of these things in JavaScript with simple web searches, and best of all, you are learning them actively.

2. Jump in the Deep End

Think about the car example from earlier. The tutorial author figured, since you don’t know anything about software architecture, it was better to give you a contrived example unrelated to how the concept would actually be used. He or she was shielding you from that which you are assumed to not understand. This goes against how I believe people learn.

When you start out, a whole lot of things are going to seem foreign to you. Code, terminal commands, and architecture diagrams are going to read like Greek. The temptation is to start out slow, and stick to simple things that make sense. Think about how this approach might affect your learning — you are trying to learn something esoteric and complex, that you have little understanding of now. Are you going to accomplish that by sticking to what you already know? Of course not.

When I started programming, I decided to use Linux instead of the Macbook I already had — and I encourage other beginners to do the same. I could have installed Ubuntu, which is straightforward to install and comes mostly configured “out of the box” with a desktop environment similar to what you may be used to on Windows or OS X. Instead, I followed a blog post to install CrunchBang — an alternative Linux distribution I was told is “not for beginners”. But what is for beginners?

In your learning journey, you must expose yourself to as much as possible that you don’t understand. You may attempt something, like installing CrunchBang, which is too difficult for you at the time, and you may have to give up. However, this is not a failure! In doing so you will be exposed to dozens of concepts that you do not yet understand. Compare that to following a tutorial “for beginners”, which exposes you to only a handful. Which is going to be more effective?

See, even if you do not understand these concepts at the time, the exposure to them has embedded them in your memory and your subconscious mind. This is similar to reading a later chapter in a book before reading the first — something I recommend as well, by the way. You may only understand 20% of what you are doing or reading, but you can then go back to the beginning. In a book or blog post on an advanced topic, concepts foreign to you will be tossed around and referenced. Later in your learning, you will come to these concepts again and your subconscious mind will recall where you heard it referenced before. The more advanced topic will begin to put itself together like a puzzle in your mind, and you will say to yourself “Oh, that is what he meant!”.

In learning this craft you must be ambitious. Never tell yourself that something is “too advanced” or “beyond me”. Instead, tell yourself “I will come to understand this”. Take mental note of the words and concepts that you do not understand. You will doubtless see them again, and eventually create understanding. If you truly want to go as far as you can with programming, you should seek out the most advanced sources of information. After all, that is where you eventually want your level of understanding to be. By experiencing it right away, you create a pathway in your mind to get you to that point.

3. Peek Under the Hood

When learning you will find a lot of code examples and terminal commands online to solve a problem you may be facing. If the code or command works and solves the problem, the temptation is to just move on. To do so is to throw away an opportunity to learn.

Why did that work? You should examine the solution until you come to an understanding of exactly what it is doing. If code uses methods or keywords you are unfamiliar with, look them up to discover what they do. If the command uses flags or Bash keywords you don’t know, look up those flags in the program’s man page or search for the Bash operator used. You should come to understand the solution well enough that you could have written it yourself. This is not always possible — some people post solutions that are almost unbelievably clever. Regardless, you can learn a lot from them.

Once you are working as a developer, under the pressure of bosses and deadlines, you may have to sacrifice learning to simply “get things done” — but you needn’t do that now. We are not only seeking to learn how to code and how to create, we also want to understand how things work. Some may say of a specific library or tool that you don’t need to know how it works to use it. That is certainly true — but don’t take it to mean you don’t need to know at all!

Even if you end up working as a web developer, only needing to know HTML, CSS and JavaScript, does that mean you should stop there? Of course not! For example, the front-end developer can better themselves by learning about exactly how the JavaScript engine in the browser works, how their code is interpreted and executed, and about the protocols and standards that are used by their code. This deeper understanding will translate into better code, and a better position — like a senior developer. Isn’t that where you want to go?

See, only a small portion of development is knowing “how to code”. To use a language you must know the different constructs and how to apply them, of course. However, a large portion of what the working developer actually does is linking together existing libraries and services to create a full usable application. To do this kind of work, you must have a holistic understanding of how all of these parts work and what they do — not just the language you are actually writing in.

Therefore, for every new thing you encounter you must make some effort to understand it. If it is open source, you may even want to go look at the source code, the README, and the things people are putting in the bug tracker. It may not make any sense to you at the time, but remember we want to jump in the deep end. If the information is out there, use it!

4. Just Google It

This may seem obvious, but bear with me. We have discussed why we don’t want to follow linear tutorials — we want our learning to be self-directed. Therefore the roadblocks we encounter will spring organically out of working on what we want to create. When you encounter these roadblocks, the first thing you will want to do is use Google. These searches will typically take you to StackOverflow, MDN (if you are a web developer), or most fruitfully, some obscure and minimalist Unix enthusiast’s personal website.

The most common search you will want to make is “how to do x in y”. Practically, you can leave off the “how to” and just specify what you want to do and in what language. If we were working on the dummy text generator from earlier, we may search “random element from array in javascript”. If you perform this search, you will find an excellent solution in the first result.

This is the most effective process for self-directed learning that I have experienced. We have a project we want to complete, and working towards that is generating questions along the way. We put those questions in the search engine and seek out an answer. We apply the answer and come to understand why and how it works. Then, we continue working until we are presented with the next problem. Lather, rinse, and repeat.

Another effective strategy is to put errors into the search engine. This is not always as straightforward as the example above, but if you get an error you do not understand, you can typically copy and paste it in to Google. Make sure it does not contain any text which is specific to your program, or the results may be skewed. You will likely find people in similar situations receiving help from more experienced developers. Their situation may not be identical to yours, but by reading a couple of these you may realize where your error is. Resist the urge to ask directly for help if you have not thoroughly researched your problem. The solution to almost everything you will encounter at this stage is already out there.

If you encounter a roadblock and cannot solve it through searches, you may be tempted to reach out to the community for help. This is okay, but many beginners ask too quickly without taking time to understand their problem. This can lead to the same questions being asked many times, and those answering them becoming exasperated. There is a neat little trick you can use to get an answer of sorts from the community, without pestering them in real life.

When I get stuck I like to pretend, in my head, that I am asking a question on StackOverflow or IRC. I open a text file and begin to write my question. As I am writing, I imagine how I think community members will respond to my query. Usually, I can hear someone in my head saying “did you try x?”, where x is something I have not yet tried. I stop writing and try it. 9 times out of 10, I never actually end up presenting my question to the community. Simply the idea of having a second set of eyes on the problem leads me to the solution. We can get stuck in one way of thinking about a problem and be unable to see the solution, and this simple exercise serves to jolt us out of that mindset.

5. Use the Terminal

Many people are intimidated by the terminal, where programs are executed in a text interface. It is absolutely essential that you begin using the terminal as much as possible. Most of the programs you use now probably have GUIs, or Graphical User Interfaces. You click on buttons and fill in text boxes to interact with them. Under the hood, they interface with your operating system in the same way as programs in the terminal.

When it comes to running or compiling programs you write, starting and stopping servers, or managing your code with git, it is essential that you do these through text-based commands. There exist GUI applications to shield you from this reality, but they are counter-productive. The commands you issue in the terminal are in a programming language themselves, called Bash. By learning this language you can learn to automate your system in ways you never thought possible.

When I was starting out to be developer, I had never used the terminal. A mentor showed me some work he had been doing while using it heavily. I was mystified and intimidated by the rapid typing and text output flying by. I felt I could never learn to do that. I distinctly remember him telling me that using the terminal was “faster” than using a GUI. Faster? Could this really be true? I struggled to imagine how remembering and typing complex incantations to my computer could be faster than what I was used to — clicking around to files and applications, only typing when I was writing something.

Is there anything you do now on your computer that takes two, three or more steps? What about a time you had to do the same thing two, three or more times? The GUI user is stuck doing these tasks the same way they do everything — use the interface, point and click. Compared to this, the terminal user has super powers.

Commands in the terminal are programs themselves. Bash provides ways to link these commands together by “piping” the text output of one program to the input of another. Bash is also a language, so any amount of commands can be written in a file called a script and executed from there. Scripts can also contain logic like loops, if/then statements, and other traditional programming constructs. By using composed commands and scripts, you can do operations in a single line of Bash code that would take a GUI user hours. There is simply no competition.

Using the terminal is not only about efficiency, however. It is also going to teach you how your computer actually works. Even some experienced developers, if they are used to working with a specific set of tools, will have limited proficiency in the terminal. If you truly want to be a great developer, however, the skill and understanding to use the terminal effectively is something you must develop. How to do so is outside of the scope of this post, and there are great resources out there. Simply force yourself to use it, even if it’s uncomfortable, and look up anything you can’t figure out. Soon you will be mystified as to how you got anything done without it.

Don’t Give Up

If you have tried to use books and tutorials to learn development in the past, and feel like you failed, try applying these principles to direct your own learning. I believe that anyone with the right creative mind can teach themselves to build computer programs and applications, and doing so is one of the greatest joys in the modern age. All of the necessary information is freely available, and it only takes the right approach to digest and apply it. If you can eliminate your mental blocks and take action to start creating programs, you have the power to learn it fully and make it your career.

The Self-Taught Engineer

Eternally curious geek on a mission to empower people to create their own software for fun and profit.