Sonntag, 25. Mai 2014

Raise a Ruby exception or better fail it!

In Ruby there are a lot method alias or synonyms doing the exactly same job. That is no mistake or arbitrary choice. That is an intended concept for writing expressive code.
It is the same with the Kernel#raise and Kernel#fail. Most Ruby developer use Kernel#raise for raising exceptions but only a few use Kernel#fail for the same goal. They miss the chance to improve the expressive power of their code. Jim Weirich was the first, who used Kernel#raise and Kernel#fail for different purposes.
Following that pattern is a stylistic decision.

1. Use fail for raising exceptions, when code fails in a true sense (means an unexpected behaviour that breaks the processing)

class Account
  def register name
    fail ArgumentError, "The assigned parameter is not a name." unless name.is_a? String
    "Hello #{name}!"
  end
end

2. Use raise for raising exceptions, when you catch the exception afterwards

class Person
  attr_accessor :salary
  def net_salary
    return 0 if salary.nil?
    begin
      salary - Calculator.tax(self)
    rescue NotImplementedError
      puts "Net is equal to pre-tax."
      salary
    end
  end
end

class Calculator
  def self.tax person
    raise NotImplementedError
  end
end
The intention behind is to use raise when the code does not fail, but explicitly raises an exception. In practice the mentioned scenario is rarely the case. Therefore indicating a failure by fail will become your natural friend.
Speaking of exception:
Do not use exceptions for flow control.
There you better go with throw/catch.

Supported by Ruby 2.1.1