Extract Compound Conditionals

Day 6 of Ben Orenstein’s Code Quality Challenge

James Nutt

--

A compound conditional is any conditional statement which combines two or more requirements.

If those two requirements are simple, it’s not always a problem. The problem with them is that they obscure intent. If your conditional hinges on multiple requirements, it is not always easy to tell why those requirements are going together. A rule of thumb might be that if you had to read the boolean expression to a non-technical team member, would they understand the intent? How about if you read it to a user?

To take an example that I worked on today:

if @post.author &&
current_user.access_rights.lock_posts &&
@post.author != current_user

# ...
end

This is checking three things:

  1. Whether a post has an author.
  2. Whether the current user is allowed to lock posts.
  3. Whether the current user is the post’s author.

That’s an awful lot of cognitive load for one if statement. It might take us a good few seconds to figure out why this branch is supposed to execute.

We can extract the conditionals to make it a bit clearer:

def post_has_author?
@post.author
end
def current_user_can_lock_posts?
current_user.access_rights.lock_posts
end
def post_author_is_current_user?
@post.author == current_user
end

This cleans up the original statement to be a little more explicit.

if post_has_author? &&
current_user_can_lock_posts? &&
post_author_is_current_user?
# ...
end

This is an improvement, but whoever is using this code still has to absorb more information here than they might need to, and we’re still dealing with a bulky compound conditional. Let’s go one final step further.

if current_user_can_lock_post?
# ...
end
def current_user_can_lock_post?
post_has_author? &&
current_user_can_lock_posts? &&
post_author_is_current_user?
end

Great. Now we’ve extracted the bulk of the conditional logic to other methods that can safely be tucked away. Our original conditional is totally explicit in what it is checking, and programmers can happily ignore the meat of the logic if that’s not what they’re there for.

This post is part of my series following along with the 30 Day Code Quality Challenge by Ben Orenstein. Any useful information found in these posts is wholly thanks to him and the other great people on the challenge forum.

--

--