|Problems? Is your data what you think it is?|
Best practices for handling errorsby v_melnik (Scribe)
|on Sep 27, 2014 at 11:31 UTC||Need Help??|
v_melnik has asked for the wisdom of the Perl Monks concerning the following question:
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.
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.
So, usually it looks like this:
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 $@.
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!