I have been reading “A Philosophy of Software Design,” and almost the entire book is spent either explaining the dangers of complexity in a codebase, or eliminating complexity.
Code, especially Ruby code, should make its intent loud and clear to the reader. Clear code is the opposite of complex code. It’s easy to understand its purpose, so it’s easier and less risky to modify, extend, or remove.
Double Negatives
One thing that I haven’t seen explicitly discussed in this book is double negatives.
Whether it’s spoken or written, double negatives make sentences less clear. Something like “There are not no eggs left at the store” is obviously poor grammar, but it also makes the sentence harder to understand.
When our code reads like a sentence (well written Ruby should), double negatives increase complexity. Things like unless !some_condition can be more clearly written as if some_condition.
Most programmers will find writing in-line conditionals like this to be straightforward, but it gets less intuitive when extracting this logic into methods.
An example
A bit ago, I was writing some ruby code with a friend. We wanted to take an action if something was false, and like the good ruby programmers we are, we extracted that complex conditional into its own short method.
We found ourselves going around and around trying to make this as clean as possible. One of our first iterations contained a programming double negative - see if you can find it:
# Method call
return [] unless items_found(users)
# Method implementation
def items_found(users)
no_items_found = false
users.each do |volunteer|
if volunteer.items.present?
no_items_found = true
end
end
no_items_found
end
Contrast this to what we ended up with
# Method call
return [] if no_items_found_for(users)
# Method implementation
def no_items_found_for(users)
no_items_found = true
users.each do |volunteer|
if volunteer.items.present?
no_items_found = false
end
end
no_items_found
end
It’s a pretty small change, but I think it highlights what the code actually does much better than the first time around. I’m trying to be more intentional about writing my code with these things in mind.