DEV Community

Cover image for Namespaced errors for Ruby
Augusts Bautra
Augusts Bautra

Posted on

Namespaced errors for Ruby

Today I was working on upgrading the version of Dentaku gem we use for resolving user-provided, untrusted formula inputs.

I was able to observe an interesting evolution of how error classes are treated in the gem:

  1. A naive implementation - there's just one custom error and most of the API relies on built-in errors like RuntimeError and ArgumentError. Needless to say, this is a poor showing, problems will be hard to debug.
  2. Next step in the evolution - some more custom errors get defined for common failure spots. Debugging is improved.
  3. Final form? A rich set of errors is defined, and, most importantly, all gem's errors inherit from Dentaku::Error base class, allowing simple catch-all rescues in using code:
def my_method
  Dentaku(my_formula)
rescue Dentaku::Error # will handle Dentaku::ParseError, Dentaku::TokenizerError etc. 
  warn_user("Something is incorrect in the formula")
end
Enter fullscreen mode Exit fullscreen mode

The takeaway

When working on a gem or even a component in a larger system, treat errors as 1st class API citizens, alongside inputs and outputs. Document them and apply good software architecture principles. Have a way to expose any raised errors in method docs, as well as having a glossary of all errors possible in the code.

Distilling Dentaku's approach we get this file structure:

dentaku/
  lib/    
    dentaku/
      exceptions.rb
    dentaku.rb
Enter fullscreen mode Exit fullscreen mode

And zooming in on what exactly goes on in exceptions.rb:

module Dentaku
  # The "abstract" toplevel parent error class for all errors
  # raised by this gem, allows users to do
  # `rescue Dentaku::Error` in their code for a catch-all solution.
  # Also gives an opportunity to have all errors inside the 
  # gem have the same API, some metadata etc. depending on 
  # whether this is needed for the domain of the system.
  class Error < StandardError; end 

  # A "concrete" error class for the gem.
  # -- Description when this error is raised and possible solutions/changes needed to avoid it --  
  class ParseError < Error
  end
end
Enter fullscreen mode Exit fullscreen mode

Photo by Alexander Hipp on Unsplash

Top comments (0)