Coders at Work is a compilation of interviews with some of the most influential programmers of our time. It would make for a very nice podcast series or audiobook, but I prefer reading so I got the Kindle edition. It is a big book, all the conversations are long and go deep in many subjects, all revolving around the art and craft of programming.
Speaking of which, we are still debating about what programming really is and what it is most similar to: is it an art, a craft? Is it engineering or a science? Is it a mix of some of these or none of them? This debate, is such a central question because programming is something very new: “computer programming has existed as a human endeavor for less than one human lifetime: it has been only 68 years since Konrad Zuse unveiled his Z3 electro-mechanical computer in 1941, the first working general-purpose computer.”
Perhaps Time will give us a nice definition at some point but I wouldn’t count on it. Programming is a journey that has no end, it is like the proverbial mountain without a top. There’s no finish line. That’s the beauty of it. And, while attempting to give a precise definition might be an impossible exercise, we can still find patterns and grasp its essence not only by our own experience but by reading about those who have made of it a long and fulfilling career. This is what I set out to do when I sat down to read this book.
Seibel did an amazing job in selecting his characters. There is a good range of hardcore coders and hackers along with more theoretical and scientifically-minded ones like Peyton Jones. But, regardless of the interview, there are common themes that captivated me. For example, most of the interviewees see formal proofs as something like a toy to play with. Proofs are nice and interesting as an object but almost nobody uses them in real life because they are impractical: they require sophisticated theorem provers and code annotations that might contain errors themselves, making proofs hard to prove.
One of the most inspiring aspects is the doer mentality of all the subjects. Peyton Jones, recounting an episode early in his career tells us to “just start something, no matter how humble.” Zawinski—one of the first engineers at Netscape—tells the story of how they shipped their first version: “We were so focused on deadline it was like a religion. We were shipping a finished product in six months or we were going to die trying”.
There is also a learning aspect of this mentality. All agree that the way you learn programming is by doing. Zawinski learned by “taking something apart and looking at it.” And Brad Fitzpatrick said “you never learn something until you have to write something in it, until you have to live and breathe it.”. In programming—as in life—there are few or no shortcuts, we all must put in our work.
Barred a few subjects, most of the coders in the book started their careers when computers were big and slow and had to be programmed by punched cards. So it is no surprise that their choice of tools is Spartan. Douglas Crockford tells us that “I use a little freeware text editor. It doesn’t do anything tricky. That’s about all I need.” Donald Knuth even wrote his original version of Tex by hand—pencil on paper—before he started typing code in a machine.
This is telling. Nowadays there’s a myriad of tools. From Integrated Development Environments to no-code programs, to fancy text editors, new programmers can suffer from decision paralysis even before they start typing code. In my experience, some of these tools can be useful. An IDE, for example, simplifies things and helps you debug a very big project. But most of the time you can easily write your programs in a text editor without too many blows and whistles. Something like Vi, ViM, or Emacs will get you 99% of the way.
If I would be giving advice to my younger self I’d say: “Master one terminal-based editor. They are Lindy. They have been around for 30+ years so they will be around for 30 more. But don’t be religious about them. Different tools can give you different perspectives and advantages. Learn to exploit them”.
Like it or not, debugging is every programmer’s bread and butter. Programmers spend a lot of their time debugging programs, that is, they spend a lot of time looking for and fixing errors in the code. It is no surprise then that a lot of the conversations in the book revolved around debugging. Siebel managed to ask very good questions around this topic and always extracted important insights into how this set of world-class programmers goes about finding and fixing errors in their programs.
It surprises me though that many didn’t think much about testing. While testing is now viewed almost with religious zeal at some companies and some projects boast 99% code coverage (this means that 99% of the code is reached by at least one test), almost none of the subjects thought of testing as something fundamental to do. For some, like Zawinsky testing is simply something that most of the time you can’t afford if you want to ship products:
“I hope I don’t sound like I’m saying, “Testing is for chumps.” It’s not. It’s a matter of priorities. Are you trying to write good software or are you trying to be done by next week? You can’t do both. One of the jokes we made at Netscape a lot was, “We’re absolutely 100 percent committed to quality. We’re going to ship the highest-quality product we can on March.”
Others, like Brendan Eich, appreciated it more: “I think what I’ve learned with Mozilla and Firefox has been about more test-driven development, which I think is valuable. And other things like fuzz testing, which we do a lot of.”
When it comes to debugging there is more consensus and can be summarized with this passage:
“The great gods of programming said, “Thou shalt put printf statements in your program at the point where you think it’s gone wrong, recompile, and run it.”
Everybody agrees that debuggers can be useful but most didn’t count on them. This can be attributed to two things. The first is that most of the subjects learned to program while the discipline was very new and there were no tools, there was no debugger for assembly or punch cards, print statements were the debugger. Second, perhaps Joe Armstrong’s Law of Debugging, which states that “all errors will be plus/minus three statements of the place you last changed the program”, is true and using print statements is easier and faster most of the time.
If you’re not convinced by this, and you can’t live without a debugger, take the example of Ken Thompson, who wrote a lot of the code that most of the world runs on today: “Mostly I just print values. When I’m developing a program I do a tremendous amount of printing. And by the time I take out or comment out the prints, it really is pretty solid. I rarely have to go back.” Or Joshua Bloch “I’m going to come out sounding a bit Neanderthal, but the most important tools for me are still my eyes and my brain. I print out all the code involved and read it very carefully. Debuggers are nice and there are times when I would have used a print statement, but instead use a breakpoint. So yes, I use debuggers occasionally, but I don’t feel lost without them, either.” He understands the benefits of debuggers but more importantly of the need to run through the programs: “For all of the fancy debugging tools at our disposal, there’s nothing that can match the power of simply stepping through a program, in a debugger or by reading it and mentally executing the code.”
In the end, the most important thing for debugging is to keep an open and scientific mind and have lots of patience. Brad Fitzpatrick put it best when he talked about the most important thing for him: “Thinking like a scientist; changing one thing at a time. Patience and trying to understand the root cause of things. Learn how to write things incrementally so that at each stage you could verify.”
“Despite the millions of people who have written code, and the billions, if not trillions of lines of code written since the field began, it still often feels like we’re still making it up as we go along. People still argue about what programming is: mathematics or engineering? Craft, art, or science?”
Throughout the book there is no real consensus about what programming is. Bloch nailed it when he said, “to some, the truth of the matter is that programming is at the confluence of a whole bunch of disciplines”.
What is certain though is that programming is a makers’ discipline. Almost by definition programmers and coders need to be doers. All of the subjects learned programming by programming and fell in love with it in this way. Bernie Cosell, for example, speaks of when he was learning to program “I viewed computer programming as a means to get neat things done and I learned how to program in order to make things happen”.
But programming, in general, is a subjective experience. For Zawinsky, there is an element of discovery: “Just figuring out how to get from point A to point B—how to make the machine do what you want. That’s the basic element that the satisfaction of programming comes from.” For Bloch, it is a craft that must include certain engineering aspects: “What we’re doing is an aesthetic pursuit. It involves craftsmanship as well as mathematics and it involves people skills and prose skills—all of these things that we don’t necessarily think of as engineering but without which I don’t think you’ll ever be a really good engineer.” Crockford takes Zawinsky’s element of discovery even further, arguing that “part of what makes programming difficult is most of the time we’re doing stuff we’ve never done before. If it was stuff that had been done before we’d be reusing something else.”
From these views, we can distill a few patterns. Programming is a mixture of disciplines and a very subjective craft. In my own experience, I tend to see programming differently depending on what I’m working on. When polishing a program and making it easier for others to read and understand it feels almost like prose—more on this later. Other times it is much closer to mathematics. You sit there in front of a blank screen or piece of paper trying to decode the problem at hand, trying to decide if a familiar algorithm or data structure will work or if you need to design something from scratch. This can take minutes or hours, it is a process of discovery, patience and adventure like Zawinsky might put it.
“Oh, if you’re no good at English you’ll never be a very good programmer.”
Programming is a form of writing, no one can deny that. We, programmers, spend a lot of our time pushing keys on our keyboards to try to tell computers what to do and thinking how to structure our programs, how to give them flow and a form that is simple to understand and read. After all, programs are read more times than they are written. So a badly structured program or an unreadable piece of code will go to waste faster than a well-documented one—provided it produces value and is actually useful.
Crockford said it best when he said that writing programs is “similar to writing in English or any language, getting the punctuation right, getting the capitalization right, putting the commas in the right place. Then you start looking at higher-level things like how you structure the sentences and where you break the paragraphs. In a programming language, it takes the form of how do you decompose the problem into a set of functions or a set of classes?”
Or take Zawinsky who goes a little bit further, comparing programming with writing prose: “I’ve always seen much more in common with writing prose than math. It feels like you’re writing a story and you’re trying to express a concept to a very dumb person—the computer—who has a limited vocabulary. You’ve got this concept you want to express and limited tools to express it with. What words do you use and what does your introductory and summary statement look like? That sort of thing.”
For Crockford, making programs readable is a top priority: “Readability of code is now my first priority. It’s more important than being fast, almost as important as being correct.” And in fact, making programs readable is so important that Donald Knuth went as far as creating a new way of programming, “Literate Programming”. This is a form of structuring your programs in which you intersperse prose with code. You use prose to document and explain what your code is doing and, in between paragraphs, you write the actual code that will be executed by the machine. While interesting though, none of the other subjects in the book used literate programming. Most were aware of it and had experimented with it but never picked up the habit. This can be attributed to a lack of tools for literate programming —I only know of one programming language, Haskell, which supports this form of programming out of the box.
If making your code readable is about structuring it in the right way, making your code understandable is about writing clear and concise comments and documentation. This is what the subjects in the book agreed the most. As in prose, in programming writing serves as a means to clarify the thoughts and think. This process often starts with documentation—some times a document, some times comments around one’s code—that explain what the program does. Documentation is so important that Joe Armstrong usually starts by writing it first: “with very difficult problems I quite often start right by writing the documentation. The more difficult it is, the more likely I am to document it first. I like documentation. I don’t think a program is finished until you’ve written some reasonable documentation.” And let’s not forget about the importance of using descriptive identifiers for variables and constants, Bloch even suggests the reader to carry a dictionary around, the Merriam-Webster’s Collegiate Dictionary, 11th Edition to be precise: “Never go anywhere without it. It’s not something you actually read, but as I said, when you’re writing programs you need to be able to name your identifiers well. And your prose has to be good. I’d feel lost without a good dictionary.”
As a field, Programming is so new, dynamic and heterogeneous that books like this help distill the big ideas and themes around the subject. But, as much as there are clear patterns in the way people program, it is one of the most subjective and creative endeavors I know of.
We need more books like this and less textbooks so new generations of coders can grow inspired by what this craft is all about and what is possible through it.