I learned about guard clauses thanks to Rubocop, the super annoying yet awesome code analyzer. I started refactoring my code everywhere Rubocop told me a guard clause would be better.
Why would it be better? Because guard clauses are an awesome way to make a piece of code more succinct and understandable.
Code explains better than words, so let’s take an example. Checkout the method below.
def my_method(variable)
if variable == 'great'
# do something great
else
return nil
end
end
As you can see, this is a relatively common method where we check if the passed parameter matches our expectation. If that’s the case, we ‘do something great’, if not we return nil
.
In reality, we can write this code in only two lines with a guard clause. You see, guard clauses are named like this because they protect some code from running unless a condition is met. They are usually used to ensure that the parameters that were passed meet some criteria to avoid running into exceptions or other problems.
def my_method(variable)
return nil unless variable == 'great'
# do something great
end
Those examples were pretty simple so you could see how easy it is to use guard clauses. For more complex code, they can be used to prevent a bad code smell known as nested conditional. That’s when a method has a bunch of conditions making it hard to read through it and understand the flow of execution.
To have an idea of what a nested conditional nightmare is, take a look at the code below. What do you think?
def pay(invoice)
if invoice.paid?
return nil
else
if invoice.delay_payment?
invoice.set_delayed_payment_date
else
if invoice.amount > 1000
invoice.trigger_manual_payment
else
invoice.pay
end
end
end
end
I personally don’t like it at all! It’s hard to read and understand exactly what’s going on. What about the alternative below?
def pay(invoice)
return nil if invoice.paid?
return invoice.set_delayed_payment_date if invoice.delay_payment?
return invoice.trigger_manual_payment if invoice.amount > 1000
invoice.pay
end
It’s so much simpler and clearer! Whenever I can, I use guard clauses and I haven’t looked back.
Give it a try, you won’t regret it.