Target Audience: This pitch would interest a developer interested in the Exception Handling Best Practices in Perl. This series starts with basic exception handling and adds complexity, ending with pragmatic Best Practices recommendation.
So you've come back wanting to put a stack-trace in your code. Here's the code, before we start deconstructing. Add this sub throw to your code and call it 'myLittleException01.pl'.
sub throw {
my $mess = shift;
my $i = 1;
package DB;
while (my @parts = caller($i++)) {
print "$parts[3](@DB::args), $parts[1], $parts[2]";
};
die $mess;
}
Modify sub 'inner3' to 'throw' instead of 'die' as illustrated:
sub inner3 {
# throw ("junk");
my $fname = shift;
my $secret;
open(SECRET, "<$fname") || throw ("Unable to fopen $fname");
$secret = < SECRET >;
close(SECRET);
return $secret;
}
Note, you can 'throw' just as well as 'die' anywhere in your code.
Before go any further, proof of the pudding is in the eating. Here's what a stack-trace looks like.
There are actually three stack-traces here - did you notice? That's because my main package executes the functions as follows:
# F i r s t #
eval {
$secret = outer($fname, "1");
};
if ($@) {
print $@;
}
# S e c o n d #
eval {
$secret = inner2($fname);
};
if ($@) {
print $@;
}
# T h i r d #
$secret = inner1($fname);
Why am I doing this? To demonstrate that this is indeed genuine stack-tracing. Bear with me if it seems redundant.
Now for the catechism.
Follow me! (Cont'd)
8.
STACK TRACE
What is it? How does it benefit?
Run the script.
Track the programmatic flow via stack-trace.
10.
sub 'throw' - what is the minimum definition? ('die', with message)
sub throw {
my $mess = shift;
die $mess;
}
11.
use 'caller' for STACK TRACE
What is the frame-stack? (Code executes in frames. Like shooting pictures with a camera in rapid succession to execute a movie.)
Is a function in Perl self-aware? (Can it introspect?)
Does a function know what frames were executed before it?
How to obtain a frame-stack?
perldoc caller
Try the following: put in sub 'caller' and observe behavior.
What do you see?
sub throw {
my $mess = shift;
my $i = 1;
while (my @parts = caller($i++)) {
print "$parts[1], $parts[2], $parts[3]";
};
die $mess;
}
12.
Use 'caller' for STACK TRACE (cont'd).
perldoc caller - in case you missed it first time! :o)
Try the following: refine 'caller' behavior.
What do you see?
sub throw {
my $mess = shift;
my $i = 1;
while (my @parts = caller($i++)) {
print "$parts[3](), $parts[1], $parts[2]";
};
die $mess;
}
13.
Try the following:
Uncomment in 'inner3' - throw("junk")
Call 'inner3' in main without the 'eval' block;
What do you see?
14.
To see the arguments of a function call.
perldoc DB
package DB
sub throw {
my $mess = shift;
my $i = 1;
package DB;
while (my @parts = caller($i++)) {
print "$parts[3](@DB::args), $parts[1], $parts[2]";
};
die $mess;
}
15.
The final script is provided below.
use strict;
$, = "\t", $\ = "\n";
my $fname = 'secret1.dat';
my $secret;
eval {
$secret = outer($fname, "1");
};
if ($@) {
print $@;
}
eval {
$secret = inner2($fname);
};
if ($@) {
print $@;
}
$secret = inner1($fname);
print $secret;
sub outer {
my $fname = shift;
my $secret;
$secret = inner1($fname);
return $secret;
}
sub inner1 {
my $fname = shift;
my $secret;
$secret = inner2($fname);
return $secret;
}
sub inner2 {
my $fname = shift;
my $secret;
$secret = inner3($fname);
return $secret;
}
sub inner3 {
# throw ("junk");
my $fname = shift;
my $secret;
open(SECRET, "<$fname") || throw ("Unable to fopen $fname");
$secret = < SECRET >;
close(SECRET);
return $secret;
}
sub throw {
my $mess = shift;
my $i = 1;
package DB;
while (my @parts = caller($i++)) {
print "$parts[3](@DB::args), $parts[1], $parts[2]";
};
die $mess;
}
What have we achieved? Quite a bit, actually! We are able to attain a stack-trace and that itself is of enormous value in debugging. But before we get too excited, what are some the potential drawbacks?
Aha! I still depend on strings for error-handling. How would you like to improve the world a little bit further? Did I hear you say "Exception Classes?" That's right. Ladies and Gentlemen, I give you, Exception::Class (Sound of furious clapping and oohs and aahs as the public goes wild in anticipation.)
That's what's coming up in Part-03.
No comments:
Post a Comment