Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Replacing warn/die with carp/croak?

by dragonchild (Archbishop)
on Oct 04, 2007 at 13:58 UTC ( [id://642655]=perlquestion: print w/replies, xml ) Need Help??

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

(This node was prompted by #29709: DBM::Deep should use Carp module)

I'm going to come out and say it - I've never liked the output from Carp. Ever. The stacktrace is humungous, hard to navigate, and very rarely provides anything useful (to me). But, I know a lot of people that I respect like Carp a lot. As such, I'm willing to entertain the idea that I should replace warn/die with carp/croak. But, the reasoning in the ticket is a bit light and I'm not happy with the tone the requestor is taking. As such, I'm coming to the monks for suggestions.

  • Do you like to see carp/croak or warn/die when using a CPAN module?
  • If you have a CPAN module, what do you use? Why? Have you switched from one to another? Why?

My criteria for good software:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Replies are listed 'Best First'.
Re: Replacing warn/die with carp/croak?
by ikegami (Patriarch) on Oct 04, 2007 at 14:24 UTC

    What are you talking about? croak and carp don't create a stack trace.

    >type script.pl use M1 qw( ); sub test2 { M1::test3(); } sub test1 { test2(); } test1(); >type M1.pm package M1; use M2 qw( ); sub test4 { M2::test5(); } sub test3 { test4(); } 1; >type M2.pm package M2; use Carp qw( croak ); sub test5 { croak("ribbit"); } 1; >perl script.pl ribbit at M1.pm line 3

    Although you can force them to produce a stack trace.

    >perl -MCarp=verbose script.pl ribbit at M2.pm line 3 M2::test5() called at M1.pm line 3 M1::test4() called at M1.pm line 4 M1::test3() called at script.pl line 2 main::test2() called at script.pl line 3 main::test1() called at script.pl line 4

    If there's a reason against using carp and croak, it's that they hide the true source of the error in an attempt to tidily show the actual source of the error. When that's not good, the person debugging the problem can turn on verbose mode and get the information he needs.

Re: Replacing warn/die with carp/croak?
by brian_d_foy (Abbot) on Oct 04, 2007 at 21:07 UTC

    This particular bug report looks like more Perl Best Practices fanboyism where the reporter doesn't understand what's actually going on in the code. It's clear from his response that he doesn't understand why you shouldn't change it, just that no one should ever, ever use die. There's no associated programming problem here (or that he has reported).

    Most of the calls to die in DBM::Deep are for code that happens very early (as in _init) and usually around an eval where some special magic is happening. That's internals stuff that no user should be thinking about.

    DBM::Deep does its error handling with _throw_error, which already handles what Carp does (mostly). I know because I sent Rob the patch to make that happen. The complaint that DBM::Deep is not going to show its exceptions from the perspective of the caller is just ignorant. It does that already because I made something better: _throw_error shows the file and line number from the first thing that isn't inside DBM::Deep. Since something inside DBM::Deep is calling _throw_error, croak would report a line number inside DBM::Deep still. Replacing that with croak would be a step backwards, and it would break some of my code when croak starts reporting the wrong thing. If there's a bug in _throw_error, report that with an example script that shows the bug.

    I say close the ticket and ignore it. RT does have a "reject" option. :)

    --
    brian d foy <brian@stonehenge.com>
    Subscribe to The Perl Review
Re: Replacing warn/die with carp/croak?
by Sidhekin (Priest) on Oct 04, 2007 at 14:29 UTC

    If you have a CPAN module, what do you use? Why? Have you switched from one to another? Why?

    I use both die and croak: die for internal exceptions, caught or uncaught; croak for user errors. (I use neither carp nor warn, but would probably distinguish those similarly, if I had cause to use them.)

    Do you like to see carp/croak or warn/die when using a CPAN module?

    carp/croak, definitely. For user errors, that is the most helpful (telling me where I made a mistake, and not where the module found it). For internal exceptions, I prefer the module handle those itself, and don't show me. (Of course, if it cannot handle those itself, it should show me, most usefully using die. I just won't like it.)

    print "Just another Perl ${\(trickster and hacker)},"
    The Sidhekin proves Sidhe did it!

Re: Replacing warn/die with carp/croak?
by toolic (Bishop) on Oct 04, 2007 at 14:23 UTC
    I like Carp so much that I use confess in my private modules to get the maximum stack information.

    When things go wrong, I want as much detail as possible. I am also a fan of use diagnostics;

    I have never created anything worthy of submitting to CPAN, but I do prefer CPAN modules which use Carp.

    That's my 2 cents.

Re: Replacing warn/die with carp/croak?
by moritz (Cardinal) on Oct 04, 2007 at 14:24 UTC
    In my modules (both on CPAN and private ones) I always die with a Carp::confess.

    I don't like croak() because it could lead to errors that are hard to find, especially when the module that uses it is buggy.

    The output of confess() contains all the information that I need to find the bugs, and it allows me as a user to judge if a bug is in the calling code or in the code of a module.

Re: Replacing warn/die with carp/croak?
by shmem (Chancellor) on Oct 04, 2007 at 14:41 UTC
    I like the less convoluted and most flexible solution. I use Carp::cluck and Carp::confess a lot during development, switching later to warn and die.

    There are cases in which croak reports wrong line numbers. I generally prefer modules which use just warn and don't die, because die in a module leads to evalitis.

    I would rather see warn in modules, because I can override that easily with a $SIG{__WARN__} = \&Carp::cluck, and don't have to redefine Carp::croak.

    I have stumbled over a very nasty usage of croak in the IO::All module, which wraps croak into a function called throw(). Took me some time wondering, and searching through the module to find out why my __DIE__ handler didn't work. I ended up redefining IO::All::throw with a custom function.

    So, I wouldn't make the change, but answer to the ticket issuer "You can always install your custom handlers via $SIG{__WARN__} and $SIG{__DIE__}" and leave it there.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Forcing usage of $SIG{__WARN__/__DIE__} sounds poor. However, does it make sense to provide an option for using carp/croak vs. cluck/confess vs warn/die ?

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
        Sounds poor? Well, those pseudo signals exist for that purpose.

        A verbosity switch makes sense, imho.

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Evalitis [ee-vuh-lie-tis]: Sounds like a disease, but actually a good thing. Also see: suffrage. DISCUSSION: Don't be afraid to die (or croak). Let them eval you. That will lead to more maintainable code. </word-of-wisdom-from-fenLisesi-the-quack>
        Let them eval you. That will lead to more maintainable code.

        A bold statement. Please expand your reasoning - why would them having to eval me make their code more maintainable? or mine, for that matter?

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Replacing warn/die with carp/croak?
by jhourcle (Prior) on Oct 04, 2007 at 14:17 UTC

    My modules aren't in CPAN (I guess one of these days, I should release 'em, but there's less than 10 people who seem to be searching for solar physics data and were interested in installing the software so far), but I'd have to say that I use both carp and warn. I _rarely_ use croak or die.

    Basically, if we were to think of it as the difference in a webserver throwing a 500 level error vs. a 400 level error -- was this something wrong with _this_ code, or was it somethig wrong with the code that called this code?

    So, if bad arguments were passed in, I use carp. If I hit a branch of logic that seems like something went wrong with my code, I use warn (in extreme cases, die, but they're typically reserved for major problems, like someone not defining required functions when inheriting an abstract class ).

Re: Replacing warn/die with carp/croak?
by SuicideJunkie (Vicar) on Oct 04, 2007 at 16:33 UTC

    I thought the use of carp/croak was fairly intuitive when I first saw it (after running it to see the output):

    • If it is you or your children's fault, you warn/die.
    • If it is clearly the caller's fault, you carp/croak.
    • If in doubt, warn/die

    For example; At the beginning of a sub, sanity check the input and carp/croak if it is bad (too many, too few, invalid data, wrong reference type, etc). Then roll along, and use warn/die when things the sub does go wrong. If in doubt, warn/die.

    The key thing IMO being to make sure that when carp/croaking, the caller knows what you're talking about. If your error message refers to a parameter or lack thereof, carp/croak makes sense.
    The Bar() sub could carp/croak with the following message, for example:
    "Unmatched parentheses in Parameter 1 at file Foo line 42:  $Answer = Bar('(2+5))*5');"
    And that makes perfect sense as an error message.

    "Failed to open log file for write" on the other hand, is not the caller's fault. Unless one of your parameters was a filehandle to use as a log, they will have no idea what the message is talking about. If you were passed in a filehandle for that purpose, the message could be better written as
    "Log filehandle in Parameter 5 could not be opened for write"

Re: Replacing warn/die with carp/croak?
by stvn (Monsignor) on Oct 04, 2007 at 17:50 UTC

    Personally I love confess, so much so that I export it by default in Moose. I understand the argument that stack traces are ugly, but when I have a fatal error, I want as much information as possible at that very moment so I don't have to go back and try and reproduce the error and other such hoop-jumping-through stuff.

    In some cases I think using die/croak is okay, but in a library I think it can be frustrating. A good stack trace (and the occasional bit of source diving) will almost always tell me who is causing the error (me or the library). Whereas a die/croak means I have to do my own stack tracing to find the path from my code to the error, and that is tedious even in the cleanest code. Some might say that really good error messages will accomplish all this without needing a stack trace, but IMO that is just delusional.

    As for the dependency issue, its a noop, Carp is in the core.

    Oh yeah, just to play devil's advocate, there is always Carp::Always.

    -stvn
Re: Replacing warn/die with carp/croak?
by perlfan (Vicar) on Oct 04, 2007 at 15:25 UTC
    Without trying to sound too much like a mindless fool, why worry about it if it is in Perl's core set of modules? I /like/ when Carp is in code I see because it tells me that the author /tried/ to do the right thing. I certainly don't use it all of the time and don't know about a fraction of its features, but I if someone is concerned about creating quality Perl code then I think it is very important to use - even if as a simple replacement for warn or die.
      Why do you equate using Carp with "doing the right thing"? That's what I'm trying to get at.

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: Replacing warn/die with carp/croak?
by graff (Chancellor) on Oct 05, 2007 at 02:42 UTC
    ...I've never liked the output from Carp. Ever. The stacktrace is humungous, hard to navigate, and very rarely provides anything useful (to me).

    I know what you mean about stack traces being big, noisy, pointless things -- and I totally agree. But it may be that the uses I've seen and had for carp/croak haven't been so "deep" that their output has been a problem for me.

    On the contrary, I've been really grateful for all the times where a given method or function from a module is being used in a lot of different places in an app that I'm working on, and when I make a mistake, carp or croak tells me which line number in calling code triggered it -- without a whole lot of other useless trivia (all the args passed at every layer of the call stack, what their memory addresses were, what the command-line looks like as hex bytes, blah blah blah...)

    (My colleagues who use python don't seem care much about error reports -- every time one of their python scripts hits a dead-end, the user gets several lines of doggerel with seemingly random white-space/line-breaks and rarely a legible word, let alone a coherent phrase. Even for cases where the user just needs to be told "file foobar not found". I don't understand why anyone would want or allow errors to be handled in such a way. But I generally don't see this sort of thing with perl code using carp or croak.)

    If you feel that users of your module are very unlikely to call a given method or function from more than one spot in their apps, don't worry about it. But if it's likely that one app might use a given sub in lots of different places, you'll probably be doing the module user a very big favor by telling which line in the caller's code caused a given problem.

      Simplest thing to do is go on using die and warn. Then if someone, perhaps you, wants more info, they can "use diagnostics". It's really much easier that going through your code and replacing everything. It's also more efficient... since the Carp (or diag) module need not be loaded unless there's a problem.

      Many module authors have taken to "require Carp" just before croaking.... to alleviate this... which is a cumsy but effective solution.

      I really think "use diagnostics" or perl -Mdiagnostics=-traceonly has replaced the need for carp/croak. If you need to be verbose ... you can get it as needed.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (5)
As of 2024-04-25 21:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found