Stevey's Drunken Blog Rants™
What exactly does it mean to practice becoming a better programmer?
Well, of course the boring dictionary definition is: "To do or perform something repeatedly in order to acquire or polish a skill." That definition feels a bit too narrow, though. I also want it to include the idea of studying, which the dictionary equally boringly defines as: "To apply one's mind purposefully to the acquisition of knowledge or understanding of a subject."
If you're still awake after that mind-numbing paragraph, then I think you're ready to give it a try! Studying has a weird way of putting me to sleep, unless I'm doing it because I want to. Homework just seems to kill the desire to learn. Don't read this blog if someone is insisting that you read it! Wait until you really think you want to get better at programming, then read it.
Incidentally, I toyed with the idea of coining a new word for "study and practice", like I did with servware. Unfortunately, "practudy" sounds like some sort of medical problem, and "studtice" is just unthinkably bad ("Honey, I'll be home late tonight -- I'm working on my studtice.") So for this essay I'll just use the word practice to mean study and practice.
Contrary to what you might believe, merely doing your job every day doesn't qualify as real practice. Going to meetings isn't practicing your people skills, and replying to mail isn't practicing your typing. You have to set aside some time once in a while and do focused practice in order to get better at something.
I know a lot of great engineers -- that's one of the best perks of working at Amazon -- and if you watch them closely, you'll see that they practice constantly. As good as they are, they still practice. They have all sorts of ways of doing it, and this essay will cover a few of them.
The great engineers I know are as good as they are because they practice all the time. People in great physical shape only get that way by working out regularly, and they need to keep it up, or they get out of shape. The same goes for programming and engineering.
It's a bit easier to tell if someone's in great shape physically than if they're in great shape mentally. You can't just stare at their brain and hope to find a six-pack in all those folds. It's easy to tell how physically fit someone is. You can make people run laps, lift things, take their physical measurements, etc.
But for determining someone's mental fitness, you pretty much have to interview them. It it's hard to do a good job of it, since it's like running backwards in front of the person, egging them to go faster. You have to be in pretty good shape yourself to be a good interviewer.
If you need a cornerback for your football team, of course you want someone who's in outstanding shape. But they also have to know how to play football -- and in particular, how to play cornerback. Great football players can sometimes play multiple positions, but most positions aren't naturally fungible; you can't usually take an offensive lineman and make him a great cornerback or quarterback.
There are some parallels here with finding great programmers. You want people who are smart, and also who have common sense (both the regular kind, and the software kind.) Smarts and common sense are equivalent to being in good shape, and perhaps having good reflexes.
But football -- well, if you know anything about American football, you'll know that it's a pretty rich sport. It's more like playing chess than playing soccer. It has elaborate rules; simply knowing the edge-case rules in the NFL rule book is a significant feat. It also has elaborate plays with amazing complexity and diversity, even though it just looks like guys hitting each other for 10 seconds at a time. And football has traditions, uniforms, statistics, all kinds of different coaching roles, referee organizations, tournaments and championships, aftermarket products, games and video games, specialized recruiters, specialized announcers... Football is a way of life.
So for that cornerback we need, is it good enough for him to be in good shape? Hardly. Maybe it's sufficient for a position on a high-school junior-varsity team, but Amazon's supposed to be more like the NFL than high school J.V., isn't it? I think so.
We hire for smarts and for skills. Well, we try, anyway. Sometimes, in a pinch, we'll settle for one or the other. Our hiring philosophy is that if someone is smart and motivated, then they should be able to make up for any particular skills they might be lacking, provided they have "enough" of the basic skills according to some ill-defined but hopefully intuitive heuristic.
As it happens, we don't get much time on the job to improve our skills. For the most part, it's up to us, as engineers, to take our own training into our own hands. Yes, there's some training, and there's some mentoring, and there are book club discussions and so on. But in the NFL, people practice daily. That's what practicing is all about -- doing things repeatedly, daily, habitually, to get better as fast as possible.
I doubt we or any company is likely to set up organized daily practice for their engineers. In fact I personally don't think it should be necessary. The most important thing you learn in college is how to learn on your own. They teach you how to research, and how to apply the scientific method and question your own findings, and they give you the fundamentals of math/language/social sciences/etc., so that when you want to learn something, you know how to figure it out for yourself.
Unlike the NFL, programming is a profession for which practicing is usually most effective if you do it alone, or at most with one other person. It requires quiet concentration and deep thinking, and you absolutely must solve the problems yourself, rather than just seeing the solution done for you. So even if we wanted to set up organized daily practice, most of it would be spent reading or programming quietly.
In a nutshell: if you're a programmer, you need to take matters into your own hands, and train yourself.
Programming happens to be a discipline in which you can squeeze practice drills into nooks and crannies in your schedule; you don't need to get into uniform and allocate a 3-hour session for it. That's why I'm offering you these practice drills. It's so you can practice the things you need to be good at in order to play on an NFL-quality servware development team.
Why bother practicing your skills if you've already made it past the interview, and you've landed yourself a job here?
Well, what do you suppose happens if you don't practice, and you gradually get all mentally fat and out of shape?
Easy enough to answer! Go to www.monster.com (or our resume pipeline) and look for SDE resumes from people with 20 to 30 years of experience. Well hey looky, they're mostly Fortran and Cobol experts, on IBM mainframes, and they've never done any web programming (or in fact anything you've even heard of before.) They don't even know Unix, which is only like 100 years old now, in dog years anyway.
Those folks, alas, are obsolete dinosaurs, and their programming knowledge is formally classified under "archaeology". They never pass our interviews, and they're becoming less and less able to find jobs. No wonder it's so hard to find senior SDEs -- most of them are just doing their jobs for 25 years, and now they don't know anything of value.
We do keep searching for senior SDEs, though, because every once in a while we find someone with great training and great experience and great practice habits. These folks are often phenomenal, and they make all the search efforts worthwhile.
Of all of your skills as a programmer, how many of them could be considered "timeless?" Face it: most of your technical knowledge has a shelf life, an expiration date. A good exercise (let's make it our first practice drill) is to enumerate all the skills you've acquired that are relevant to your job as a programmer. Sort them into two buckets, based on whether the skill will still be useful 100 years from now.
This drill will help you see where you need practice. It won't turn up your "blind spots" -- i.e., areas that you don't know anything about (hence aren't on your resume) but that you should know something about. But it'll at least help you see how current your working skillset is, and how long you expect it to stay current. And, hey, it's always nice to have an up-to-date resume.
What I think you'll likely find is that math, computer science, writing, and people skills are for the most part timeless, universal skills. Most specific technologies, languages and protocols eventually expire, to be replaced by better alternatives.
Technologies aren't replaced by switching them off overnight. Once a better alternative comes along, the original technology's usage follows an exponential decay curve, with a half-life: say, the time it takes for the technology to be used in only half as many places. And some technologies survive by evolving (XML is a good example); their half-life is the time it takes for your knowledge of that technology to become only half as valuable. With evolving technologies like Java or XML, your knowledge will decrease in value if you don't keep current.
So you need to practice -- not just to improve your skills, but also to keep yourself from becoming obsolete. Studying by itself doesn't cut it, either; you have to use a technology in order to gain any real familiarity with it. That's why this essay is really about study and practice. Great programmers do both.
The majority of programmers have literally no idea how to practice, since nobody teaches it. So they simply don't do it. The first step towards becoming good at practicing is knowing a thing or two about practice itself. Practicing for anything is generally best done via drills: short, high-intensity exercises designed to yield the highest return on the time you invest. In this essay I'll give you a dozen or so drills that you can practice, in any order, at any time, as often as you like. None of them should take more than an hour.
However, before I get into some standard drills that good programmers do regularly, I'm taking you on a quick detour, so we can look at how practicing works in professions that have been around for centuries. Why? Because those folks are pretty darn good at it by now, and they may have some lessons for us.
I've had a fair amount of classical music training, so I know how musicians practice -- and what differentiates the good ones from the bad ones. Because I used to be an extraordinarily bad one.
Picture the average amateur guitarist: A teenager. Messy hair. Cheap guitar. Plays alone, or for baked friends in bedroom in parents' house. Knows a few riffs, a few licks. Can play almost every track on the first two Nirvana CDs. Puts on a good show for an hour, if you're a forgiving listener.
OK, got it. The average guitarist sucks.
How does the average guitarist practice? In the years before I started getting serious about lessons, I played a lot -- 6 to 8 hours a day for about 5 years. I learned a lot of songs, all by memorization, and I had to play them constantly to keep them in memory, so at least 2 hours of every day was wasted just running through the pieces. Through brute-force effort I eventually started to sound like I knew what I was doing. Fooled myself and most of the people around me, anyway.
I was practicing WAY too much, and getting very little out of it.
I felt I could muddle through almost anything, but it was clear that I became progressively sloppier as the music became more technically challenging. And there were some things I just couldn't play. I could memorize them, sure, but I'd get halfway through them and my hands would just stop working, from sheer exhaustion. Then I'd watch professional guitarists play the piece (or solo, or whatever), and I'd be surprised at how effortless they made it seem. How could they be so relaxed?
The problem was that I had no idea how to practice correctly. The saying "practice makes perfect" is inaccurate, as any music teacher will happily tell you. Perfect practice makes perfect. I'd been practicing sloppily, and had become very good at being sloppy. For one thing, I was tensed up, trying to force my fingers to make the right moves. So I only knew how to play tensed up, which exhausts you quickly. I was actually doing all sorts of things wrong, more than I'd ever have guessed, but the details aren't important. What's important is that I was thinking about it all wrong.
I knew that everyone said you should take lessons, but I had convinced myself that I didn't need them. I was actually a bit afraid to take lessons, because instructors were telling me I'd have to "forget everything I knew and start from scratch." That was a stupid way to attract new students! Nobody's going to want to throw away years of work. It was also incorrect: lots of the stuff I knew carried forward. Learning the proper technique turned out to be more like learning a new song than learning a new instrument. But at the time, I thought: "Screw that. I know how to play guitar. I'm happy with my playing, and I'm not going to change the way I play."
I hope you don't think this discussion is too far afield, because my attitude towards guitar lessons was identical to the way most programmers feel about their technical skills. "I'm already great at Perl, so I don't want to go back to the beginning and learn C, or assembly-language. I like the way I program." Or: "I'm great at Java, and I don't see any reason I should have to learn how to write scripts. I can get by just fine without them."
The thing is: I wasn't a great guitarist, and Perl-only folks aren't great at Perl. But you can't see that until you've done the hard work of learning what your instructors are telling you to learn.
Simply thinking about good programmers you know, and what makes them good, is good practice in itself. But we'll also use the results of this drill in some later drills.
Anyway, let's compare the average guitarist's practice techniques (and philosophy) to the way real musicians do it.
Professional musicians have such a rigorous practice methodology that it takes a while to fully comprehend it, let alone apply it. To get the full picture, you need to take lessons from different people, watch other musicians (both good and bad ones) practice, and experiment a lot.
This isn't unique to music. People practice rigorously in other disciplines too. Take golf, for instance. Even Tiger Woods still takes regular lessons. He's working more on course management than on his swing, of course, but he still takes lessons. In hyper-competitive disciplines, even the practice techniques themselves are improving over time.
Real musicianship is the result of studying and applying the theory, history, and performance of music. Many musicians also advocate studying the physics of sound and music, the construction of musical instruments, the mechanics the human hand and ear, and the psychology of performers and audiences.
The average guitarist is no more aware of these sub-disciplines than your average laborador retriever. I sure wasn't. I just wanted to play guitar. Remember that awful Antonio Banderas movie, The Mask of Zorro? Yeah, I know. Painful. But at one point, Anthony Hopkins asks Banderas if he knows how to use a sword, and Banderas replies: "Yes. The pointy end goes in the other man." That remark actually hit home. It's right around the level of sophistication you find in the average guitarist, and (alas) in the average programmer.
Music theory is rich and complex. Most guitarists don't see any reason to bother with it, since you can "get by" without it. (I detest that phrase. Saying you can "get by" without learning anything new is a sure way to make my eyes glow red.)
Yes, you can get by without knowing any theory. But your playing is just parroting if you don't understand how the piece was constructed. Knowing music theory can improve your playing in a hundred subtle ways, with the net effect being a much more professional performance.
Real musicians read sheet music almost as easily as you and I read English. (Better, for some substitutions of the variable "you". Not you, of course. Other yous.) It's amazing to watch. But most guitarists can't read sheet music. Instead, they use a crude pictogram notation called "tabulature", which doesn't contain enough information to know how to play a piece without hearing it first. It's as lame as it sounds, trust me. Being able to read real sheet music means you don't have to worry as much about committing pieces to memory. It also gives you access to a lot of great music that's never been recorded.
Sheet music is also beautiful in its own right.
Musicians study the history of music for many reasons. One reason is simply to know why things are the way they are. Another is to learn about great past Masters and their extraordinary abilities, and perhaps set higher personal goals. Mostly, though, it's a matter of culture. All the best musicians are totally immersed in the musical world. The best musicians share ideas and push the envelope of their field; music history gives them a vocabulary and a set of examples to draw on when fleshing out new ideas. Knowing your history is important for innovation.
The history of programming, incidentally, is absolutely fascinating. They were solving problems 30 and 40 years ago that are completely relevant to our work today, and most of us (me included) still don't understand the solutions. The pioneers of Computer Science -- the Donald Knuths, the Von Neumanns, the Dijkstras and Hoares -- these folks are geniuses, like the Masters of music, and it pays to study their work and their lives. The history of our field makes for a a richly rewarding study.
If you run out of people to read about, there's also a list of computer scientists. Spending a few hours a week in Wikipedia is a fun, easy way to get a feel for our field and related fields. Make sure you pay attention to the the history and the people. Makes it more fun.
Finally, there's music practice. There are sooo many types of practice. The common characteristic among them is that practice has to be habitual. Professional musicians develop daily and weekly practice habits that they keep up for their entire careers. Practice requires a recurring time commitment.
One type of practice is simply to go listen to other musicians play, as often as you can. You'll learn a lot just by watching and listening. The analogs in the programming world are watching other people program, and reading their code.
Another kind of musical practice, useful for avoiding memory lapses during recitals, is to close your eyes and envision yourself playing the piece, measure by measure. It helps to try doing the measures out of order -- starting at arbitrary points, working backwards, etc. The point is to build up multiple mental models of the piece, to gain a more complete and robust understanding of it. There are analogs for this in programming that I'll cover in some drills later on.
A lot of practicing, of course, involves actually playing your instrument. I bet you thought I'd never get to that. But first (ha!) you need to learn a bit about the instrument's physical characteristics: how it responds to temperature and humidity changes, how the response decay varies with pitch and octave, how the strings sound when struck in different places, even how the instrument responds to the friction of your clothes. It'd be kind of embarrassing to drop the ol' guitar in the middle of a performance. But not as embarrassing as having your zipper scratch a $9000 guitar you haven't bought yet.
Heck, even tuning a guitar isn't a simple proposition. After you change a string's tension, it will stretch or contract slightly over the next few minutes in the direction opposite to the change you made. And you have the Pythagorean Comma to worry about; tuning an instrument "perfectly" is actually a physical impossibility, so you have to figure out how to strike the right balance for whatever key you're playing in. You could write a 30-page manual on the art and science of tuning a guitar.
Why am I belaboring the tuning thing? Because learning how to tune your guitar properly is basically a tools issue. Many guitarists are perfectly happy to get by with poor tuning, but then they sound bad even if they're playing well. Developers are often content to use whatever tools they've got, without digging in and figuring out how to "tune" the tools for maximum efficiency. Mastering the tools of the trade is an important part of every professional's ability to be effective.
By starting with the tools you already love using, it'll be that much easier to get into the habit of exploring their capabilities.
And finally, real musicians don't practice by playing the piece over and over from beginning to end. They dissect every piece of music into tiny components and work on each one individually -- every phrase, every note, every fingering, every transition, it's all worked through, mechanically and musically, for countless hours. They play it slow, fast, quietly, loudly, even in different time signatures and beats. And they do daily drills: right- and left-hand finger exercises for building stamina and dexterity.
Sound like a total pain? Actually, it's not too bad at all. Takes a bit of getting used to, but once you start doing it right, your overall technique improves rapidly. And you're no longer "capped" at a particular difficulty level, because you're not exhausting yourself, and you know how to tackle complex technical passages. Oh, and one hour of that kind of practice is as good as a week of playing songs over and over.
OK, enough about music already. The takeaway is that musicians have built up intricate and very effective practice techniques through centuries of experimentation. It takes formal instruction and a fair amount of personal discipline to master professional practice techniques. You wouldn't think of most of them on your own, at least until you get the feel for the overall goals of the practice.
We don't have centuries of accumulated experience about programming, so we're still sort of feeling our way along. But programming is a clearly a complex blend of art, science, logic, engineering, design, and craftsmanship, and we can borrow ideas from all those endeavors.
Hopefully I've convinced you that you can't become world-class (or even a competent professional) in any profession, including programming, without making a serious commitment to ongoing study, training, and practice.
You already knew that, though. The fact that you've read this far into my crazy blog means you're probably already the type who practices a lot. Or you like to read about it at least, like that Dilbert where he's reading a book about driving the cart around in a golf video game.
Now, with your new-found insight, go chop a brick in half with your hand! Ouch. Better yet, go play some Doom 3. You can't study all the time.
One of the best ways to get better as a programmer is to participate in the recruiting process: resume screening, phone screening, interviewing, having people mock-interview you, coming up with new interview questions, solving other peoples' interview questions yourself, all that stuff.
Of course, if you just ask the same questions in interview after interview, you're not really practicing, and it won't help you much.
Here are some recruiting-related drills. Just fer fun 'n stuff. Is anyone really still reading this thing? You probably all think I've cracked. But read on! I believe I can make the unqualified promise, with no hedging whatsoever, and backed by my personal guarantee and my word as a sportsman and a gentleman, that this essay will eventually end.
Resume screening is a useful practice -- and not just for the comic relief, although that's certainly one of its draws. It's also useful so you can see what people in your industry are doing these days. Unemployed ones, anyway. And if you see a particular buzzword appearing more and more often, it's a sign that you might want to look into it, and see why it's popular.
Group resume screens are way more fun than doing it by yourself, and probably more accurate as well. You need at least four or five people, though. The discussion keeps you from falling asleep.
Phone screening is really hard to do well. It may not actually be that useful for improving any skills other than phone screening. However, recruiting is an important part of every programmer's job, so you should do phone-screens occasionally.
For the drill, we'll just have you listen in on someone else's phone screen. That way you might hear a question you don't know the answer to, which gives you something to go study.
And, of course, go figure out how to solve anything the screener asked that you didn't know the answer to.
Incidentally, I sometimes listen in on phone screens, and I bring a pen and paper, so I can doodle during the boring lulls, where the screener is saying loudly into the speakerphone: "Did you say paren paren backslash slash? Or was it paren paren slash backslash slash?" I'll use the pen and paper to experiment with solutions to some of their questions, as well as take notes on the screen.
Interviewing is absolutely one of the best ways to improve your own technical skills.
For one thing, it requires you to invent and present challenging technical questions, then conduct deep-dive discussions of them with interview candidates. That's just plain good exercise.
For another, you can ask candidates to teach you new stuff. For instance, if they did a Masters thesis or Ph.D. on some exotic-sounding CS subject, you might have them try to explain it to you. If they do a great job, well, you'll have learned something new! And if they do a terrible job, you'll at least have learned something interesting about the candidate -- namely, that they can't explain something they know well, which implies that they may not understand it very well.
It doesn't necessarily have to be a thesis topic. You might run into a domain expert in a domain similar to one you're familiar with. For instance, if you're interviewing an SQL Server expert, you might ask how SQL Server handles a particularly thorny problem you've experienced with Oracle. Or if you're interviewing someone who's a fan of a technology you haven't heard of, you might ask them to give you a high-level overview of it.
Interviews can basically be free education, and you might as well take advantage of them.
Sometimes their explanation is just gobbledygook, and I don't get much out of it. That's usually because it requires more math than I have handy, so I'll spend a day hitting the math books after that happens. (It's never enough, but it's good practice anyway.)
Sometimes you'll be able to follow them, ramp up quickly on the idea, start probing in complex corners, and wind up with a really good discussion. Or sometimes you'll find the candidate can't answer even trivial questions about the subject, which can be useful data for the interview.
Pair-interviewing is also useful. All you need to do is listen in while someone else conducts the interview (although sometimes pair interviewers divide up the questions, or give each other a chance to ask stuff.)
Pair interviewing is great because it gives you new questions to ask, and it shows you new approaches to managing the flow of the interview. Everyone runs interviews a little differently, and being exposed to multiple styles will make you a better interviewer.
Nowadays I make it a habit to try to invite someone to every one of my interviews.
Some people do Mock Interviewing to hone their skills. You just pick a random person and have them ask you an interview question, and solve it right there on the board. If you fail the question, you have to go read up on that area. No big deal.
Ron Braunstein comes into my office every two or three weeks, writes a problem on the board, and asks me to solve it right then and there. (I do the same to him almost as often.) It's usually a problem that he just finished solving, and thinks it might be an interesting interview question or programming challenge. I work through it, then we talk about it and compare our approaches.
You should do this once in a while. It's good for you. Sometimes you'll do great, and sometimes you'll get stuck. Just like in real life.
If your buddy's questions are always too hard, my recommendation is to find yourself a new buddy. It can be a bit deflating when your buddy votes not to hire you 3 or 4 weeks in a row.
One last interviewing-related drill: make sure you can solve any coding question that another interviewer asks. I overhear interview questions occasionally that I'm not immediately sure how to solve. I file them away and go implement them later in the week.
If you struggle with it, e.g. it takes more than an hour, you may have a gap in your knowledge, which is wonderful, because now you know and can fix it. However, it might also mean that the interview question is too hard. You might bring it to a Bar Raiser or another experienced interviewer and ask them if they think it's a reasonable SDE interview question.
I was planning on trying to make up 20 practice drills, but the effort basically killed this blog entry. It sat unfinished for over 2 months. Instead, I'll stop at a dozen, and maybe mention some more drills in a future blog. There are plenty of others, but hopefully this gives you a few to work on.
If you have ideas for other practice drills, feel free to submit them in the comments section. I'm willing to try anything that's worked well for others.
Dave Thomas has a long blog thread on practicing programming. This gives 21 suggested exercises, or 'code kata'.
On the music side of things, I'm learning to play piano, and teaching myself because two years of lessons did nothing but lighten my wallet. It seems that practicing techniques are still fairly hotly debated even now; some people maintain that non-musical drills such as those by Hanon and Czerny are worthless; it's better to use, say, Bach Two Part Inventions or Chopin Etudes, because technique should never be divorced from music.
Personally I found this free online book immensely helpful: http://members.aol.com/chang8828/contents.htm
(He has a good reviews second, where he recommends other materials; I went with Seymour Fink's book, and I'm about to buy the 'Freeing The Caged Bird' video.)
Also, I found this book reading this book right now, which combines elements of Tai Chi and Feldenkrais and an apparent unification of the arm-weight/finger-movement schools. The author is a bit full of himself, but the first couple of chapters (on the bus this morning) were good. I guess I should blog this...
Posted by: Chris N. at January 24, 2005 09:23 PM
Another article worth reading along the same lines is Peter Norvig's Teach Yourself Programming in Ten Years.
Posted by: Daniel C. at February 4, 2005 11:46 PM