On the fundamentals of programming
Let's start with a story.
I am a volleyball fanatic. I enjoy the game in a way that borders on obsession. Lately I play three times a week for hours at a time. Now, my position is known as middle hitter. As you might have guessed, I'm the guy who stands in the middle of the court and tries to pound the ball through the other team's floor.
A few months ago, I was going through an athletic crisis. Despite many hours of play I still wasn't that good at hitting. In fact, I kinda sucked at it. My other skills were decent, but when it came to spiking the heck out of the ball, something wasn't right. I just wasn't getting the power other people were and I didn't know why. I experimented constantly: different arm swings, changing my hand shape, snapping my wrist. Nothing worked. Sad and ashamed, I enrolled in a clinic hoping to cure my hitting dysfunction.
On the first night, the coach ordered us into a hitting drill. No problem. I'm focused, I'm ready; I'm going to crush this ball. I went up for my approach and, well--tapped--the ball over the net. Not impressive. I tried again but with similar results. Discreetly, the coach pulled me aside:
"Did you know you're taking an extra little hop before you jump?"
"I am?"
"You are. It's taking away all your momentum so your jump is all wrong. Get rid of that and try again."
On my next attempt, the set was perfect: high and tight, and I smacked it the same way you'd high-five your grandmother. But that time, I felt the extra hop I was taking. Suddenly it was so obviously there.
I lined up once more. I took three strong steps, leapt in the air, and pounded down the best shot of my life. WHAM! I was elated. The problem I had with hitting was simple: I was deficient in the fundamentals. Everything I'd been tweaking was the minor stuff. Fundamentals are the rock-solid road bed you build on. I'd been rearranging the mile markers on a strip of sand.
The point here is important: mastery of any complex skill requires mastery of its fundamentals. I think this idea just might tell us why there are so many bad programmers out there. And I also think it tells us it's our fault.
How does one acquire the fundamentals of programming?
I don't think the answer lies in obtaining a computer science degree. I once interviewed a recent MIT graduate who'd majored in computer science. She was articulate, had a strong GPA, and couldn't write the pseudocode to sort an array. Really. This is actually a familiar phenomenon. A CS degree tells you how, theoretically, you might spike a volleyball, but that doesn't mean graduates have ever actually hit one. Of course computer science isn't really about programming, it's not even about computers. Now, there are lots of strong coders with CS backgrounds, but that strength is almost always acquired through their own work--they are self-taught.
Academia isn't much help, so we're going to have to become deadly code-ninjas on our own. Fortunately, there is a wizened master who can point us in the right direction: Peter Norvig, whose essay "Teach Yourself Programming in Ten Years" wins my personal Nobel for Programming Literature. It's probably the best advice out there on the subject, and we'd all do well to follow his recommendations. However, despite the fact that Peter is so smart his brain has its own gravitational pull, I think his essay glosses over an important point.
Let's look at the main thrust of Norvig's advice:
Program. The best kind of learning is learning by doing. To put it more technically, "the maximal level of performance for individuals in a given domain is not attained automatically as a function of extended experience, but the level of performance can be increased even by highly experienced individuals as a result of deliberate efforts to improve." (p. 366) and "the most effective learning requires a well-defined task with an appropriate difficulty level for the particular individual, informative feedback, and opportunities for repetition and corrections of errors."
This is clearly good advice. Surely that MIT graduate could have written me that algorithm if she'd, you know, written code before. But check out the quotation Norvig cites. Where exactly does one find well-defined programming tasks of an appropriate difficulty level? How about informative feedback and corrections of errors?
Well?
It turns out that there's a shortage of things like this for programmers. Especially new ones. This is a serious problem, and it is this I blame for the huge numbers of coders who lack the fundamental skills of our craft. Worse, this is our own fault: only people already skilled in an activity can devise effective training for newcomers. Even worser: when you lack skills in the fundamentals you almost never know it. I had no idea why I couldn't spike a volleyball.
So how do we fix this? We do what all great thinkers do: steal a great idea from somewhere else and reuse it. So here's my solution, shamelessly grabbed from a different, but related area of my life:
To become a better programmer, one should practice like a musician.
Bear with me...
A beautiful piano sonata is the product of thousands of perfectly executed notes. If even one note is misplayed you have cacophony. However, the consideration of individual notes never enters my mind while playing. Instead, I'm thinking about making the phrases flow together, the winsome arc of the melody, or keeping the steady beat of the bass line. It is these things that create music from mere notes. I'm able to think of these things because my mind is free from worrying about playing individual keys, and my mind is free because of my mastery of the fundamentals. The study of classical piano (and every other musical endeavor) devotes ample time to performing exercises. There are perhaps hundreds of books full of them. Compared to a real piece of music they are simple and repetitive, but each exercise isolates and drills a vital skill. This focused practice makes such skills automatic--I can play a very fast run of notes smoothly and accurately because I've quite literally practiced it thousands of times. I no longer need to think about it. Because of this, I am a better pianist.
The application of these ideas to programming should be clear. When I'm focusing on the overall musicality of a piece, I'm operating at a higher level of abstraction. Individual details have faded away, and I'm able to focus on making something beautiful. The same skill is required for creating beautiful programs. If you must spend brain cycles struggling with minute implementation details you have no hope for making your solution elegant.
So let's take this musical idea and alter it slightly. After all, when it comes to programming exercises, coverage is more important than repetition. Not remembering how your language retrieves values from a hash is far less damaging than not knowing hashes exist in the first place.
Fortunately, I can already point to an excellent example of these sort of problems. I believe newcomers would learn more about programming per unit time by working through Ninety-nine Prolog Problems than almost anything else. (Replace Prolog with your language of choice). With the ability to check your answers and also post questions on a wiki, we've even covered the "correction of errors" and "informative feedback" requirements mentioned above. Also excellent is The Python Challenge, a series of riddles with programmatic solutions that get progressively harder over time. The site is massively popular and makes people better programmers. Truly, this is a phenomenal start, but there's much more to be done.
So how about it guys? What are the first fifty programs someone should write to break out of that painful newcomer phase? What topics would they definitely have to cover? Later, what programs must one write to reach hacking virtuosity? I also like to think about this a different way: what problems would you be embarrassed to tell your coworkers you can't solve?
I think these questions are important, and they just might help improve the overall quality of programmers out there. If you accept programming as an art, why don't we treat it like one? Let's start practicing like musicians, and maybe we can create something beautiful.