> > On Jun 8, 2004, at 11:34 AM, Scott Stearns wrote: > [..] > > For you professional Perl programmers: how do you approach > > exception-handling in the your world? I know there are a lot of ways > > Perl > > gives us to do this: basic 'die', eval'ing blocks of code and the > > Exception.pm module but is there a standard in the real world for > > handling > > exceptions? > [..] > > On Jun 8, 2004, at 11:39 AM, Wiggins d Anconia wrote: > [..] > > In my world, and a scary place it tis', I use a home > > grown object and just throw it as a return value. > > Subs generally then return either undef or the exception, > > or in the case I need a return value back I just check that > > return value to see if it is an instance of my exception > > object type. > [..] > > As a strategy this seems to be catching on. > I have not looked at Schwartz's kvetchings > about the Exception::Class - but it too would > seem to be working in this tactic; a la: > > my $got_back = $obj->method(@args); > > if ( ref($got_back) eq "Foo::Bar") > { > # deal with 'foo::bar' case > } else { > # else cope with alternative... > } >
Yeh, after Randal mentioned the Exception::Class and peering at it very briefly I was most pleased to find that I must be doing something right, since my Exception object works nearly the same. The quick doc I wrote for the rest of my team went something like this: "Note that because of Perl's ability to chain method calls using the -> (arrow) operator it is possible to create a new exception and attach the previous "triggering" exception to it all in one call. This makes it easy to propagate the exception up an execution chain, while allowing the exception to store a full stack trace. For example, the following is what I mean by chaining method calls, Exception->new->throw(...); This says to call the 'new' method of the Exception class, then call the 'throw' method on whatever the return value was from Exception, which is naturally an instance of the Exception class. In this case the special functionality is provided by the 'throw' method which recognizes whether it is getting multiple arguments meaning that it is an initial exception, or it takes another exception object, in which case it is a rethrow or propagated exception. There is the third possiblity, though it was used very infrequently in our app, where a new exception was thrown, but a triggering exception was still added. Exception Handling Most functions will return nothing on success or an exception in the case of a problem. Always check the return value of the function. Example 1: Subroutine that returns nothing on success or an exception on failure my $result = $obj->function_that_returns_nothing; if ($result) { # re-throw exception result return Exception->new->throw($result); } sub function_that_returns_nothing { my $self = shift; # perform a bunch of stuff if (<failure condition>) { return Exception->new->throw(IERR, PROGCODE, EXC_<name>, $!); } # perform some more stuff if (<another failure condition>) { return Exception->new->throw(FAIL, PROGCODE, EXC_<different name>, $!); } return; } Example 2: Subroutine that returns a value or an exception on failure, must check type of return value my $value = $obj->function_that_returns_value; if (UNIVERSAL::isa($value, 'Exception')) { # rethrow exception return Exception->new->throw($value); } # optional else else { # handle value here } Additionally I added a 'get_messages' method to get a stack trace for when actually handling the exception itself, but because it is just passing an object around the handler can be really simple and just at the top of the execution. Again I didn't look at Exception::Class close enough to see how it handles what I call the 'trigger', but the other difference in what I wrote above is that I use a set of exported constants to determine the type of the exception, for instance IERR (internal error) above, and a set of EXC_* constants for having a standard formatted message, such as EXC_FILE_DNE with a specific error code such as 0012 and a message like "File does not exist: %s" which is then passed off to sprintf when setting the message in the object. A plain message can be generated with a EXC_GENERIC. I just wish I had known about Exception::Class at the time!!! > But a core part of the problem is that one either > goes back into the 'original code' and starts to > clean it up to lace the 'exception handling' into it. > > Or one essentially uses it and wraps it with this > type of exception handling. > Yes, or as in my case we were refactoring everything from scratch so didn't have to worry about either! ;-) > On Jun 8, 2004, at 12:51 PM, Randal L. Schwartz wrote: > > > > In a few weeks, you'll be able to read > > <http://www.stonehenge.com/merlyn/PerlJournal/col12.html>, or you can > > get it from TPJ now if you're a subscriber. But in there, > > I tout Exception::Class as a good solution. > > We look forward to the kvetch. > Definitely. http://danconia.org -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>