13.6. Reporting Failure
If someone is using a subroutine you wrote: use Data::Checker qw( check_in_range ); for my $measurement ( @remote_samples ) { check_in_range($measurement, {min => 0, max => $INSTRUMENT_MAX_VAL}); } they're not going to want to encounter an exception like this: Value 24536526 is out of range (0..99) at /usr/lib/perl/Data/Checker.pm line 1345 The message itself is fine, but the location information is close to useless. Developers who are using your code don't care where your code detected a problem; all they care about is where their code caused the problem. They want to see something like: Value 24536526 is out of range (0..99) at reactor_check.pl line 23 That is, they want to be told the location where the fatal subroutine was called, not the internal location where it actually threw the exception. And, of course, that's the whole purpose of the standard Carp module: to report exceptions from the caller's point of view. So never use die to throw an exception: die "Value $val is out of range ($min..$max)" if $val < $min || $val > $max; Always use croak( ) instead: use Carp; The only situation when die could reasonably be used instead of croak( ) is if the error is a purely internal problem within your code, and not the caller's fault in any way. For example, if your subroutine is supposed to generate a result within a certain range using a very complicated process, you might choose to test whether the result was valid before returning it, like so: die "Internal error: somehow generated an inconsistent result ($result)" if $result < $min || $result > $max; return $result; The simple rule of thumb here is that any exception message thrown with a die should always start with the words: 'Internal error:...'. However, even in the case of internal errors, it can still better to use croak( ): croak "Internal error: somehow generated an inconsistent result ($result)" if $result < $min || $result > $max; return $result; For a start, reporting the internal error from the caller's point of view allows developers to work out where their code is affected by your bug (in other words, where they'll have to devise a workaround). More importantly, the Carp module provides a special 'verbose' option, which can be activated from the command line: > perl -MCarp=verbose bug_example.pl Running a program with this mode enabled causes every call to croak( ) to provide a full stack back-trace after the error message. For example, instead of a message like: Internal error: inconsistent data format at 'bug_example.pl' line 33 under the "verbose" option, you would be given the full context of the failed call, including subroutine arguments: Internal error: inconsistent data format at /usr/lib/perl/Data/Loader.pm line 58 Data::Loader::get('income.stats') called at ./Stats/Demography.pm line 2346 Stats::Demography::get_stats_from('income.stats','CODE(0x80ec54)') called at 'bug_example.pl' line 33 By always reporting internal errors via croak( ), you make it easier for developers to cope with them at the time, and easier for you to debug them later (without having to modify your module's code to do so). All the preceding arguments apply to warning messages, too. So always report warning messages using the carp( ) subroutine, instead of the built-in warn. |