Re: Re: The art of error handling
by AgentM (Curate) on Dec 19, 2000 at 21:54 UTC
|
Since you mentioned CGI (thus, CGI app writing), it is extremely important to return some error code and message to the user/browser (this is called "user-friendliness"). This is not so intuitive until you use CGI::Carp or better yet, you own personalized error message system which fits in with the theme of the rest of the site. The problem I see with global variables is that they become to cluttery and are named differently for every module. I find function return codes far more useful and clear. Plus, you can put the whole shebang in the same statement!
die "Oops!\n" unless evilfunction(); #or "if", if you prefer
I suppose the use of the global vars carried over from C when you were basically stuck returning static variables for multi-variant-byte length information. Of course, Perl does not have this restriction and thus would recommend using returns. My favorite scheme is 0 for success, some string or number on failure- preferably something I might be able to output to the user. This is definitely that something that has come with me from my UN*X C background (POSIX likes to make success 0 now).
AgentM Systems nor Nasca Enterprises nor
Bone::Easy nor Macperl is responsible for the
comments made by
AgentM. Remember, you can build any logical system with NOR.
| [reply] [d/l] |
|
|
Since you mentioned CGI (thus, CGI app writing), it is extremely important to return some error code and message to the user/browser (this is called "user-friendliness"). This is not so intuitive until you use CGI::Carp or better yet, you own personalized error message system which fits in with the theme of the rest of the site.
But don't be too friendly. Never tell anything about why an error happened. Just say "something broke, we already know about it", no matter what went wrong. Do not say "database error" or "invalid URL" or anything that reveals
any kind of nature about why.
Yes, it's human nature to want to know (and to reveal), but it's a evil person's nature to use that information to reveal potential breakin paths. So don't. Just say no to "helpful error messages".
-- Randal L. Schwartz, Perl hacker
| [reply] |
|
|
Good point, VERY true with CGI apps, to use something like "...or die('Failed to open $file');" would reveal the path to a critical file to potential trouble-makers.
Hot Pastrami
| [reply] |
|
|
| [reply] |
|
|
My personal opinion is to never, ever, ever die when using CGI.
The most annoying thing to me (as a web user) is when something doesn't work and I'm just presented with an error. That pisses me off more than anything else. If I get an irrecoverable error (very, very rare), I want to see an error page that gives me options for notification, ETA on fixes, or other things I can do with my data that I just spent 15 minutes filling out.
And just to digress for just a moment, 404 pages suck. If the page isn't found, it's not there, but just don't leave me hanging, give me options or redirect somewhere. I went once to a lecture on usability, and while the lecture sucked, the speaker made one good point; that is that as programmers, we spend far too much time just quitting out of apps when something goes wrong. More care needs to be taken in handling the error. Sending an error message back to the user doesn't actually "handle" the error. It just passes it on for the end-user to handle, often times with no options whatsoever.
| [reply] |
|
|
return($success_ref, $error_ref);
Each subroutine returns either
$dbh->prepare($query) || return (0, "Error: " . $dbh->errstr);
or
return ($array_ref, 0);
You can pepper these throughout your code anywhere there's a DBI action able to fail and it ensures that you can fail somewhat gracefully.
It's not perfect, but it also makes error-checking easy (just test whether $errors contains anything) and allows you to develop a cascading series of calls where it doesn't bother executing subsequent queries if one has already failed. | [reply] [d/l] [select] |
Re: Re: The art of error handling
by Hot Pastrami (Monk) on Dec 19, 2000 at 21:51 UTC
|
But if you return undef or 0, the error is unspecific, it just means there was a failure... how do you address the specifics? I have been struggling with error checking myself, so I am quite curious what responses will appear.
Update: By the way, the way that I have been handling errors in modules is to have a sub called error() which takes a string, stores it in an ERRORS array in the package, and return undef, so I can have code like this:
open(TEST, ">$file") or return $self->error("Failed to open $file");
That way, I get the undef return value, and store the error in the array in one shot. There's probably a few better ways, though.
Hot Pastrami | [reply] [d/l] |
|
|
If you use subroutine/methods which perform simple
operations then the calling code usually either
ignores the error, fall back to another method (
$val= $obj->method || default) or dies quickly.
So I usually handle errors at the level just above the
method/subroutine where it happens. Not quite the
"detect at the lowest level and at the highest level"
philosophy, I admit, but it usually works for me.
| [reply] |