Unless, The Abused Ruby Conditional
Some people hate
unless in Ruby. I personally do not, but I try to abide by a few rules. I’ll explain with some examples below. The uses that I label as “ok” below could just be personal preference, so I will not refer to them as “good”, but I would definitely avoid using the ones I label as “bad”.
unless actually reads better than
if ! when used as a statement modifier. For example, I think this…
raise InvalidFormat unless AllowedFormats.include?(format)
…reads better than this…
raise InvalidFormat if !AllowedFormats.include?(format)
I think the reason I like the former incarnation is because it would read like a sentence to almost anyone, even those unfamiliar with Ruby (like my mom and we all know it is important for moms to be able to read code).
I also don’t mind using
unless when you are just checking one condition and not using
else like so…
unless foo? # bar that thing end
With an Else…Bad
What I dislike is when
unless is used with an
else like so…
unless foo? # bar that thing else # foo that thing end
If you have code like this, just swap the code doing the work and use
if. Trust me, it reads a lot better.
if foo? # foo that thing else # bar that thing end
if version just feels easier to process than the version with
unless. I think using
else is like speaking with double negatives. It slows down the next programmer in the code, as they have to think instead of just flowing through the conditional, if that makes sense.
When testing nil?…Bad
As Ryan Bates pointed out in the comments below, testing nil like this…
unless foo.nil? # do some foo end
…is a bit more readable like this…
if foo # do some foo end
unless foo.nil? and
if foo equate to the same thing but is kind of a double negative issue, like I just mentioned about using
else. Thanks for the another bad
unless tip Ryan!
With Multiple Conditions…Bad
The reason I hate (and it is hate, not just dislike as above)
unless with multiple conditions is that I always forget whether the “not” applies to only the first conditional or to all of them. If you are wondering, the “not” does apply to all conditionals, but just talking about it has me feeling confused again, so please do not do this…
unless foo? && baz? # bar that thing end
Instead, I would probably do something like this…
if !foo? || !baz? # bar that thing end
unless is ok but do not throw it in your code willy nilly. I said “nil” get it? Hehe. Some might say that if
unless can be so easily abused, why not avoid using it all. I guess I disagree with that, as I think it does actually improve code readability in some cases, as I mentioned above. Feel free to argue below and I will ignore you. :)