Written January 12, 2015. Tagged Ruby.
I've found multiple returns to be a good way of expressing long or complex conditionals.
This typically applies to policy objects or policy methods, e.g. code concerned with whether an action is possible.
Today, for example, Tomas and I came across a method like
def changeable?
auction.buyer && !auction.withdrawn? && the_only_auction_on_its_invoices?
end
Our task called for adding a fourth condition.
Instead of piling onto this long expression, we first refactored it to use multiple returns:
def changeable?
return false unless auction.buyer
return false if auction.withdrawn?
return false unless the_only_auction_on_its_invoices?
true
end
I feel this reads better. It also makes for nicer diffs: adding, removing or changing a single condition affects a single line. It's clearer where any raised exceptions come from. Debugging is easier.
You might argue that multiple exit points are bad and should be avoided. But when the conditions are all bunched together like this, it's just a compact conditional.
Refactoring by Martin Fowler and friends has this to say:
[…] one exit point is really not a useful rule. Clarity is the key principle: If the method is clearer with one exit point, use one exit point; otherwise don't.
That book (as well as Refactoring: Ruby Edition) includes a "Replace Nested Conditional with Guard Clauses" refactoring, which is closely related to what I describe above.