Over the years, I've come to understand the qualities that I admire in code. With the help of some of my personal heroes, I'll explain why I strive for "kindergarten code" and how it will make you a better engineer.
this talk because over the past several years I’ve come to appreciate a particular quality in code that I didn’t have a name for. But then I finally found a useful name: kindergarten code. This talk is a collection of quotes from people much smarter than I to give you a sense of this “kindergarten code” and why it’s important.
Brent Simmons – Vesper Sync Diary “Since this is a super-critical part of the app, it should read like a smart kindergardener wrote it. Which is exactly how I want all my code to look, come to think of it.”
Brent Simmons – Vesper Sync Diary All the damn time I see code that’s confused and more complicated than it needs to be. It’s easy to fall into this trap. But if your code is clear and straightforward, enough that a kindergartener could understand it, then you’re in good shape.
it exactly right the first time Bernie Cosell – Coders at Work “I want every routine you work on to look as if it was just written. I do not want to see any evidence of afterthoughts or things gone wrong followed by something to correct the error or a mysterious piece of code saying, "This routine returns the wrong value every now and then so I've got to fix it." I don't want to see any of that. I want to see code that looks like through some divine inspiration you got it exactly right the first time.”
it exactly right the first time Bernie Cosell – Coders at Work Say as you’re working on something you realize a better way of doing it. You damn well better circle back and improve upon the existing code to use that new style too. You’ll see examples of this done poorly EVERYWHERE YOU LOOK. ! Do not comment out code. git will remember your previous versions. Code confidently!
Abrams – The Pit of Success “Build platforms that lead developers to write great, high performance code such that developers just fall into doing the “right thing”. Rico called this the Pit of Success. It is the key point of good API design. Build APIs that steer and point developers in the right direction. Types should be defined with a clear contact that communicates effectively how they are to be used. I am not just talking about the docs and samples but in the design of the APIs.”
Abrams – The Pit of Success I don’t love the term “pit of success” but I think it’s trying to be the exact opposite of “pit of despair”. But it is what I strive for when I architect something (success, not despair). Apple does a really great job of this with its APIs. There’s a consistency and clarity to the UIKit APIs that just makes you feel like a wizard. There’s an obvious, straightforward way to do things. APIs are orthogonal and work together. That’s why I love Objective C so much.
I thought, “Wait, seriously?” And each time Microsoft implicitly replied, “Seriously.” Casey Muratori - The Worst API Ever Made An incredible example of where this was done wrong is described in http://mollyrocket.com/casey/stream_0029.html The author describes an API for a simple feature that basically took weeks to actually get working, because it was so horrifically designed. Don’t do this. Don’t require your users to care about weird implementation details. The takeaway from Casey’s piece is write your synopsis first because it will be free from those unnecessary details.
dynamic process Edsger W. Dijkstra – A Case against the GO TO Statement (EWD 215) “Our intellectual powers are rather geared to master static relations and our powers to visualize processes evolving in time are relatively poorly developed. For that reason we should do (as wise programmers aware of our limitations) our utmost best to shorten the conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible.”
dynamic process Edsger W. Dijkstra – A Case against the GO TO Statement (EWD 215) Your program is little more than a gigantic text file. When you run your program, the text isn’t itself doing anything. The process that results from your program is a living, breathing beast. It’s important that the program and its process match as closely as possible, otherwise it’s very difficult to understand and modify the program to get the desired behavior out of the process.
dynamic process Edsger W. Dijkstra – A Case against the GO TO Statement (EWD 215) It’s the difference between a recipe and its resulting dish. What you wouldn’t want in a recipe is nonsensical, extraneous steps. Like if you’re following a recipe and step 4 is flush your toilet. Why the hell is that in the recipe? Because the original guy had to take a leak while he was waiting for his noodles to boil. You might think that’s ridiculous, but it happens ALL THE DAMN TIME in code. “Oh I was trying to fix something so I just left that in there and didn’t bother to remove it when I figured it out that the problem was somewhere else.” Use “git add -p” to select exactly the changes that do what you need and throw the rest away.
bandwidth channel Bret Victor – Media for Thinking the Unthinkable “The authors have a very rich picture in their heads. And they're trying to compress that picture to transmit over a very low-bandwidth channel, which is this stream of symbols. So it's a very lossy compression. And we've got the reader on the other end trying to decompress this picture into their own head. And it doesn't work very well.”
bandwidth channel Bret Victor – Media for Thinking the Unthinkable This quote was talking about a scientific research paper, but it applies equally well to code. The programmer knows in their head what they’re trying to accomplish. They have to communicate this idea using the programming language. There’s no way to encode all of that rich picture into text. So to make sure that there’s no miscommunication, you want to be very precise, very explicit, and overly critical. I’d go so far as to say that you want to do this in all technical communication, whether it be code, tests, documentation, IRC channel, etc.
Sussman - Structure and Interpretation of Computer Programs “We want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute.”
Sussman - Structure and Interpretation of Computer Programs I’m sure you’ve seen this quote before. This is the same idea as the previous few quotes. It is VITAL that your code be comprehensible or it becomes a liability. Quick informal poll, has anyone had to modify code that wasn’t incredible? Did that go well? Do you wish the author had been more careful putting together that code?
made the (relatively major) changes Alan Kay – The Early History of Smalltalk “Steve Jobs said he didn't like the blt-style scrolling we were using and asked if we could do it in a smooth continuous style. In less than a minute Dan found the methods involved, made the (relatively major) changes and scrolling was now continuous! This shocked the visitors, especially the programmers among them, as they had never seen a really powerful incremental system before.”
made the (relatively major) changes Alan Kay – The Early History of Smalltalk This is an anecdote I like that reflects what having this clarity in your code. There’s a certain beautiful competence you earn by having your code well- formed and comprehensible. Anything that doesn’t live up to that beauty is offensive to me. If only you could read my private Slack conversations… :)
dare not modify Simon Peyton Jones – Coders at Work “The most depressing thing about life as a programmer, I think, is if you're faced with a chunk of code that either someone else wrote or, worse still, you wrote yourself but you no longer dare to modify.”
dare not modify Simon Peyton Jones – Coders at Work I’m sure no one here has been in this situation before. Lately I’ve been striving to be in the exact opposite situation. I go well out of my way to become master over the code I’m writing. If there’s something I don’t understand, I spend time tumbling down the rabbit hole. If I catch myself thinking “gosh, I hope I don’t ever have to touch THAT code” then something’s not right in paradise.
Dijkstra - An Introduction to Implementation Issues (EWD 656) “I intend to mention as little accidental detail as possible. I shalln't shun detail wherever the subject matter doesn't allow me to do so, but it is my firm intention to reach my goal by abstracting from whatever can be identified as accidental. Being abstract is something profoundly different from being vague: by abstraction—from what is uncertain or should be left open—one creates a new semantic level on which one can again be absolutely precise.”
Dijkstra - An Introduction to Implementation Issues (EWD 656) The whole point of abstraction is to build the tools you then use to work at a higher level. When you’re interacting with a database, you don’t want to have to care about the file I/O operations that need to happen. You want to deal in the realm of SQL queries, which is a very precise system. Dealing with the I/O yourself would be a disaster.
abstraction Peter Seibel – Coders at Work “I've noticed that one thing that separates good programmers from bad programmers is that good programmers are more facile at jumping between layers of abstraction - they can keep the layers distinct while making changes and choose the right layer to make changes in.”
abstraction Peter Seibel – Coders at Work I worked with someone once who was terrible at this. Every bugfix and feature would be done in the wrong place. It drove me absolutely mental and it was a serious drag on the entire project. In stark contrast, the student I mentored for Gnome Outreach Program for Women, Upasana Shukla, was perfectly good at this. She is a real pleasure to work with. She was hacking on Moose which…
whole process Casey Muratori – Working on The Witness “Instead of stepping through the code or even carefully reading it to see what it was doing, I added debug visualization code right away. I know if you’re going to debug one thing in a piece of code, you’re going to debug a bunch of things, so you might as well add the debug code early and leverage it throughout the whole process.”
whole process Casey Muratori – Working on The Witness This is not directly related to my theme, but I did want to include this as a practical suggestion.
and porting parts of, a complicated spreadsheet. You feed it a few numbers, it runs a shitload of arithmetic, and spits out a few numbers. We basically use this as a specification since a gigantic XLS would not be appropriate to ship to end users. By the way folks, Excel really does rule the world. You might think everything is stored in a nicely normalized Postgres database with proper types and foreign keys and, but in reality, your precious tree structures have cycles, and everything is a copy of a copy of a copy…
one formula. This is about the first half of it, the rest didn’t fit into the window. And then look at how long the vertical scrollbar is. And then notice that the list of tabs at the bottom even has its own scrollbar. It’s like 4 megabytes of XML baby.
need to investigate why. No one carries this spreadsheet in their head, nor could they work backwards from the outputs to figure out which intermediate calculations went wrong. We need some way to surface all those bazillions of lines of arithmetic. So I thought hey, printf. I even spruced it up with some formatting and highlighting of like terms on hover.
that log output to even figure out which cell it’s referring to. ! So I threw it all away and started fresh. The spreadsheet includes a “reference algorithm” which is a euphemism for flim-flam.
closely to the spreadsheet’s format as possible. That way differences immediately jump out at you. ! Building the right tools like this not only cuts down time on time both for debugging and customizations dramatically, but also lets the next programmer come along and see exactly what’s going on. The static program, in this case the spec, is INCREDIBLY similar to the dynamic process, which is surfaced in this way.
– The Early History of Smalltalk Build the right tools. This applies both to the previous debugging example, and to the earlier examples about finding the right abstractions. Expose yourself to new ideas. Pick up another language, whether programming or spoken.
Humble Programmer (EWD 340) “Programming will remain very difficult, because once we have freed ourselves from the circumstantial cumbersomeness, we will find ourselves free to tackle the problems that are now well beyond our programming capacity.”
C. A. R. Hoare – Software Design: A Parable “The current situation in software design is bad, and it is getting worse. I do not expect that this will be recognised by the designers or users of software, who will regard the increase in complexity as a sign of progress. And everything is now so complicated, that any particular attack on the problem of low quality software design can always be evaded by appeals to tradition, to standards, to customer prejudice, to compensating advantages, and even to promises to mend the fault in future issues.”
C. A. R. Hoare – Software Design: A Parable “But even if the problem were widely recognised and deplored, its solution is going to present extremely difficult technical problems. The pursuit of simplicity is one of the most difficult and challenging activities of the human mind. Progress is likely to be extremely slow. We need not only brilliance of intellect but breadth of experience, nicety of judgement, excellence of taste, and even more than our fair share of good luck. And finally we need a puritanical rejection of the temptations of features and facilities, and a passionate devotion to the principles of purity, simplicity and elegance.”
most vital activities of a competent programmer Edsger W. Dijkstra – The Humble Programmer (EWD 340) “We all know that the only mental tool by means of which a very finite piece of reasoning can cover a myriad cases is called "abstraction"; as a result the effective exploitation of his powers of abstraction must be regarded as one of the most vital activities of a competent programmer.”
introduce the bugs to start with Edsger W. Dijkstra – The Humble Programmer (EWD 340) “If you want more effective programmers, you will discover that they should not waste their time debugging, they should not introduce the bugs to start with.”
interfaces impairing our ability to factor the system in a helpful way Edsger W. Dijkstra – The Humble Programmer (EWD 340) “The best way to learn to live with our limitations is to know them. By the time that we are sufficiently modest to try factored solutions only, because the other efforts escape our intellectual grip, we shall do our utmost best to avoid all those interfaces impairing our ability to factor the system in a helpful way. And I cannot but expect that this will repeatedly lead to the discovery that an initially untractable problem can be factored after all.”
step that becomes possible Michael Polanyi – The Republic of Science “Imagine that we are given the pieces of a very large jigsaw puzzle, and suppose that for some reason it is important that our giant puzzle be put together in the shortest possible time. We would naturally try to speed this up by engaging a number of helpers; the question is in what manner these could be best employed. Suppose we share out the pieces of the jigsaw puzzle equally among the helpers and let each of them work on his lot separately. It is easy to see that this method, which would be quite appropriate to a number of women shelling peas, would be totally ineffectual in this case, since few of the pieces allocated to one particular assistant would be found to fit together. We could do a little better by providing duplicates of all the pieces to each helper separately, and eventually somehow bring together their several results. But even by this method the team would not much surpass the performance of a single individual at his best. The only way the assistants can effectively co-operate, and surpass by far what any single one of them could do, is to let them work on putting the puzzle together in sight of the others so that every time a piece of it is fitted in by one helper, all the others will immediately watch out for the next step that becomes possible in consequence. Under this system, each helper will act on his own initiative, by responding to the latest achievements the others, and the completion of their joint task will be greatly accelerated. We have here in a nutshell the way in which a series of independent initiatives are organized to a joint achievement by mutually adjusting themselves at every successive stage to the situation created by all the others who are acting likewise.”
just really good at "playing computer" Bret Victor – Inventing on Principle “To a large extent, the people that we consider to be skilled software engineers are just those people that are really good at "playing computer." But if we're writing our code on a computer, why are we simulating what a computer would do, in our head? Why doesn't the computer just do it and show us?”