If you polled development teams, most people would say "We want readable code." You may even find a preference for readability over functionality. But when it comes down to asking people to define readability, opinions will start to diverge. Such was the premise of Laura Savino's presentation at Explore DDD 2018. She covered why we want readable code, what it really means to be readable, and when readability absolutely must take priority over other considerations.
Savino's background as a French teacher to elementary school students, followed by a career as an iOS developer and mentor, allowed her to provide more insight than typical comparisons between spoken languages and programming languages. Programmers just starting to learn a new language often begin by writing a basic "Hello, world!" app. Similarly, "Bonjour," "Hola," or "Guten-tag" are likely to be among the first words acquired by someone learning French, Spanish, or German.
Just as programmers will quickly move past "Hello, world!" spoken language next moves to an intermediate phase. Savino gave the example of asking a classmate in your French class if they would like to have coffee with you after class (Voulez-vous prendre un café avec moi après les cours?). Even if they reply in the negative (Désolé, je ne peux pas prendre de café après les cours), and anyone listening would say this was the most boring conversation ever, you feel on top of the world, just from going through a very small feedback loop: You made a statement; It was properly understood; There was an appropriate response; You understood the response. It's like getting data to display in an iOS app -- It's not glamorous, but the first time you do it successfully you get a little dopamine hit.
The advanced phase of language learning moves past thinking about grammar. Your goals have moved beyond establishing that you can understand each other, and you now need to be attuned to nuance and subtlety. That is the point where the analogies to human languages start to break down, or at least require deeper analysis.
In a code review, it wouldn't be uncommon to have one person declare, "I'm having trouble understanding this code," while another, possibly the author, counters with, "But it's more readable this way." Savino uses this to illustrate that "Readability needs a reader." What complicates readability for developers is that they really have two distinct audiences for their writing: other developers, and the computer. Because the computer is very loud and opinionated, quick to tell us when it doesn't understand us, we naturally orient ourselves towards the computer. Acknowledging this bias, we sometimes compensate by surrounding our code with human-readable comments. But, Savino warns us, "We can't comment our way to readable code."
Savino clarified the difference between deciphering text or code and fluent reading. She used the E. E. Cummings poem "when serpents bargain for the right to squirm" as an example of a beautiful and complex piece of writing that takes several passes to really begin to understand its meaning. This same level of deciphering happens when you encounter unfamiliar terms while reading code — looking one up, then the next, and the next, leads you down a rabbit hole until you've forgotten what you were originally trying to understand. While there can be pleasures from deep understanding, Savino cautions that, "Cerebral poetry has no place in production software."
Conversely, fluent reading is quick, correct understanding, without taxing your working memory. Years of experience as a reader gives you the ability to quickly skim an article and still understand it. Savino believes the same can be true with well-written code. When code is easy to lazily scan, one part of your brain can notice when something is wrong, making reviews far more effective.
Having established the reasons why readable code is important, Savino discussed techniques for how to make code readable. Avoiding slang and enunciating clearly are good guidance for communicating with non-fluent speakers. In code, this means naming a method beginApp()
instead of releaseTheHounds()
, and spelling out variables and results at each step rather than chaining together function calls.
Savino also discussed our instinctual pattern matching abilities, and how things that act the same should look the same. At an abstract level, this involves using the "squint test" to look at the general structure of the code, to see if anything stands out. At a much lower level, try to avoid characters and symbols that look similar, including !, I, l,
and 1
, which can lead to anti-pattern matching. Finally, if you're working on something distinct, name it in such a way that makes it stand out from the crowd.
Some of the best advice for any writer is "know your audience." When your audience is someone reading your code, Savino says you should go one step further, and also believe your readers. When someone tells you your code is unclear, believe them and then ask what information they are missing that makes it hard to read the code. Treat the confusion as data, and use it to improve your code readability.
Savino finished by mentioning some examples of when readability needs to be the primary driver. Simply stated, the more important a piece of code is, the more it must be readable. Savino cited the coding guidelines at NASA's Jet Propulsion Laboratory, which state that, "Mission critical code should not just be arguably, but trivially correct." A more down-to-earth scenario involving human communication is signage for fire escapes, which shouldn't require extra effort to decipher when fleeing a fire.
On your team, have conversations about if and when readable code is necessary. Your goal should be all team members reading fluently. Savino concluded by encouraging everyone to "Decipher less. Create more."