Code Simple: Conceptual Compression Through LanguagePart of a series on the benefits of "code simple", a look into improving readability through language.
This post is part of the "Code Simple" series where we share experience around writing simpler code. In this post we'll take a quick look at language usage and how important it is to readable code.
In this case we're not talking about a programming language, but literally the language used by the development team writing the code. For Harled Inc, our programming language is Ruby on Rails and the language of our development team, for business purposes, is English.
Ruby and Ruby on Rails focuses on delighting developers, where the focus isn't specifically on pleasing the CPU (with performance, or type checking optimizations) but rather on being enjoyable for writing code as a developer. This philosophy bodes particularly well for the concept of language and remembering that we don't write code for the computer to read, we write code for our peers to read.
Employing language effectively (simply) when developing lends itself to conceptual compression which DHH has spoken about frequently and represents the idea that complex information can usually be compressed or simplified (albeit with the risk of some loss).
During a recent pull request the following code was reviewed:
# users_controller.rb def add_to_organization @user = User.find(params[:id]) @organization = Organization.find(params[:organization_id]) @organization.default_subscriptions.each do |group| @user.follow(group) end end
What's the problem? Well, per the title we have used language to introduce a number of concepts that cause cognitive load on the reader. Clearly we have some relationship between objects (user and organization), but how the relationship is defined is expressed with different language throughout the code. The following three concepts are included:
- Add / Remove (
- Subscribe / Unsubscribe (
- Follow / Unfollow (
From the database perspective all three represent a join table. Semantically they mean different things, but when having a general conversation they are fairly interchangeable. This is exactly the problem! If we were sitting down and having coffee, using different words is natural and more interesting than limiting ourselves to a small and restrictive vocabulary. In code it is exactly the opposite. The more boring the language is, the better the readability!
When I read this code I was curious about the difference between followers vs subscriptions and why we might call the broader method "add" if it was really only acting on a more specific relationship. After discussing with the developers it was clear that we were really only working on a single concept; the ability to subscribe a user to multiple organizations.
So, how do we improve on this? Just pick any of the three concepts (literally) and it will be better. In our case, we made a decision to stick with subscribe / unsubscribe with the noun being a subscription. That alone reduces the things to understand by 66%.
However, we had one complication. The underlying library we use (acts_as_follower) provides methods based on the idea of "following". So we're out of luck right, or we should have picked follow/unfollow? Wrong, we can simply abstract the method so that at least the controller and view layers speak strictly in the language of subscriptions. Here is an example of how simple the wrapper can be:
# user.rb def subscribe(organization) self.follow(organization) end
# users_controller.rb def subscribe_to_organization @user = User.find(params[:id]) @organization = Organization.find(params[:organization_id]) @organization.default_subscriptions.each do |organization| @user.subscribe(organization) end end
The above code is much easier to read simply because it has used fewer unique words to describe what is going on. Thinking about conceptual compression we removed the understanding of "add" and "follow". Reading the controller method is really simple! So, what loss did we experience? Well, it isn't going to win a literary award, but that was never our goal.
The rule to remember is that code is not a creative writing assignment where liberal usage of a thesaurus adds interest. It does the opposite, it makes code hard to read and confusing to iterate on.
Next time you find yourself up against multiple words referencing the same underlying concept, do your peer developers a favour and raise your hand and force the selection of one concept and one set of language to represent it.
Keep an eye on the blog for additional posts in the "Simple Code" series.
About the author
Chris is dedicated to driving meaningful change in the world through software. He has a history of taking projects from idea to production in fast yet measured ways. Chris has has experience delivering solutions to clients spanning fortune 100, not-for-profit and Government.