Motorcycles, Gumption, and Beautiful Code
I love reading Zen and the Art of Motorcycle Maintenance and I have to say it is one of the best books I have ever read as it has allowed me to reconcile many of my feeling about the value of technical things.
I think it’s fair to say that we’ve all dealt with bad and good instructions in our lives. We live in a world where we are expected to read directions every day. Everything you buy, from electronics, to soap, to drugs, to food, comes with instructions.
Good instructions go unnoticed and bad instructions draw attention to themselves. Driving directions are a good example. Good driving directions switch between giving you lots of notice for some instructions and very little notice for others depending on how much information you need to handle.
Maybe you’ve never read the manual for how to use the remote control for your TV or a microwave. Some instructions are part of our education in this society. We’ve already been taught how a TV remote should work. Most microwaves just require entering the time and hitting Start, but some have the first step of requiring Cook to be pressed. There are microwaves with knobs or +30 seconds buttons that result in sighs and eye rolls.
Instruction developers often think that pictograms are the way to be universally interpreted. To be blunt, these people are idiots. Just because symbols give suggestions about their use, it doesn’t make them universal. They are a language that has to be learnt. This is why they test your on road signs when getting a licence and driving in a different country is confusing. If pictograms were truly universal, we’d all be able to read Ancient Chinese.
To me, the purpose of literary work is to some how, magically, make me feel and think what the author wanted me to feel and think. The purpose of a program is to make the reader understand the procedure as the author understood it. Some programmers take what I might call and “Dungeons and Dragons” approach: the only way for you to understand their program is to go on the epic quest of following in their footsteps. If you follow the map they have given you and defeat the various monsters along the way, you will understand what they intended. You will essentially relive their coming to understand the problem and therefore the solution. Unfortunately, it becomes hard to tell if something is intentional or an error in the author’s undersatnding. “Why is there a
+ 1 attached to this value?” Figuring that out might require you to remove it and understand why the program fails. You might also be following the program along to see it go into the Mountains of Terror instead of the Forrest of the Happy Elves and you suspect the author was incompetent. What you don’t know is that the programmer tried the Forrest of the Happy Elves only to discover that it had a Gorge of Computational Inefficiency…but that isn’t written down.
Ultimately, a programmer has to decide on how to convey meaning, which comes down to only three things:
- the abstractions they use
- the names they give things
- the documentation they include
Some programmers subscribe to the TV chef approach to documenting programs: before each step, they give you an English language description of that step. Much like watching some TV chefs, this doesn’t really provide me with any insight into why the program is bothering to do any of this at all. It’s unhelpful to tell me “next, you fry this” as you dump it in the pan of hot oil. Better to dump it into the pan of oil and say “wait until it bubbles around the edges so that it crisps up” because, of course, we can all figure out that dumping it in a pan of hot oil is frying. The motivation is what I really need to know.
One of the poisonous conventions, very prevalent in Java, is to name variables based on types. So, you have a definition
which makes the subsequent line
without context or meaning. If we simply say
then the meaning of
becomes immediately apparent: we intend to do something to x only if it is valid. The following code has a much better context for “why” and we didn’t even change “how”.
I think programming language authors try to make things better but get caught up on the wrong details. SQL is a good place to start. SQL statements are meant to be read like English; for instance,
SELECT id, name FROM employees ORDER BY age
has some kind of meaning to someone who has never seen SQL before. Unfortunately, most of the English assistance ends up in the wrong part of the program as it gets bigger. The
ORDER BY contains little help when looking at a query with a gargantuan
Libraries and abstractions determine the interpretability of programming languages. In fact, the libraries rule everything since you spend most of your program manipulating the outside world, not the syntax in your programming language. Here’s where C does a dismal job. Most of the string-related function start with
index and what do you think
strpbrk does? And for file manipulation,
fscanf take the
FILE* first, but
fgets take it last. Oh, and
fclose deal with
FILE* too, but
fsync does not. All that kind of inconsistency makes reading and writing a program frustrating, particularly if the variables are poorly named. Here, I think programming language developers spend very little time; I know I did this poorly in Flabbergast.
Is there a measure of aesthetics in programming? Undoubtedly. It is the same measure we would use for any other literary work: how is easy it to understand what the author was thinking and feeling?
Why is it easy to run out of steam when programming? In the book, Pirsig talks about gumption traps, things which get you stuck while working and drain your motivation.
When I lose track of what I’m trying to convey with a piece of code, it’s hard to just keep hacking on it. It doesn’t mean anything any more. I’m just pushing symbols around until I get the output I want. Why not name the variable
foo if I can’t really explain what’s in it? What inevitably gets created is of low Quality, in Pirsig’s terminology, and the lack of quality shows in both the code and the final product.