views:

14

answers:

1

Q: The title is perhaps too big of question and the answer probably is "it depends"? However, providing some practical cases/examples should help developers, like myself, recognize when to apply what. I'll start out with my particular situation. Would you or would you not use custom error classes? Why/why not?

Other examples as the one below are welcomed, like when you would use your own error classes. I really am wondering.

Ex: I'm using httparty to query our rails web service app for some data. It uses basic authentication. I'll paste both test code and implementation. What should my test expect, RuntimeError or SomeCustomError?

class MyIntegrationTest < Test::Unit::TestCase
  context "connecting to someapp web service" do
    should "raise not authorized if username is wrong" do
      #get default MyWebserviceInterface instance, overriding username setting
      ws_endpoint = build_integration_object(:username => 'wrong_username')          
      assert_raises RuntimeError do  #TODO error design pattern?
        ws_endpoint.get
      end

    end
  end
end

The implementation:

class MyWebserviceInterface
  include HTTParty

  #Basic authentication and configurable base_uri
  def initialize(u, p, uri)
    @auth = {:username => u, :password => p}
    @uri = uri
  end

  def base_uri
    HTTParty.normalize_base_uri(@uri)
  end

  def get(path = '/somepath.xml', query_params = {})
    opts = {:base_uri => base_uri, :query => query_params, :basic_auth => @auth}        
    response = self.class.get(path, opts)
    evaluate_get_response(response)
    response.parsed_response
  end

  def evaluate_get_response(response)
  code = response.code
  body = response.body
  if code == 200
    logger.debug "OK - CREATED code #{code}"
  else
    logger.error "expected code 200, got code #{code}. Response body: #{body}"
    #TODO error design pattern? raise the above logged msg or a custom error?
    raise SomeAppIntegration::Error(code, body)
  end
end
+1  A: 

In most cases, I would never rescue from or raiseRuntimeError. That could be something completely unrelated to your code. It's best to use a custom exception.

Generally, you can call errors whatever you want as long as you namespace them within your library's constant. For example, if someone gets their username wrong you could have YourApp::InvalidUsername as an exception object which would be defined like this:

module YourApp
  class InvalidUsername < StandardError
    def message
      super("Yo dawg, you got your username wrong all up in here")
    end
  end

end

When you raise YourApp::InvalidUsername you'll see that message appear.

Ryan Bigg
never? In my experience, _always_ and _never_ are seldom the best rules. But I do agree that _rescuing_ from a RunimeError is wrong and RuntimeError should not be thrown in these situations.
Ole Morten Amundsen