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

I am writing a module to support an internal project, and I've come to the point where I need to design the error system. In general, when module subroutines encounter an error, they must return the error string (which is actually specified outside my control) so that the calling code can decide what action to take for that specific error.

The error strings are modelled after network protocol communication, i.e. they begin with a number, a space, and then contain the error text '220 Cannot connect to service'. The programming model I generally use is "Return true on success, False on failure". Obviously (as I confirmed in a CB session with tye,theorbtwo and others) I cannot return error strings that are logically false, but I'd like to preserve the illusion. ;-)

Imagine code looking somewhat like this:

unless ( $object->method('param') ) { ## somehow get $errstr my ($errcode) = split ' ', $errstr; &$erract{$errcode}($errstr); } ## %erract contains such things as ('220' => sub { die $_ });

My debate comes in the 'somehow get $errstr' area. I could do what DBI does, and set $Module::errstr, but I've always personally disliked that approach, and the development section rules here strongly eschew globals in "includes" (It's not a Perl shop, so I interpret that to be "modules" for my purposes).

Ideally, the above chunk of code would leave the error string in $_, so that this would work:

unless ( $object->method('param') ) { my ($errcode) = split ' ', $_; &$erract{$errcode}($_); }

The closest way I can think of to implement that is to use die to throw and catch exceptions, like:

eval { $object->method('param') }; if ($@) { my ($errcode) = split ' ', $@; &$erract{$errcode}($@); }

But, I think I may have screwed myself out of being able to do that -- I use exceptions for internally fatal errors, and I am loathe to call any of the spec errors "fatal".

Is there another way to use this general approach to dealing with errors? I'm looking to end up with calling code that is clean and understandable, even for Perl neophytes; but, of course, it's most important that it works well.

Thanks in advance for any ideas, links, reading resources, etc. related to this.

Update {

Thanks to dragonchild and monkey_boy, I have solved the problem by extending Class::Base, which roughly implements dragonchild's suggestion. Thank you to all the monks who helped me reason this one out!

Anima Legato
.oO all things connect through the motion of the mind