> 
> 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>


Reply via email to