Here's my take on handling parse errors, and error handling in general.

1. I don't like to (unconditionally) die from within libraries except for
conditions that are totally avoidable.  For example, I die if you forget to
send a required argument.  But I would not die in a parse() function that is
expected to handle user-created input!  That would force everyone to use an
exception-handling style of error checking just to use your modules, which
is not nice.

2. I use plain old undef as my error return value, but I sometimes document
the methods saying that any false value is an indication that there was an
error.  This works in all methods that return objects (which is most of the
ones I write, and any parsing method in DT).

3. I make sure I store some sort of sensible error message or code somewhere
convenient, letting the user of the library know why something failed.  Even
if it's only "Invalid date: 'foobar'", it goes a long way towards making
debugging easier.

I think this system gives the most flexibility to the user of a library.
Examples:

    # Use fatal errors
    $dt = DateTime->parse(...) or die DateTime->error;
    $dt->parse(...) or die $dt->error;

    # Use non-fatal errors
    if($dt = DateTime->parse(...)) { ... }
    else { warn DateTime->error }
   
    if($dt->parse(...)) { ... }
    else { warn $dt->error }

    # Use exception handling
    eval
    {
      $dt = DateTime->parse(...) or die DateTime->error;
      $dt->parse(...) or die $dt->error;
      ...
    };

    if(@$) { ... }

Finally, I want to immediately help anyone who does this:

    $dt = DateTime->parse(...);
    $dt->set(...);

By puking all over them right then and there.  While a "DT::Undef" object
might be useful for some, it should not be used as a return value in the
case of an error.  People who want to use it can just do this:

    $dt = DateTime->parse(...) || DateTime::Undef->new;

which is a lot clearer, IMO.  Also, I don't think DT::Infinite is in the
same boat, because that is a legitimate date (that DT::F::Simple must parse,
BTW: /^([-+])?inf(?:inity)?$/i).  Returning DT::Infinite is not an error!

-John

    
    

Reply via email to