A new developer joins a project, and asks in Campfire: “what is the purpose of the
The flag in question is a boolean column on User. Rails automatically created a query method for this column, which is used like so:
if can_refer_other_users? # allow user to refer end
The new developer’s innocuous query reveals an important subtlety between code that describes its job, and code that makes its purpose clear.
At first glance, a name like
can_refer_other_users seems quite good. You’re reading it now without any context, and can probably guess exactly what it does.
The problem is, there are no clues about why we wouldn’t let a user refer others. Since growth is good, it’s counter-intutive that we’d block it. Looking in the database, most users have it set to true, with a handful of falses. No help there.
It turns out that some users are disallowed from this process because they were caught referring their own duplicate accounts, earning illegitimate bonuses. Unfortunately, you’ll find this information nowhere in the code. It lives only as an oral myth passed between developers of this project, subject to our own faulty memories.
I think this is a great example of the weakness of code that tells you what it does, but not why. Code that is clear about its job, but opaque about its purpose.
can_refer_other_users weren’t a flag anymore, but a method that referred to a new flag?
def can_refer_other_users? !caught_referring_own_accounts end
Suddenly, it’s clear why this alternate code path exists. New developers have one less question to ask, and someone that removed the bonus for referring others would know this flag is now unnecessary. The implicit purpose behind the code is made explicit. And rather than burdening our memories with this fact, we use git.
Good developers are careful to create code that clearly tells you what it does, but the why is far more important. It’s more important because all code already says what it does. Even if that flag had been named
foo, you could examine the conditional and ascertain that it determined whether users could refer others.
However, there’s simply no way you could find out why the flag was created without asking someone. That knowledge cannot be deduced from any amount of code study.
It’s tough to write code that communicates what it does, but it turns out that bar isn’t quite high enough. Strive to write code that makes clear the meanings behind its machinations. Code that can survive the loss of those who originally wrote it; that doesn’t just redescribe its implicit function. Code that answers “why?”.
Detect emerging problems in your codebase with. We’ll deliver solutions for fixing them, and demonstrate techniques for building a Ruby on Rails application that will be fun to work on for years to come.
In episode #7 of the Giant Robots Smashing into other Giant Robots podcast, Ben Orenstein is once again joined by Joe Ferris, CTO of thoughtbot.
Joe and Ben dive right in to a technical discussion about Objects versus Structures. They then discuss what Joe does as the new CTO of thoughtbot, and how his goal is to set up a system where everybody is teaching everybody. Finally, they discuss why Joe doesn’t like using rspec’s
subject, and his strategy for writing tests without them.
Email your questions to email@example.com or tweet to us @thoughtbot.
Follow @thoughtbot, @r00k, and @joeferris on twitter.