Skip to content

Instantly share code, notes, and snippets.

@victormartins
Last active December 1, 2017 07:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save victormartins/dccb50608596991cbfbf52142f7b3206 to your computer and use it in GitHub Desktop.
Save victormartins/dccb50608596991cbfbf52142f7b3206 to your computer and use it in GitHub Desktop.
Coding Ideas

Error Handling

"The Problem is that the part of a program that spots an error isn't always the part that can figure out what to do about it." ... "Exceptions clearly separate normal processing from error processing. This makes programs easier to understand. Understandability is next to godliness." – Refactoring - Ruby Edition

"Decide if the caller should check for the condition before making the call or rescue the exception. If the error is likely to occur in normal processing then I would make the caller check the condition before calling. If the error is not likely to occur, then I would rescue the exception." – Refactoring - Ruby Edition

Caller Checks before call

def withdraw(amount)
  raise ArgumentError if amount > @balance
  @balance -= amount
end

Same strategy but With Assertions

class Account
  include Assertions
  
  def withdraw(amount)
    assert!('Amount is to large') { amount <= @balance }
    @balance -= amount
  end
end

module Assertions
  class AssertionFailedError < StandardError; end
  
  def assert(message, &condition)
    return if  condition.call
    raise(AssertionFailedError, "ASSERTION FAILED: #{message}")
  end
end

Caller Catches the Exception

In this case we create a custom exception and let the consumers of the method rescue and handle the error.

class BalanceError < ArgumentError; end

class Account  
  def withdraw(amount)
    raise BalanceError if amount > @balance
    @balance -= amount
  end
end

class Foo
  def some_operation
    (...)
    account.widthdraw(amount)
    (...)
  rescue BalanceError => e
    handle_balance_error_exception
  end
end

Conditionals Vs Exceptions

Warning: Algorithms that use exception/rescue are many times slower than conditional checking. We probably do this in the validation stuff. Maybe being invalid is exceptional in our case, or maybe not if this is user data.

In this case, use conditionals for code flow and use assertions as we saw above, to raise exceptional errors.

"Exceptions should be used for exceptional behaviour: behaviour that is an unexpected error. They should not act as a substitute for conditional tests. If you can reasonably expect the caller to check the condition before calling the operation, you should provide a method for a given test that returns a boolean, and the caller should use it." – Refactoring - Ruby Edition

This is fast

def resource
  if @available.empty?
    @allocated.push(Resource.new)
  else
    @allocated.push(@available.pop)
  end
end

This is slow

def resource  
  @allocated.push(@available.pop)
rescue EmptyStackError
  @allocated.push(Resource.new)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment