“How to Make $100/hr as a Freelance Software Developer (No Degree Required)” a YouTube video title reads — with a quarter-million views to boot. “Turning code to cash — How to make money as a Web Developer” is the title of a Medium article published by freeCodeCamp. It’s obvious that programming is hot right now — with no indication of a slowdown. But as software engineering has skyrocketed in popularity and profitability over the past few decades, it lost its soul.
Donald Knuth’s seminal The Art of Computer Programming was written 50 years ago. And while many regard it as a “must read,” I have a feeling that few have actually read it. This essay is a love letter to the craft of programming — to the art of making something out of nothing. Ours is a fantastical realm where ex nihilo nihil fit, paradoxically, doesn’t seem to hold.
What is an artisan?
“Artisan” implies craftsmanship, skill, a life-long dedication, and a high bar for quality. The Japanese word for artisan — shokunin (職人) — has even stronger connotations:
Shokunin means not only having technical skill, but also implies an attitude and social consciousness… a social obligation to work his best for the general welfare of the people, [an] obligation both material and spiritual. — Wikipedia.org
I first started writing code in 1992. My dad had just traveled from Romania to England (his first trip out of the country; Romania had been under Communist rule until 1989) and brought back with him the first computer — if you could even call it that — I’d ever seen: a Psion Organizer II.
I was as old as the device itself: both of us were born in 1986. And like any young kid, I was more interested in the gaming potential of the pocket-sized device than its calendars or address book. Unfortunately, the Psion didn’t come with any games. What it did come with was a thick-ish programming manual. Halfway through, there were about 30 pages that had the source code of a simplistic platformer. I meticulously copied every single line into the barebones BASIC interpreter — the rest, as they say, is history. I was hooked.
Programming, for me, is a lifelong endeavor. I never really wanted to do it professionally. In fact, doing it professionally kind of sucks — more on that in the next section. As a software engineer, you often find yourself surrounded by people with overblown egos that can recite red-black tree insertion complexities off the top of their head. But that’s not really what programming is about.
The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it can be an aesthetic experience much like composing poetry or music. — The Art of Computer Programming pg. 3
Punk-rock programmers
Artisanal programming is counter-cultural because programming as a profession, from undergrad to interview to retirement, is foundationally anti-artisanal. Undergraduate degrees in software engineering are disasters: 50% of the classes focus on algorithmic idiosyncrasies and uninteresting low-level concepts (pointers and the like) and the other 50% focus on mathematical and computational theory. There’s very little making happening.
Interviews, in turn, focus on testing these very skills — computational theory and algorithms. And when such a programmer is thrown into “real world” programming, they inevitably crash and burn. I’ve seen enterprise code written by senior engineers with 10+ years experience that had lower code quality than throwaway open-source projects you might find on GitHub. In other words we’re teaching students how to draw straight lines and we hire employees based on how straight the lines they draw are, but in reality, we need artists that can paint us vivid landscapes. Finally, ageism is rampant in the industry; the motivating idea being that older developers provide close to the same value as newly-hired ones. Given that most engineers aren’t trained to be artisanal programmers, this is often times, unfortunately, true.
OSS is the epitome of punk-rock programming. I cannot overstate the importance of open source: both writing it and reading it. Open source is written in such a way that makes it welcoming to contribute to a project. One of my favorite open source projects is libevent. Reading the code is an absolute pleasure. Even mundane optimizations are meticulously documented (from evhttp_parse_request_line
):
[cpp]
/* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
/* Since both GET and PUT share the same character ‘T’ at the end,
* if the string doesn’t have ‘T’, we can immediately determine this
* is an invalid HTTP method */
if (method[2] != ‘T’) {
break;
}
[/cpp]
A few other awesome repos: UE4 and Golang. These are huge repos, and yet most parts can be understood by novice programmers. Code isn’t meant to be obfuscated, difficult, or arcane. But in the office, you’re bound to see abstraction layer on top of abstraction layer and code that makes your head spin. I need to mentally prepare for code reviews; they’re not collaborative processes, they’re roasts. And you learn to play this “game” but you forget why you started programming in the first place — or maybe you should’ve never done it to begin with.
How to write a program
At the end of section 1.4.1 of his first volume, Donald Knuth gives an outline of “how might one go about writing a complex and lengthy program.” I hope you’ll agree that there’s a sort of innocence here, and a kind of craftsmanship unhindered by Agile or Kanban. I’d like to end this post by briefly walking through his steps (my favorite highlights are quoted):
Step 0: Initial idea
First we decide vaguely upon the general plan of attack that the program will use.
Step 1: A rough sketch of the program
We start now by writing the “outer levels” of a program, in any convenient language.
Step 2: First working program
We now write in computer language, say
MIXAL
orPL/MIX
or a higher-level language; we start this time with the lowest level subroutines and do the main program last. […] As more and more subroutines are written during this process, our confidence gradually grows…
Step 3: Reexamination
The result of step 2 should be very nearly a working program, but it may be possible to improve on it. […] At this point, it is often a good idea to scrap everything and start again in step 1! […] There’s no reason to be afraid to go back to step 1 — it will be much easier to go through steps 2 and 3 again, now that a similar program has been done already.
Step 4: Debugging
Debugging is an art that needs much further study, and the way to approach it is highly dependent on the facilities available at each computer installation. […] The most effective debugging techniques seem to be those that are designed and built into the program itself — many of today’s best programmers will devote nearly half of their programs to facilitating the debugging process in the other half; the first half, which usually consists of fairly straightforward routines that display relevant information in a readable format, will eventually be thrown away, but the net result is a surprising gain in productivity.
Interestingly, this process clashes thematically with the first hundred pages or so of the volume — which is written with mathematical certitude. Here, when actually writing code, Donald Knuth seems more like a woodworker whittling down a tree stump than a mathematician proving a theorem.