autodie 1.11_01 "Aristotle" released - Awesome inheritance

pjf on 2008-07-04T03:54:37

autodie 1.11_01 "Aristotle" released - Awesome inheritance
autodie version 1.11_01, codename "Aristotle", is now making its way through the CPAN. The new version contains quite a few exciting changes. You should be able to make and install the new version just like any other module, without having to muck around with @INC. Do be warned it will overpower your existing Fatal.pm, and while it should be completely backwards compatible, there's always the small risk of bugs that I've missed.

In this post, I want to show you why autodie is so cool, particularly with this new release.

Because autodie is smarter than Fatal, a whole bunch of things which are normally bugs start being correct if you're using autodie. As an example, take the following code:

if ( fork() ) {
   # This is the parent process.
} else {
   # This is the child process.
}

Normally, that code involving fork contains a bug, because fork could return an undefined value to indicate the fork failed. Since we're not checking for undef, our parent would act as a child process, and things are likely to go very badly from there.

However, with autodie we can write:

use autodie qw(fork);

if ( fork() ) {
   # This is the parent process.
} else {
   # This is the child process.
}

And now the code is correct! autodie knows that fork is allowed to return zero to the child, but returning undef is an error. This is much easier than checking the return values manually.

However in my opinion the best thing about the new release is that we can now cleanly subclass both autodie and autodie::exception, which means we now have a very easy way to slot in our own exceptions frameworks.

Let's start with a trivial example, and pretend we think the old name lethal was a better name for the module. We can just write inside a new lethal.pm:

package lethal;

use base qw(autodie);

1;

And now, we can use lethal the same way we would use autodie.

As a more complex example, let's say that we want to do a bit of localisation. I want an Australian version of autodie that caters to our strong cultural identity. I can write inside bludging.pm:

package bludging;

use base qw(autodie);

sub throw {
   my ($class, @args) = @_;

   return bludging::exception->new(@args);
}
package bludging::exception;

use base qw(autodie::exception);

# Mate, it's always a good time for a beer in Australia!
sub time_for_a_beer {
    return "Now's a good time for a beer.";
}

sub stringify {
    my ($this) = @_;

    my $original_string = $this->SUPER::stringify;

    return "$original_string\n" . $this->time_for_a_beer;
}

1;

I can now write:

use bludging qw(open);

open(my $fh, "<", "fair_dinkum.txt");

If fair_dinkum.txt doesn't exist, I get the Australian-friendly error message:

Can't open 'fair_dinkum.txt' for reading: "No such file or directory" at australia.pl line 1
Now's a good time for a beer.

Of course, one could instead extend the exceptions to use your favourite object framework, wake your sysadmins up in the wee hours of the morning, provide extra diagnostics and stack back-traces, or do anything else you consider worthwhile.

So, what are you waiting for? Grab yourself autodie 1.11_01 from the CPAN now, or (if your mirror is a little behind) you can download the release directly from my server.