Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
Points one, two, and five all seem to be arguing against return codes, which are in my view basically a certain (particularly inelegant) type of exception handling. You don't need to convince me that's a bad way to do it; my question is why it (punting an error to the caller's caller's caller) should ever be done at all.

Point (1), (2), and (5) still apply if you're only dealing with an error code at the caller level.

Point (1): Robustness. Consider:

my $output = ''; my $buffer; while (my $n = read(INPUT, $buffer, 1024)) { $output .= $buffer };

This code is broken because it is not checking for possible read errors (when read returns undef). This can lead to $output being silently truncated. If read threw an exception I could not accidentally ignore the error.

Point (2): Brevity. If we ignore passing the error up and just die I still have much shorter code when I do:

sub foobarfribbleni { eval {$o->foo->bar->fribble->ni}; die "failed to foobarfribbleni" if $@; };

Than if I had to do:

sub foobarfribbleni { $o->foo or die "failed to foobarfribbleni"; $o->bar or die "failed to foobarfribbleni" $o->fribble or die "failed to foobarfribbleni" $o->ni or die "failed to foobarfribbleni" }

Point (5): No confusion between return values and error conditions. The problem with the code using read above is because the developer has treated an possible error value as a legal return value. With exceptions that mistake cannot occur.

Regarding your third point, clarity: one of us is smoking crack, because putting code that handles an error pages away from where the error actually happens is my idea of severe obfuscation. How it could ever conceivably enhance clarity is entirely beyond my ability to fathom.

The argument is that the code will work one way 99% of the time. The 1% of error conditions are, well, exceptional :-)

With exceptions you can show the way your code works 99% of the time, without cluttering it up with the error handling code. The foobarfribbleni subroutines given above are one example. Another would be DBI, which you can switch between throwing exceptions or returning error codes. Compare:

# With exceptions eval { $sth = $dbh->prepare(q{ SELECT region, sales FROM sales_by_region +}); $sth->execute; my ($region, $sales); $rv = $sth->bind_columns(\$region, \$sales); while ($sth->fetch) { print "$region: $sales\n"; } }; die $dbh->errstr if $@;


# Without exceptions $sth = $dbh->prepare(q{ SELECT region, sales FROM sales_by_region }) or die $dbh->errstr; $sth->execute or die $dbh->errstr;; my ($region, $sales); $rv = $sth->bind_columns(\$region, \$sales); while ($sth->fetch or die $dbh->errstr) { print "$region: $sales\n"; }

Personally, I find the exception throwing version easier to parse without the sprinking of die statements.

Point four, however, I'd like to explore further. Maybe I just haven't encountered the right problem yet. Every error I've had to handle either could be fixed, or it couldn't. If it couldn't be fixed, it either could be logged and ignored and the program proceed less certain functionality, or else it was fatal. That basically leaves three options when an error condition pops up: do stuff to fix the problem, log it and go on, or spit an error message and exit. I have yet to encounter a situation where the caller might be relevant to the question of which of these conditions applies.

An example:

We have a registration system App::RegisterUser that needs to store usernames and e-mail addresses in a database. The usernames and e-mail addresses need to be unique.

App::RegisterUser forms part of a larger system App. All the DB access goes through App::DBI which has all the common DB access code in it.

App::DBI is built on top of DBI.

We take our data integrity seriously, so we have registered uniqueness constraints on the underlying database tables so that attempting to insert duplicate usernames or email addresses causes an error. This also allows us to get around any race conditions since inserts and updates are atomic.

So, an attempt to add a duplicate user with App::RegisterUser will cause an error at the DBI level.

What is the right response to the error?

When I use App::RegisterUser as part of a web-based registration system the correct response is to tell the user that the name/email is already used and try again.

When I use App::RegisterUser as part of a bulk registration system the correct response is to log the error for later use.

So, we have two possible responses to the error from App::RegisterUser, which comes from App::DBI, which comes from DBI.

In reply to Re^2: Best Practices for Exception Handling by adrianh
in thread Best Practices for Exception Handling by Ovid

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

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others chilling in the Monastery: (5)
    As of 2018-06-25 01:29 GMT
    Find Nodes?
      Voting Booth?
      Should cpanminus be part of the standard Perl release?

      Results (126 votes). Check out past polls.