Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: Style guide for error messages?

by rir (Vicar)
on Sep 21, 2005 at 22:22 UTC ( #493989=note: print w/ replies, xml ) Need Help??


in reply to Style guide for error messages?

Perl Best Practices covers this issue well. Objects are the thing to throw.

I disagree with some of your ideas:

  • Warnings should be meaningful. A warning that needs no action can be ignored, then will be ignored, then just becomes useless verbiage. Make it an error or silence it.
  • "Fatal errors" are a self defining group. You don't need to tag them so. Update: I wish I hadn't said that. It is true, but if you know your exception should be fatal you should capture that information in the exception. One just needs to be careful of unwarranted assumptions about the calling environment.
  • Always provide the line number of the error and/or the caller. If some part of the code doesn't handle input correctly, you will need to know which code that is.

Like Best Practices I would suggest using objects, in your first pass use the object type and the long output of a bare croak, in your message clean up phase use another method to output the exceptions' error strings. Since these methods or the table they use doesn't exist the brokenness forces the fix; examining your type tree gives you a list of all your errors and their meanings then you just need express them. This implies handler objects or another way of consolidating your error handling code.

You may complain that I've only moved your problem to the naming of exception packages. I won't argue.

Be well,
rir


Comment on Re: Style guide for error messages?
Re^2: Style guide for error messages?
by xdg (Monsignor) on Sep 21, 2005 at 23:25 UTC

    I agree on objects being the thing the throw. (c.f. Exception::Class and my own Exception::Class::TryCatch)

    However, even the object carries with it some message that may wind up in front of the user. But if I understand your argument, you're suggesting never bothering to add any error string at the time of the croak -- just the default system output -- and using the description defined in the Exception::Class object as the message instead. That does just push the problem upstream, as it were, but at least it's done only once, and at a time when more thought can be devoted to crafting the message (and it can be parameterized with fields as necessary). That's a good idea. ++

    On the other hand, I think it requires overriding the as_string function to stringify as the description plus the right field(s) in case it isn't caught. Lots of up front work, but on a large project, definitely less headache in the long run. E.g., a very brief, quick example:

    use Exception::Class ( 'FileOpenError' => { isa => 'Exception::Class::Base', description => "Error: couldn't open the file called ", fields => [ 'filename' ], alias => 'throw_file_open_error', }, ); BEGIN { # minimal stringification *FileOpenError::as_string = sub { my $self = shift; return $self->description() . $self->filename(); } } # later... open my $fh, "<", $filename or throw_file_open_error( filename => $filename );

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re^2: Style guide for error messages?
by Anonymous Monk on Sep 22, 2005 at 09:36 UTC
    I seldomly include the line number in my error messages. The vast majority of my usage of 'die' is after a system command:
    open(...) or die(...); chmod(...) or die(...);
    If I can't open a file for some reason (it doesn't exist, I don't have permission, whatever), all I care about is which file did the program try to open, and why can't it open the file. It doesn't matter whether it tried to open the file on line 23, or on line 389 - dies not being caught by eval will report to the user, and should contain only information that's relevant to the user. Line numbers aren't.

    The second largest group of die usage are meant as exceptions. Again, line numbers are useless - the die is supposed to be catched (or escalated to a real die), and I need an informative message or datastructure. That's what I'll inspect in $@ - not a line number.

    I might want to know line-numbers is during debugging. But croak() already gives a stack-trace, and that is often already enough.

    The compiler emitting line-number on syntax error, now that's a useful use of line numbers.

Re^2: Style guide for error messages?
by tilly (Archbishop) on Sep 22, 2005 at 17:38 UTC
    And I disagree with Perl Best Practices.

    The advice in PBP is designed to be one fairly good way to do things. It is not the only possible one, and it is not necessarily the best for all circumstances.

    I agree that if you attempt to use exceptions as a flow of control, then it is much better to throw objects than strings. But I'd prefer that exceptions generally be fatal, and would like to discourage trying to use the exception system for complex flow of control. Which means that all of TheDamian's arguments for exception objects are arguments for how to better do what I'd like people not to do.

    This is not to say that PBP is wrong. It is correct that it provides an internally consistent set of best practices. But it is not the only possible one, and it is not my preferred one.

      This is not to say that PBP is wrong. It is correct that it provides an internally consistent set of best practices. But it is not the only possible one, and it is not my preferred one.
      So, naturally, enquiring minds now want to know what you prefer instead! :-)
        I only got permission to quote 20 of your best practices. Doesn't quite work with the format that I wanted to use to give a comprehensive picture of exactly what practices I agree and disagree with, and why. (Unsurprisingly, I agree with more than I disagree with. And the ones that I disagree with I'd agree with in different circumstances.)

        I'm debating writing the whole thing anyways and hoping that after the fact I can get permission to post it. But that's a lot of work for what I suspect will be a "no". :-(

      ... I'd prefer that exceptions generally be fatal, and would like to discourage trying to use the exception system for complex flow of control. Which means that all of TheDamian's arguments for exception objects are arguments for how to better do what I'd like people not to do.

      The emotion behind this evokes some fellow feeling but I don't find much logic in it. Exceptions are always a flow of control mechanism. Exceptions usually are fatal. Exceptions should be used to clarify flow of control. And if you must do something, distaste is not a reason to do it badly.

      Exceptions are all about passing control to unknown code.

      The type or value of an exception should rarely be needed by the handler; that is the start of a brittle, tangled mess. I use the type to carry meaning without being locked into a representation (for those rare occasions). I use the object to carry a bunch of diagnostic data.

      I use exceptions like a more robust and efficient version of the LIBNAME_STATUS variables common to old C libraries. Rarely is there any fine discrimination by the handler, usually just FAILURE vs. SUCCESS.

      Be well,
      rir

        I think we disagree on what it means to do this badly.

        First in what I do, the point of an exception is to cause a program to terminate, with a message made available (in a log, email, or on STDERR) that will give a programmer somewhere to start in fixing the problem. If that is the point, then creating an object is extra overhead that obscures what you're trying to do. Therefore for this specific scenario, creating an object is worse than just creating the message that you want to see logged. Because even though the effect may be the same, you obscured what was going on.

        In the worst case, your error handler has a mistake and you don't successfully generate an object! Yes, we should all have tests. But reality is that our error checking code tends to be the least tested, and therefore should be coded in the most simple and straightforward way possible. It is harder to not notice messing up a string than a method call, so strings are to be preferred.

        Now let's go on to the point that I initially made.

        In general when I see exception objects being created, my expectation is that someone is intending to catch those objects and process them in interesting ways. Now sometimes that might be appropriate. For instance if you want to display messages in a language-localized fashion. Or if you need to display messages after postprocessing in various ways (text message for a command line, popup for a GUI, HTML for a web form). However it is not appropriate for what I'm doing. Which raises the question of why they are being used.

        Now, as I said, I think that just constructing the final message is better because it is more straightforward. However what some people like to do is use exceptions as a general flow of control mechanism. Yes, I know that they have the capability of doing so - else they wouldn't be useful. But when people start using exceptions that way, you get into problems. Some people dislike that in all circumstances. I'm not entirely convinced of that, though I dislike the action at a distance. But the fragility of eval, $@ and die in Perl causes me to be particularly suspicious of the design idea because I know how easy it would be to just swallow exceptions rather than doing something useful with them.

        And a random point on the topic. Re: Re2: Learning how to use the Error module by example mentions specific problems with one module that tries to make exception handling cleaner in Perl. I have no idea whether others are prone to the same kinds of issues, but unless I'm given some concrete benefits, it isn't worth my energy to find out.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://493989]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2014-10-02 11:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    What is your favourite meta-syntactic variable name?














    Results (55 votes), past polls