When code is not describable using words, most people have do a mental mapping to turn it in to words. This wastes mental energy, and you run the risk of getting the mapping wrong. Different people will map to different words, which leads to confusion when discussing the code. This is usually a fertile breeding ground for bugs born out of miscommunication / misunderstanding, and fixing these bugs often introduces new ones, for the same reasons. In the end it becomes code that no one really understands or wants to touch.
Example undescribable code
It is easy to think that code is already a written language, so if it looks simple, it should be easy to read, speak and listen to. However, this is not always the case.
Below is a common solution to deciding whether a year is a leap year.
(divisibleBy(4) and not divisibleBy(100)) or divisibleBy(400)
This is not overly complicated code. It calls a functions 3 times, has 3 operators (and, or, not), and has two levels of nesting.
However, if you take a second to try and describe the algorithm in words I think you will find it to be a struggle.
Maybe “A year is leap year if it is divisible by 4 and not divisible by 100, or divisible by 400”?
The trouble with this is that the code has brackets, but the words do not, so they cannot adequately describe the condition, and whether “or divisible by 400” applies to “divisible by 4” or “not divisble by 400”. You could try some hand waving and gesturing to get around this, or vary the length of pause between the statements, but hopefully it’s obvious that there is a lot of potential for error.
Refactoring to describable code
Instead we can start by describing the condition with words, and then make the words as clear and concise as possible. We might start with this:
“400 years is a special case. If a year is divisble by 400, then it is a leap year. 100 years is also a special case. If a year is divisble by 100 then it isn’t a leap year, unless it is also divisble by 400, the 400 year special case takes priority. If there are no special cases, then the year is a leap year if it is divisble by 4.”
This is clear, but isn’t concise, so we would probably want to shrink it a bit:
“If a year is divisble by 400, then it is a leap year, otherwise if it is divisble by 100 then it is a normal year, otherwise it is a leap year if it is divisble by 4.”
If we turn these words in to code, we probably get something like the following:
if divisbleBy(400): return LeapYear elif divisbleBy(100) return NormalYear elif divisbleBy(4): return LeapYear else: return NormalYear
Hard to understand code is a daily occurrence for virtually all programmers. We can help ourselves and our co-workers by writing code that is easy to describe in words.
And the great thing is that doing so is actually easier than writing code any other way, as there is no mental mapping / wasted mental effort. The only “trick” is to describe the algorithm in words, and then write code to match the words.
In many organisations, the algorithm will already be described in words, as part of acceptance tests or user stories, which will improve productivity even further.