Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Best practices for module error-reporting

by yulivee07 (Sexton)
on Feb 02, 2017 at 16:37 UTC ( [id://1180857]=perlquestion: print w/replies, xml ) Need Help??

yulivee07 has asked for the wisdom of the Perl Monks concerning the following question:

Hello fellow Perlmonks,

today I am asking for your wisdom in regards to best practices for error reporting in modules. I still would consider myself a novice, so this question may sound foolish to some.

So consider I want to write some kind of Module, currently I am working on one that internally deals with LDAP. The program using the module wants to know, if in a method call to the module something went wrong, e.g. the LDAP-connection timed out or something like this. There I somehow need to report errors happening to my module.

I see multiple ways of tackeling this and I am not content with either of them:

Option 1: report it with Log4Perl
All my programs write logs with Log4Perl anyway. So when my Module encounters an error, I report the Error-Message with Log4Perl and return 1 indicating an error.

Pro: Easy to do, Error easily found in log, not much clutter in my code
Cons: This is not very portable. Someone not using Log4Perl would not be able to use my module.

Option 2: internal error reporting in a moose errors accessor
I tend to write OO-Modules with Moose or Mouse. The module gets an accessor called "errors" like this:
has "errors" => ( is => rw, isa => "Str", predicate => "has_errors", reader => "get_errors", writer => "set_errors", clearer => "clear_errors", );
Every public method first calls
 $self->clear_errors(); 
, then executes its functionality. Everytime an error occurs I can perform a
 $self->set_errors($self->get_errors . $error_message); 
and stash my errors this way. In the program using the module I can perform a
 $module->get_errors 
to retrieve the error-messages and a
 $module->has_errors
to see if something went wrong.

Pro: Independent from Log4Perl!
Cons: Every Module of mine now has an errors accessor and some helperfunctions to add to this accessor, violating the DRY-principle. Also, not applicable if a method in the module itself, calls another function, as this would erase the errors-accessor. Obviously, doesn't work that great with non-OO modules

Option 3: Return an Error-Code
If everything goes right in a function, return 0. If something fails, return 1 or any higher number.

Pro: No hassle with overwriting error-accessors. I tend to use this for internal module-methods in mix with Option 2.
Cons: A lot! No proper error-message of what went wrong. If the method does return something (e.g. an LDAP-Object) this breaks and burns gloriously.

Currently I tend to use a mix of all these options and I do not like it. Option 2 makes me write a lot of similar code again and again, Option 1 makes me dependend on Log4Perl and Option 3 just doesn't work if the method returns something useful.

CPAN-Authors and Error-Catching-Perfectionists! How do you solve these problems? Proper error-catching is a very important duty in my coding environment as there services I have to work with tend to break a lot or are just not reliable and run a lot into timeouts.

I would love to hear some best practices and further options for dealing with this!

Greetings,
Yulivee

Replies are listed 'Best First'.
Re: Best practices for module error-reporting (updated x2)
by haukex (Archbishop) on Feb 02, 2017 at 16:46 UTC

    Hi yulivee07,

    Don't forget Carp, that's what I'd reach for first (Update: it's a core module). Its pros are that it reports errors as coming from the user's code, not necessarily the module's code, which is advantageous in the case of errors like "incorrect parameter passed". Second, users can enable stack traces, which can make debugging a whole lot easier. I'd only reach for a logger second, and even then I'd make it optional, since not everyone needs or wants a full-fledged logger.

    As for the "should I return a false value or throw an error" discussion, I dimly remember there have been several discussions of that question here on PerlMonks, unfortunately my Super Search skills are currently weak, but if I find them I'll update this node. Update: Here we go, a selection:

    Update 2: Just to briefly touch on the question of "return a false value vs. throw an error", I would make that decision based on what's truly an error vs. what is something that can occur normally (there is a bit of a gray area there too). For example, since you said you're writing a module for LDAP stuff, I'd say that something like "can't connect to server" should probably be an exception (via Carp), whereas for something like "no search results found", your function can return a false value. For the latter, note that there is a difference between return; and return undef;, in addition to being discussed in some of the above threads, here is another thread on that issue (and more, via search).

    Hope this helps,
    -- Hauke D

Re: Best practices for module error-reporting
by Laurent_R (Canon) on Feb 02, 2017 at 17:29 UTC
    It is probably a matter of personal opinion or taste, but I would avoid (if possible) adding dependencies that are not really necessary for the core features of your new module. They may dissuade people from using your module.

    This of course does not apply to core modules. I would also recommend Carp, which makes it possible to throw exception (and/or issue warnings) useful from the standpoint of the user, including stack trace and so on..

Re: Best practices for module error-reporting
by Anonymous Monk on Feb 02, 2017 at 21:15 UTC
    I see 2 kinds of errors: those for the users of the code and those for the developers of the code. For users of the code, just die in a consistent way but you will probably want some kind of framework if you have multiple developers working on the code. If your end product is something to be consumed by the public, then be mindful of your dependencies and try to eliminate them. If your end product installation and maintenance is handled by you, then you usually don't need to worry about NOT using such dependencies.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1180857]
Approved by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2024-03-29 01:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found