a) let the exception pass through. this is ok if, and only if, there is nothing reasonable your code could do to retry. if you do retry you have you have a configurable numbmer of retries, of course.
b) wrap the errors. my preferred approach is something like
module Wrapper
class Error < ::StandardError
attr_accessor :exception
def self.wrapping exception, *a, &b
e = new *a, &b
e.exception = exception
e
end
end
class Specific < Error; end
class EvenMoreSpecific < Specific; end
end
this allows client code respond appropriately to specific errors or simply to rescue the entire class of errors your wrapper might throw and, when you want to wrap another error you can
rescue => e
raise Error.wrapping(e)
end
i would say that you have to have a good reason to pick b over a, but they do exist.
a) let the exception pass through. this is ok if, and only if, there is nothing reasonable your code could do to retry. if you do retry you have you have a configurable numbmer of retries, of course.
b) wrap the errors. my preferred approach is something like
Another possibility, somewhere between a and b: rescue the exception and re-raise, but add some more information to the message. That extra info might be, for example, IP address and port during network operations. This doesn't change the structure of exception handling, since the Exception subclass is the same and it will be handled at the same point, eventually, but it can be very useful for logging/debugging and for presenting an informative message to the user, if your program is interactive.
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
def handle_exception e
if e.respond_to?(:error_handler_before)
fcall(e, :error_handler_before, self)
end
if e.respond_to?(:error_handler_instead)
fcall(e, :error_handler_instead, self)
else
if e.respond_to? :status
exit_status(( e.status ))
end
if Softspoken === e or SystemExit === e
stderr.puts e.message unless(SystemExit === e and e.message.to_s == 'exit') ### avoids double message for abort('message')
else
fatal{ e }
end
end
if e.respond_to?(:error_handler_after)
fcall(e, :error_handler_after, self)
end
exit_status(( exit_failure )) if exit_status == exit_success
exit_status(( Integer(exit_status) rescue(exit_status ? 0 : 1) ))
exit exit_status
end
...
which basically allows exceptions to be extended with modules or have methods defined on them which affect how they are handled. it seems like a useful pattern but i've only just started using it.
On Nov 8, 2007, at 7:20 PM, Joel VanderWerf wrote:
Another possibility, somewhere between a and b: rescue the exception and re-raise, but add some more information to the message. That extra info might be, for example, IP address and port during network operations. This doesn't change the structure of exception handling, since the Exception subclass is the same and it will be handled at the same point, eventually, but it can be very useful for logging/debugging and for presenting an informative message to the user, if your program is interactive.
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama
Thank you both for your responses - they made the gap in my knowledge quite plain, so I'm off to do some more homework on exceptions.
Alex
ara.t.howard wrote:
···
On Nov 8, 2007, at 7:20 PM, Joel VanderWerf wrote:
Another possibility, somewhere between a and b: rescue the exception and re-raise, but add some more information to the message. That extra info might be, for example, IP address and port during network operations. This doesn't change the structure of exception handling, since the Exception subclass is the same and it will be handled at the same point, eventually, but it can be very useful for logging/debugging and for presenting an informative message to the user, if your program is interactive.
good point joel, i recently added this to main:
...
rescue Exception => e
handle_exception e
end
...
def handle_exception e
if e.respond_to?(:error_handler_before)
fcall(e, :error_handler_before, self)
end
if e.respond_to?(:error_handler_instead)
fcall(e, :error_handler_instead, self)
else
if e.respond_to? :status
exit_status(( e.status ))
end
if Softspoken === e or SystemExit === e
stderr.puts e.message unless(SystemExit === e and e.message.to_s == 'exit') ### avoids double message for abort('message')
else
fatal{ e }
end
end
if e.respond_to?(:error_handler_after)
fcall(e, :error_handler_after, self)
end
exit_status(( exit_failure )) if exit_status == exit_success
exit_status(( Integer(exit_status) rescue(exit_status ? 0 : 1) ))
exit exit_status
end
...
which basically allows exceptions to be extended with modules or have methods defined on them which affect how they are handled. it seems like a useful pattern but i've only just started using it.
cheers.
a @ http://codeforpeople.com/
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama