Write Code In English Part II
17 May 2021
Most written communication is in natural language, so why wouldn’t we want to try to mirror that in our code?
This series will present small concrete examples that might help your code read less like code, today's topic is...
Name Those Predicates
Passing predicates to higher order functions to perform tasks such as filtering and reducing is commonplace in any modern language, often producing concise results but sometimes sacrificing readability.
Let’s start with a thought experiment, how would you describe the green numbers below in natural language?
1, 4, 7, 2, 8, 6, 9, 7, 1, 6, 10
Numbers that are even springs to mind to me.
It would be tempting to code up the example as follows:
A description if the predicate’s results in natural language, might be...
"Numbers where the remainder of dividing the given number by two is zero"
...which is a long way away from numbers that are even.
Can we write the code such that it parses into natural language more… naturally? Absolutely.
Using a local method we can name the predicate, assisting any readers in translating what the code does into natural language. "The numbers where the number is even" vs "Numbers where the remainder of dividing the given number by two is zero". I know which one I prefer to read!
There’s absolutely a trade off in play; the 'improved' example requires an extra definition/some indirection, but in my opinion there are times where the benefits of defining and 'naming' a predicate outweigh those negatives due to the extra 'expresive-ness' of the name.
This technique is especially good where local methods/functions can capture the variables/parameters of an outer function, for example in C#
Any readers now have the option to either gloss over the implementation details of the predicate - by reading the name and trusting it. (or they can still drill down into details if required, as without a named predicte)
In summary, 'naming' predicates can add contextual information to our code, or can reduce the cognitive load required by a future reader of the code. One for the toolbelt.