Learning the craft
I went out to dinner with an old programming friend the other night, and as all old programmers do, over our Chillis burgers we started swapping war stories about the systems and projects we'd worked on. Neither of us had a formal computer science education, and as we ended up comparing great computer related books we'd both read, it started me wondering, “How did we learn this stuff ?”
Like anything that requires skill, programming is one of those things it's hard to do as “just a job”, clocking in Monday to Friday. At least it's hard to do well that way. The best programmers I have worked with have an obsessiveness about them, a desire to create perfection within the machine. It's probably why promising young programmers are so easily persuaded to work punishing hours for a start-up by smart business people who know how to motivate them, not by money but by interesting work.
I ended up in programming by accident, as many do. I was studying for a PhD and having to write software as part of the studies, only to find that writing the software was more interesting and fun than finishing the PhD. So I ran away and joined a small software house. But having arrived there, knowing barely more than assembly language and FORTRAN, how should I learn more ? And what if the other programmers found out how useless I was ?
Find yourself a mentor
I was lucky. The senior programmer I worked with had an amazing talent. I was so intimidated by him. He'd written his own Forth interpreter in Z80 machine language, and was a published adventure game author. I was so intimidated by him that initially I was frightened to ask questions in case he'd discover how little I knew. I used to listen in on conversations he'd have with his other knowledgeable friends and pretend I understood what they were talking about and I wouldn't look so ignorant. After work I'd go home and try and look up what they were talking about at the local computer bookshop (this was way, way, before the Internet and easy search engine availability).
Eventually I realized that I wasn't learning much. So one day (and I still remember the cold chill I got in my gut just before doing this) I simply interrupted his conversation with a “excuse me, I don't understand what you just said, can you explain it to me ?” I stood there waiting for the earth to swallow me up, or at the very least for him to unleash lightning bolts from his heights on Mount Olympus. To my complete surprise, he simply said, “oh, OK. What I meant was..”, and proceeded to explain in clear and full detail the technique he was discussing.
From then on I was hooked. I asked him anything and everything about programming, and he was happy to teach me. Since then I've discovered that the most talented programmers love to share what they know with younger colleagues. The old adage “the only stupid question is the one you don't ask” is really true. People love to share their area of expertise so don't be afraid to bug them to learn what you need to know (within reason I hope).
He also knew C. When I asked him how he'd learned C he told me he'd picked up a little book called “The C Programming Language” by Kernigan and Richie (who were the original authors of the language) and it was pretty simple once he'd read that. Anyone who has read this book themselves will realize just how good this guy really was, as it's an incredibly terse read. It tell you everything you need to know about C, but only once. No repetitions, not much in the way of examples and a crisp and functional style. But it's one of the classics of computer science literature.
Which brings me to my next point.
Read the right books.
Of course, when I say “books” these days I also mean Internet references. Even if you studied computer science your course notes are no match for the tomes of wisdom to be found on Amazon or your local bookshop. Once I found the classics of computer science I never looked back. I bought myself copies of Knuth's classic “The Art of Computer Programming” and started to haunt the computer bookshops in Sheffield, UK, avidly looking for my next fix of new information. The books I bought there ended up sending me to the USA for a programming job (the dream of any northern English lad in those days, I wonder if it still is ?). I still remember coming across W. Richard Stevens “UNIX Network Programming” and realizing I'd found a gem. Everything else he ever wrote was too. The book that got me to the USA was Asente and Swick's “X Window System Toolkit”, which I still refer to as the gold standard in how to document the internal and external API's of a programming library. The knowledge I learned from that book got me the job in Silicon Valley. Any of Andrew Tanenbaum's books are must-purchases too.
I ended up buying a lot of crap too. The problem is (and to a large extent still is) that it's hard to evaluate books or text to discover if they're any good until you've read them and tried to implement the techniques they're talking about. A lot of books look good on the surface, but actually are rubbish in disguise. How do you determine the wheat from the chaff ?
These days, for a UNIX system programming book I look at the section on signal handling (sorry for getting technical here but there's no other way to describe this). As signals are asynchronous (like threads) and so if you ever see a printf() call in a signal handler to demonstrate it being invoked, hurl the book across the bookshop with great force and never buy anything from that author again. It'll teach you to write code that will randomly fail in the real world.
After I moved house recently I finally dumped about three hundred books on the second hand bookshop in Mountain View. I realized I no longer need to keep references for old API's and libraries that you can now look up on the Internet. It was like saying goodbye to old friends, but I needed the room.
Read code. Lots of code.
Before the advent of ubiquitous Open Source/Free Software this used to be hard to do. I had to learn by reading the internals of Sun's (my employer at the time) X Windows libraries and Solaris kernel code. These days there's no excuse for not looking at the multi-millions of lines of high quality code free to review from the Open Source/Free Software communities. I know this is an obvious one, but most of the techniques I use and apply every day are things I first read in other people's code (this is one of the reasons software patents are so insidious for programmers). Occasionally you'll do something new, but mostly you'll just be applying the work of others in different ways. In fact, if you have to invent a new technique you're usually doing something wrong (unless you're really, really, good). Remember Pablo Picasso “Good artists copy. Great artists steal.”
Change jobs often.
Unless you're working for IBM (or I guess Microsoft these days), you'll never be in the sort of organization that has the breadth of interests you'll need to learn what truly interests you. Even if you are working for the aforementioned companies, you'll never be in the position to move across all the product groups you'd have to join. Once you find success, you'll get stuck. I was not originally known as a network or Windows interoperability engineer, I was a graphics wonk, working on X Windows. Until I left Sun Microsystems and went on an odyssey though the “Silicon Valley of Startups” here in California I never got the chance to learn about compilers, C++, Microsoft Windows system programming or ultimately the details of Windows interoperability (where I've found a happy and productive home). I worked a lot of hours, got issued a lot of worthless stock and got burned by many sleazy venture capitalists but more importantly I learned a lot about the incredibly interesting job of computer programming.
Let me know what you consider the most important elements of learning the craft, I'd love to hear from you !
San Jose, California.
6th September 2008.