From: Jacob Fugal Date: 2006-11-29T00:01:06+09:00 Subject: Re: Help me design my exception classes On 11/27/06, J. B. Rainsberger wrote: > My concrete example is this: I'm "spooling" documents to be printed by > sending them via FTP. There might be other ways to spool documents, such > as by sending them via e-mail, to a printer, to the screen. I would like > to represent an exception that occurs in the underlying transport > mechanism (FTP, SMTP, printing subsystem...), but of course, I don't > want my clients to know about those things directly. > > In Java, I would do something like > > //... > catch (FTPException wrapped) { > throw new RuntimeException("Unable to spool document", wrapped); > } > > where the FTP library would throw me an FTPException to indicate that > something went wrong. I only throw a RuntimeException because I don't > necessarily want to create a custom exception class when I only report > generic, unrecoverable "I couldn't spool" exceptions. At that point, > there's nothing (yet) to gain from distinguishing exceptions by their type. > > What's the corresponding exception class in Ruby to Java's generic > RuntimeException. Is it RuntimeError? StandardError? Exception? You're on the right track. I'd use the same model you've got going in your Java design. For a usage like this, RuntimeError is the one you're looking for. Fortunately, Ruby uses RuntimeError as the default when you just raise a string instead of a specific Exception object. Also, in Ruby to raise specific exceptions you don't need to call new on the specific exception class, just provide more arguments to raise. And unless you do your own custom wrapping in a subclass, you can't wrap a previous exception -- but you can subsume the backtrace as an additional parameter to raise. Unfortunately, you need to specify the exception class as the first parameter when you do so. So your syntax could look like this: begin # ... # code that might raise FTPException # ... rescue FTPException => wrapped raise RuntimeError, "Unable to spool document", wrapped.backtrace end Alternately, if you decide you do want to create your own class of exception for later discernment, you will inherit from RuntimeError: class SpoolError < RuntimeError; end begin # ... rescue FTPException => wrapped raise SpoolError, "Unable to spool document", wrapped.backtrace end Jacob Fugal