Ruby supports a syntactic construct known as a "statement modifier". A
statement modifier lets you move control structures at the end of an expression.
For example, the following two examples are equivalent:
return if c.empty?
I have always found this construct suspicious. After all, the saving is
fairly limited (no need to close the block with end) and moving the
logic at the end of the line is counter-intuitive for most imperative
As I was re-reading some of the Ruby code I have written over these past
months, I noticed a pattern on how and when I used statement modifiers, and it
started making a little bit more sense. I say "a little" because I still
think it’s a feature that should be used sparingly.
I started realizing that statement modifiers shared a lot in common with
exceptions. For me, they are a way to quickly handle error or trivial
cases without impacting the readability of my code. In a way, it’s an
extension to the "early abort" approach, that
I discussed in an
earlier entry. If you’re not using exceptions, early aborts or
statement modifiers, you usually end up wrapping your logic in a big if
and handling the other case in an else, which is not necessarily the
most readable way to structure your code.
With statement modifiers — and more generally, early aborts and exceptions
–, the body of your methods remains focused on the business logic that is
expected to happen "if all goes well", and other cases are moved out of the way.
Having said that, there are definitely a few usage patterns and conditions
that must be met by the statement modifier if you want to keep your code clean.
Your statement modifier should:
- Be simple. If it’s going to span over several lines or
feature a complex boolean condition, you should be using a real block.
- Not perform any side effects. If it does, then you’re doing
business logic and not an early abort, and again, you should probably use a
real block instead.
How do you use statement modifiers? Do you have examples of good ones?
And, more interestingly, of very bad ones?