Readability
Welcome back to The Coder Cafe! The theme of the week is code health. Today, we will delve into the precious concept of readability.
I don’t know about you, but I find it quite common to hear and read the term readability. For example, in pull requests:
While this message could probably be improved1, the main message is here: “your code is not readable“.
Why is readability important? Code is read far more often than it is written. Hence, writing readable code is crucial as it makes maintenance easier and cheaper. A quote I like from the Clean Code book sums it up well:
Making your code readable is as important as making it executable.
Now, let’s discuss what it means for a code to be readable. My favorite definition of code readability is how easy it is for a human reader to understand the intent (what), rationale (why), and logic (how) behind a piece of code:
Intent: What is this code trying to accomplish? (the purpose of a code).
Rationale: Why was this approach chosen? (the reasoning behind specific decisions).
Logic: How does the code achieve its goal? (the way the code works should be easy to understand2).
One thing I want to highlight is the rationale. Throughout my career, I have encountered many pieces of code where the reasoning behind certain decisions was unclear. Understanding the why is essential when it comes to the readability and maintenance of a codebase.
Let’s explore the main principles behind readability:
Relevant abstractions: Readability improves when we can abstract away some logic into meaningful abstractions—e.g., functions, modules, or classes.
Meaningful names: There are only two hard things in computer science, and naming things is one of them3. Every asset that we name—variables, functions, etc.—should clearly describe its purpose and be relevant to its context.
Aesthetics: How our code looks visually matters. For example, a file should be well-formatted, a function should be structured into paragraphs, avoiding deep nested code, etc.
Comments: Comments should focus on explaining the intent and rationale, not repeating what the code does. If what isn’t clear from the code itself, we should consider refactoring.
Clarity: Clear code is better than clever code.
Idiomatic code: Following the standard idioms of the language we are using.
Consistency: The code should stick to the patterns and conventions already established in the codebase.
Well-structured: Ensure the flow of the code is easy to follow and the structure is logical and organized.
Often, we are not the best judges of our own code’s readability. This is where code reviews come in: reviewers should also focus on the question of whether this code is readable. For example, at Google, every change must be approved by at least one maintainer of the codebase. For non-minor changes (generally more than five lines), it also needs approval from someone with a readability badge4 for that language. This ensures that someone with fresh eyes and without biases from the existing codebase can evaluate the readability of the changes.
Also, readability can sometimes be a matter of balance. In performance-critical codebases, it may be necessary to consciously sacrifice a bit of readability to optimize performance. But even then, the goal is to strike a balance between readable code and optimized code.
One last thing: a practice I find helpful is physically stepping back from the code, meaning zooming out on my IDE. This helps me get a different perspective, which can often help me find some readability issues. If you’re not familiar with this practice, I encourage you to give it a try.
Tomorrow, we will discuss one way to increase the readability of our code: how to handle complex if statements.
Why is this code not readable? What’s wrong exactly? We will discuss code reviews in a future issue.
To some extent; it’s a bit similar to the differences highlighted in #4: Cognitive Load; for example, an algorithm solving a complex problem is intrinsically more complex to understand than an algorithm solving a basic problem. What we should judge, though, is the extraneous load.
This is a famous joke from Phil Karlton:
“There are only two hard things in Computer Science: cache invalidation and naming things“.
I have readability in Go :)