Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return false vs raising an exception in Ruby- When and why?

I am really confused on the concepts of:

  • Don't use exceptions as control flow
  • Don't return nil/false as an exception

Say I have the following instance method:

class Logo
  # This method has some logic to create an image using Rmagick
  def process
    begin
      @logo_image = RmagickHelper.new(self.src)
    rescue Magick::ImageMagickError
      raise Exceptions::LogoUnprocessable, "ImageMagick can't process the URL"
    end
  end
end

So in a more general method I have the following:

def build_all_images
    begin
      @logo.process
    rescue Exceptions::LogoUnprocessable
      @logo.status = 'unprocessable'
      return false #This terminates the method so no more stuff is processed, because logo could not be processed.
    end
#....
end

My question is:

Is this correct to do:

raise Exceptions::LogoUnprocessable, "ImageMagick can't process the URL"

Or should I have just done

return false
like image 213
Hommer Smith Avatar asked Dec 19 '22 14:12

Hommer Smith


2 Answers

Once upon a time there was a language with no exception constructs (c). Each message returned an integer - 0 for success or some error-code for failure. If the caller did not check the return code before continuing - he'd be screwed. Also, most of the time the caller had nothing he could do about the failure, so even when he did check the result - the only intelligent thing he could do is return its own error code...

Then came c++, with exception constructs, just for these use-cases. Exceptions are made for times where the method got into a situation it could not handle (like reading a file that was not there, or surfing the web without internet connection).

Abusing the Exception construct means that an exception is raised in a totally expected situation, for example:

def even?
  if (self % 2 != 0)
    raise NumberNotEvenException
  end
end

Here a number being odd is legitimate, and expected; throwing an error is misusing the exception construct.

Throw an exception when the method cannot fulfill what it promised to do.

On the flip side - returning nil or false when a method fails brings us back to the happy c days, where it is the burden of the caller to notice the failure, and figure out what went wrong - not fun.

like image 91
Uri Agassi Avatar answered Jan 18 '23 23:01

Uri Agassi


The difference has to to do with how often the failure happens and whether it is a simple return value.

Asking "is this a valid url" would expect a "false" value, but In this case, it would seems that a when a valid url is expected, the failure case warrants an exception.

Exceptions are "exceptional" or unusual. Exceptions happen in command methods, where you are telling it to "do this" and it says "oops!"

Flow control is more of a question "what is this" in which case "oops" doesn't make sense.

Also, consider the number of times the code is called - exceptions take a lot more time to process than a simple return value.

like image 33
DGM Avatar answered Jan 18 '23 23:01

DGM