The best way to prepare [to be a programmer] is to write programs, and to study great programs that other people have written. In my case, I went to the garbage cans at the Computer Science Center and fished out listings of their operating system.
Newcomers to the open source world often find that their questions are answered with the phrase “Use the source, Luke.” This expresses a fundamental truth about software: the code is the ultimate arbiter. The programmer’s intentions are irrelevant if the code disagrees. Only by reading the code can one truly understand a system.
Without exemplars of good practice to study and emulate, the Practice, Practice, Practice pattern only entrenches the bad habits you don’t know you have. If you never walk a mile in someone else’s moccasins, you may come to believe that all shoes are meant to have stones in them. So how do you find out if your work is any good, given that those around you may not have the ability to tell good code from bad?
Seek out other people’s code and read it. Start with the applications and tools you use every day. As an apprentice, one of the beliefs that can hold you back is the idea that the people who built the tools that you depend on are somehow different or special or better than you are. By reading their code you can learn to program like them, and more importantly, you can start to understand the thought processes that created the infrastructure that surrounds you.
When examining an open source project, get in the habit of downloading the current version of the source code (preferably from its source control system) so that you can inspect its history and track future progress. Examine the structure of the codebase and try to work out why the files were laid out that way. See if there is a rationale behind the way the developers modularized the codebase and compare it to the way you would have done it.
Try to refactor the codebases in order to understand why the programmers made the choices they did, and to see what the consequences would have been if you had been the one writing the code. This doesn’t just give you a better understanding of these projects; it also ensures that you can build the projects. And if you find a better way to do something, you are in a good position to contribute.
As you work through the codebase, you will inevitably come across decisions that you passionately disagree with. Ask yourself if perhaps the developers knew something you don’t or vice versa. Consider the possibility that this was a legacy design that needs to be refactored away, and think about whether putting together a toy implementation of the feature might be educational.
In addition to reading other people’s code (and, where requested, providing feedback), try to find people around you who are interested in reading your source code. If you can learn to embrace their feedback while filtering out personal idiosyncrasies, you will become a better programmer. And remember, to become a journeyman you have to help others grow, so be open to reading other people’s source code as well.
A common approach among the programmers we interviewed involves joining a team or project that uses code reviews or pair programming. These practices create environments in which the programmers could safely spend time reading other people’s code, having others read their code, and learning from each other. These groups tend to produce extremely strong programmers. Other environments, such as most academic computer science departments, tend to overlook the fact that working programmers spend far more time reading code than writing code. They take this approach because making every student reinvent the wheel creates artifacts that are easy to grade. However, training yourself to be better at the task that takes up most of your working day is an optimization that yields greater rewards in the long run. This is true even if the nonprogrammers who are often in charge of these environments don’t appreciate it.
By reading a wide variety of good, bad, and indifferent code written by other people you can start to learn about the idioms and subtleties of your particular language community. Over time, this will develop your ability to divine people’s intentions from the code they have written. It will also help you learn to deal with those occasions when the two have diverged. These skills will make you a more valuable part of a team, because you’ll be able to work on other people’s code without always having to rewrite it because you can’t tell what it does.
Eventually you’ll acquire a toolbox of tricks and subtleties gleaned from other people’s code. This hones your ability to solve small problems quickly and easily, just because you’ve seen something similar before. You’ll be able to tackle problems that others consider impossible because they don’t have access to your toolbox.
Take a look at Linus Torvalds’s code for the Git distributed source control system or anything written by Daniel J. Bernstein (commonly known as djb). Programmers like Linus and djb casually use data structures and algorithms most of us have never even heard about. They’re not magicians—they have merely spent time building a bigger and better toolbox than most people. The advantage of open source is that their toolboxes are open for you to inspect, and you can make their tools your own.
One of the problems with the field of software development is the lack of teachers. But thanks to the proliferation of open source projects on sites like sourceforge.net, GitHub, and Google Code, you can learn from a more or less representative sample of the global community of programmers. Unlike in traditional teaching, these are not toy projects designed to illustrate a point, rife with shortcuts and “exercises for the reader” when things get difficult. These are real projects that solve real problems and are constantly in flux. You can track a project as its developers learn and adapt to new requirements. By studying the way real codebases evolve, you can better appreciate the effects of design decisions without having to build hundreds of software projects yourself. This offers an opportunity to learn from other people’s mistakes and to acquire a more vital skill than mere code reading: the ability to learn without being taught.
In Programmers at Work, Bill Gates said that “one of the finest tests of programming ability is to hand the programmer about 30 pages of code and see how quickly he can read through and understand it.” He had realized something important. People who can quickly absorb knowledge directly from the code soon become much better programmers, because their teacher is every line of code written by every programmer ever born.
Pick an algorithmically sophisticated open source project such as a source control—system, for example, Subversion, Git, or Mercurial. Browse the project’s source, noting down the algorithms, data structures, and design ideas that are new to you. Now write a blog post describing the architecture of the project and emphasizing the new ideas you have learned. Do you see places in your everyday work where the same ideas can be applied?
 Keynote at Ruby Hoedown 2008. Video at http://rubyhoedown2008.confreaks.com/08-chris-wanstrath-keynote.html. Transcript at http://gist.github.com/6443.