Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

Dear colleagues,

I think, it's a matter of religion, but I'd like to get to know more on how other people, more experienced, prefer to handle errors/exceptions in respect to the structure of your programs.

Let me describe how I'm doing it now and, if you have some time to share your experience, I'd be very grateful to you for describing how do you prefer to do it.

My own "rules" for myself are quite simple.

  1. Don't die() while executing a subrotine or method. Only the main module can die() if something goes wrong. Nobody can predict where the class will be used, so an unexpected die() can break the caller's logic.
  2. If I've got an exception inside of a subroutine, the subroutine may return(undef). If everything's fine, it return's some value (it can be true or false - no matter), but if some error has been occuried (e.g. if we can't get data from the database), the undef shall be returned.

That's okay, but how to let the caller know what's happened with the subroutine? As I think, the caller must have some explaination to be able to write something to the log-file or to show the error message to the operator. So, there is one more rule.

  1. Any class may have the "errstr" attribute, so if its' methor returned undef, the caller may get the explaination from this attribute.

So, usually it looks like this:

package SomeClass; #... sub some_method { # ... eval { die("Oops!"); }; if($@) { $self->{'errstr'} = "Something has gone wrong: $@"; return(undef) } # ... } #... package main; #... my $result = $obj->some_method; unless(defined($result)) { die("Can't SomeClass->some_method(): $obj->{'errstr'}"); } #...

And, when something goes wrong, I can get something like that:

Can't SomeClass->some_method(): Can't AnotherClass->another_method(): Can't OtherClass->other_method(): Can't open(): No such file at script.pl line 666.

Frankly speaking, I have a persistent feeling that there are some other, much more elegant way to do it. And I hate how the final error message looks like. Just like "can't A, because can't B, because can't C, because f*** you". Ugh... :(

And there is another annoying thing: I have to use die() in the constructor of an object (I mean new()), because if the constructor returns undef, the caller doesn't have an access to the object's "errstr" attribute at all (as we don't have the object bless()ed). So I have to always call constructors from eval()-blocks and get the explaination from $@.

package SomeClass; #... sub new { # ... eval { die("Oops!"); }; if($@) { die("Something has gone wrong: $@"); } # ... } #... package main; #... my $obj = eval { $obj->new }; unless(defined($obj)) { die("Can't SomeClass->new(): $@"); } #...

I absolutely hate it, but I don't see better ways to let the caller know why the object hasn't been blessed.

Maybe I should consider using some global variable to keep the reference to the stack of errors occuried? What do you think?

Maybe I should always die() (or confess() - as a better way to get to know who has called whom) inside of any method and call every method inside of eval()- or try()-block?

I'll be very grateful to each of you for sharing your best practices on this matter. It really makes me feel unsatisfacted. :)

Have a nice time!

UPD: Now I see, why it's better to use exceptions such as die(), croak() or even my own exception classes based on Throwable::Error superclass instead of returning undef's or setting flags. Lots of thanks to all!

V.Melnik

In reply to Best practices for handling errors by v_melnik

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (6)
As of 2024-04-25 13:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found