Author: Mark Gardner

  • Sweeter Perl exception classes

    Sweeter Perl exception classes

    What about My::Favorite::Module?

    I men­tioned at the Ephemeral Miniconf last month that as soon as I write about one Perl mod­ule (or five), some­one inevitably brings up anoth­er (or sev­en) I’ve missed. And of course, it hap­pened again last week: no soon­er had I writ­ten in pass­ing that I was using Exception::Class than the denizens of the Libera Chat IRC #perl chan­nel insist­ed I should use Throwable instead for defin­ing my excep­tions. (I’ve already blogged about var­i­ous ways of catch­ing excep­tions.)

    Why Throwable? Aside from Exception::Class’s author rec­om­mend­ing it over his own work due to a ​“nicer, more mod­ern inter­face,” Throwable is a Moo role, so it’s com­pos­able into class­es along with oth­er roles instead of muck­ing about with mul­ti­ple inher­i­tance. This means that if your excep­tions need to do some­thing reusable in your appli­ca­tion like log­ging, you can also con­sume a role that does that and not have so much dupli­cate code. (No, I’m not going to pick a favorite log­ging mod­ule; I’ll prob­a­bly get that wrong too.)

    However, since Throwable is a role instead of a class, I would have to define sev­er­al addi­tion­al packages in my tiny mod­uli­no script from last week, one for each excep­tion class I want. The beau­ty of Exception::Class is its sim­ple declar­a­tive nature: just use it and pass a list of desired class names along with options for attrib­ut­es and what­not. What’s need­ed for sim­ple use cas­es like mine is a declar­a­tive syn­tax for defin­ing sev­er­al excep­tion class­es with­out the noise of mul­ti­ple packages.

    Enter Throwable::SugarFactory, a mod­ule that enables you to do just that by adding an exception func­tion for declar­ing excep­tion class­es. (There’s also the similarly-​named Throwable::Factory; see the above dis­cus­sion about nev­er being able to cov­er everybody’s favorites.) The exception func­tion takes three argu­ments: the name of the desired excep­tion class as a string, a descrip­tion, and an option­al list of instruc­tions Moo uses to build the class. It might look some­thing like this:

    package Local::My::Exceptions;
    use Throwable::SugarFactory;
    
    exception GenericError  => 'something bad happened';
    exception DetailedError => 'something specific happened' =>
      ( has => [ message => ( is => 'ro' ) ] );
    
    1;

    Throwable::SugarFactory takes care of cre­at­ing con­struc­tor func­tions in Perl-​style snake_case as well as func­tions for detect­ing what kind of excep­tion is being caught, so you can use your new excep­tion library like this:

    #!/usr/bin/env perl
    
    use experimental qw(isa);
    use Feature::Compat::Try;
    use JSON::MaybeXS;
    use Local::My::Exceptions;
    
    try {
        die generic_error();
    }
    catch ($e) {
        warn 'whoops!';
    }
    
    try {
        die detailed_error( message => 'you got me' );
    }
    catch ($e) {
        die encode_json( $e->to_hash )
          if $e isa DetailedError and defined $e->message;
        $e->throw if $e->does('Throwable');
        die $e;
    }

    The above also demon­strates a cou­ple of oth­er Throwable::SugarFactory fea­tures. First, you get a to_hash method that returns a hash ref­er­ence of all excep­tion data, suit­able for seri­al­iz­ing to JSON. Second, you get all of Throwable’s meth­ods, includ­ing throw for re-​throwing exceptions. 

    So where does this leave last week’s FOAAS.com mod­uli­no client demon­stra­tion of object mock­ing tests? With a lit­tle bit of rewrit­ing to define and then use our sweet­er excep­tion library, it looks like this. You can review for a descrip­tion of the rest of its workings.

    #!/usr/bin/env perl
    
    package Local::CallFOAAS::Exceptions;
    use Throwable::SugarFactory;
    
    BEGIN {
        exception NoMethodError =>
          'no matching WebService::FOAAS method' =>
          ( has => [ method => ( is => 'ro' ) ] );
        exception ServiceError =>
          'error from WebService::FOAAS' =>
          ( has => [ message => ( is => 'ro' ) ] );
    }
    
    package Local::CallFOAAS;  # this is a modulino
    use Test2::V0;             # enables strict, warnings, utf8
    
    # declare all the new stuff we're using
    use feature qw(say state);
    use experimental qw(isa postderef signatures);
    use Feature::Compat::Try;
    use Syntax::Construct qw(non-destructive-substitution);
    
    use WebService::FOAAS ();
    use Package::Stash;
    BEGIN { Local::CallFOAAS::Exceptions->import() }
    
    my $foaas = Package::Stash->new('WebService::FOAAS');
    
    my $run_as =
        !!$ENV{CPANTEST}       ? 'test'
      : !defined scalar caller ? 'run'
      :                          undef;
    __PACKAGE__->$run_as(@ARGV) if defined $run_as;
    
    sub run ( $class, @args ) {
        try { say $class->call_method(@args) }
        catch ($e) {
            die 'No method ', $e->method, "\n"
              if $e isa NoMethodError;
            die 'Service error: ', $e->message, "\n"
              if $e isa ServiceError;
            die "$e\n";
        }
        return;
    }
    
    # Utilities
    
    sub methods ($) {
        state @methods = sort map s/^foaas_(.+)/$1/r,
          grep /^foaas_/, $foaas->list_all_symbols('CODE');
        return @methods;
    }
    
    sub call_method ( $class, $method = '', @args ) {
        state %methods = map { $_ => 1 } $class->methods();
        die no_method_error( method => $method )
          unless $methods{$method};
        return do {
            try { $foaas->get_symbol("&$method")->(@args) }
            catch ($e) { die service_error( message => $e ) }
        };
    }
    
    # Testing
    
    sub test ( $class, @ ) {
        state $stash = Package::Stash->new($class);
        state @tests = sort grep /^_test_/,
          $stash->list_all_symbols('CODE');
    
        for my $test (@tests) {
            subtest $test => sub {
                try { $class->$test() }
                catch ($e) { diag $e }
            };
        }
        done_testing();
        return;
    }
    
    sub _test_can ($class) {
        state @subs = qw(run call_method methods test);
        can_ok $class, \@subs, "can do: @subs";
        return;
    }
    
    sub _test_methods ($class) {
        my $mock = mock 'WebService::FOAAS' => ( track => 1 );
    
        for my $method ( $class->methods() ) {
            $mock->override( $method => 1 );
    
            ok lives { $class->call_method($method) },
              "$method lives";
            ok scalar $mock->sub_tracking->{$method}->@*,
              "$method called";
        }
        return;
    }
    
    sub _test_service_failure ($class) {
        my $mock = mock 'WebService::FOAAS';
    
        for my $method ( $class->methods() ) {
            $mock->override( $method => sub { die 'mocked' } );
    
            my $exception =
              dies { $class->call_method($method) };
            isa_ok $exception, [ServiceError],
              "$method throws ServiceError on failure";
            like $exception->message, qr/^mocked/,
              "correct error in $method exception";
        }
        return;
    }
    
    1;

    [Updated, thanks to Dan Book, Karen Etheridge, and Bob Kleemann] The only goofy bit above is the need to put the exception calls in a BEGIN block and then explic­it­ly call BEGIN { Local::CallFOAAS::Exceptions->import() }. Since the two pack­ages are in the same file, I can’t do a use state­ment since the implied require would look for a cor­re­spond­ing file or entry in %INC. (You can get around this by mess­ing with %INC direct­ly or through a mod­ule like me::inlined that does that mess­ing for you, but for a single-​purpose mod­uli­no like this it’s fine.)


  • Vicious (test) mockery of a Perl modulino

    Vicious (test) mockery of a Perl modulino

    Over the past two years, I’ve got­ten back into play­ing Dungeons & Dragons, the famous table­top fan­ta­sy role-​playing game. As a soft­ware devel­op­er and musi­cian, one of my favorite char­ac­ter class­es to play is the bard, a mag­i­cal and inspir­ing per­former or word­smith. The list of basic bardic spells includes Vicious Mockery, enchant­i­ng ver­bal barbs that have the pow­er to psy­chi­cal­ly dam­age and dis­ad­van­tage an oppo­nent even if they don’t under­stand the words. (Can you see why this is so appeal­ing to a coder?)

    Mocking has a role to play in soft­ware test­ing as well, in the form of mock objects that sim­u­late parts of a sys­tem that are too brit­tle, too slow, too com­pli­cat­ed, or oth­er­wise too finicky to use in real­i­ty. They enable dis­crete unit test­ing with­out rely­ing on depen­den­cies exter­nal to the code being test­ed. Mocks are great for data­bas­es, web ser­vices, or oth­er net­work resources where the goal is to test what you wrote, not what’s out in ​“the cloud” somewhere.

    Speaking of web ser­vices and mock­ing, one of my favorites is the long-​running FOAAS (link has lan­guage not safe for work), a sur­pris­ing­ly expan­sive RESTful insult ser­vice. There’s a cor­re­spond­ing Perl client API, of course, but what I was miss­ing was a handy Perl script to call that API from the ter­mi­nal com­mand line. So I wrote the fol­low­ing over Thanksgiving break, try­ing to keep it sim­ple while also show­ing the basics of mock­ing such an API. It also demon­strates some new­er Perl syn­tax and test­ing tech­niques as well as bri­an d foy​’s mod­uli­no con­cept from Mastering Perl (sec­ond edi­tion, 2014) that mar­ries script and mod­ule into a self-​contained exe­cutable library.

    #!/usr/bin/env perl
    
    package Local::CallFOAAS;  # this is a modulino
    use Test2::V0;             # enables strict, warnings, utf8
    
    # declare all the new stuff we're using
    use feature qw(say state);
    use experimental qw(isa postderef signatures);
    use Feature::Compat::Try;
    use Syntax::Construct qw(non-destructive-substitution);
    
    use WebService::FOAAS ();
    use Package::Stash;
    use Exception::Class (
        NoMethodException => {
            alias  => 'throw_no_method',
            fields => 'method',
        },
        ServiceException => { alias => 'throw_service' },
    );
    
    my $foaas = Package::Stash->new('WebService::FOAAS');
    
    my $run_as =
        !!$ENV{CPANTEST}       ? 'test'
      : !defined scalar caller ? 'run'
      :                          undef;
    __PACKAGE__->$run_as(@ARGV) if defined $run_as;
    
    sub run ( $class, @args ) {
        try { say $class->call_method(@args) }
        catch ($e) {
            die 'No method ', $e->method, "\n"
              if $e isa NoMethodException;
            die 'Service error: ', $e->error, "\n"
              if $e isa ServiceException;
            die "$e\n";
        }
        return;
    }
    
    # Utilities
    
    sub methods ($) {
        state @methods = sort map s/^foaas_(.+)/$1/r,
          grep /^foaas_/, $foaas->list_all_symbols('CODE');
        return @methods;
    }
    
    sub call_method ( $class, $method = '', @args ) {
        state %methods = map { $_ => 1 } $class->methods();
        throw_no_method( method => $method )
          unless $methods{$method};
        return do {
            try { $foaas->get_symbol("&$method")->(@args) }
            catch ($e) { throw_service( error => $e ) }
        };
    }
    
    # Testing
    
    sub test ( $class, @ ) {
        state $stash = Package::Stash->new($class);
        state @tests = sort grep /^_test_/,
          $stash->list_all_symbols('CODE');
    
        for my $test (@tests) {
            subtest $test => sub {
                try { $class->$test() }
                catch ($e) { diag $e }
            };
        }
        done_testing();
        return;
    }
    
    sub _test_can ($class) {
        state @subs = qw(run call_method methods test);
        can_ok( $class, \@subs, "can do: @subs" );
        return;
    }
    
    sub _test_methods ($class) {
        my $mock = mock 'WebService::FOAAS' => ( track => 1 );
    
        for my $method ( $class->methods() ) {
            $mock->override( $method => 1 );
    
            ok lives { $class->call_method($method) },
              "$method lives";
            ok scalar $mock->sub_tracking->{$method}->@*,
              "$method called";
        }
        return;
    }
    
    sub _test_service_failure ($class) {
        my $mock = mock 'WebService::FOAAS';
    
        for my $method ( $class->methods() ) {
            $mock->override( $method => sub { die 'mocked' } );
    
            my $exception =
              dies { $class->call_method($method) };
            isa_ok $exception, ['ServiceException'],
              "$method throws ServiceException on failure";
            like $exception->error, qr/^mocked/,
              "correct error in $method exception";
        }
        return;
    }
    
    1;

    Let’s walk through the code above.

    Preliminaries

    First, there’s a gener­ic she­bang line to indi­cate that Unix and Linux sys­tems should use the perl exe­cutable found in the user’s PATH via the env com­mand. I declare a pack­age name (in the Local:: name­space) so as not to pol­lute the default main pack­age of oth­er scripts that might want to require this as a mod­ule. Then I use the Test2::V0 bun­dle from Test2::Suite since the embed­ded test­ing code uses many of its func­tions. This also has the side effect of enabling the strict, warn­ings, and utf8 prag­mas, so there’s no need to explic­it­ly use them here.

    (Why Test2 instead of Test::More and its deriv­a­tives and add-​ons? Both are main­tained by the same author, who rec­om­mends the for­mer. I’m see­ing more and more mod­ules using it, so I thought this would be a great oppor­tu­ni­ty to learn.)

    I then declare all the new-​ish Perl fea­tures I’d like to use that need to be explic­it­ly enabled so as not to sac­ri­fice back­ward com­pat­i­bil­i­ty with old­er ver­sions of Perl 5. As of this writ­ing, some of these fea­tures (the isa class instance oper­a­tor, named argu­ment sub­rou­tine sig­na­tures, and try/​catch excep­tion han­dling syn­tax) are con­sid­ered experimental, with the lat­ter enabled in old­er ver­sions of Perl via the Feature::Compat::Try mod­ule. The friend­lier post­fix deref­er­enc­ing syn­tax was main­lined in Perl ver­sion 5.24, but ver­sions 5.20 and 5.22 still need it exper­i­men­tal. Finally, I use Syntax::Construct to announce the /r flag for non-​destructive reg­u­lar expres­sion text sub­sti­tu­tions intro­duced in ver­sion 5.14.

    Next, I bring in the afore­men­tioned FOAAS Perl API with­out import­ing any of its func­tions, Package::Stash to make metapro­gram­ming eas­i­er, and a cou­ple of excep­tion class­es so that the com­mand line func­tion and oth­er con­sumers might bet­ter tell what caused a fail­ure. In prepa­ra­tion for the meth­ods below dynam­i­cal­ly dis­cov­er­ing what func­tions are pro­vid­ed by WebService::FOAAS, I gath­er up its sym­bol table (or stash) into the $foaas variable.

    The next block deter­mines how, if at all, I’m going to run the code as a script. If the CPANTEST envi­ron­ment vari­able is set, I’ll call the test class method sub, but if there’s no sub­rou­tine call­ing me I’ll exe­cute the run class method. Either will receive the com­mand line argu­ments from @ARGV. If nei­ther of these con­di­tions is true, do noth­ing; the rest of the code is method declarations.

    Modulino methods, metaprogramming, and exceptions

    The first of these is the run method. It’s a thin wrap­per around the call_method class method detailed below, either out­putting its result or dieing with an appro­pri­ate error depend­ing on the class of excep­tion thrown. Although I chose not to write tests for this out­put, future tests might call this method and catch these rethrown excep­tions to match against them. The mes­sages end with a \n new­line char­ac­ter so die knows not to append the cur­rent script line number.

    Next is a util­i­ty method called methods that uses Package::Stash’s list_all_symbols to retrieve the names of all named CODE blocks (i.e., subs) from WebService::FOAAS’s sym­bol table. Reading from right to left, these are then fil­tered with grep to only find those begin­ning in foaas_ and then trans­formed with map to remove that pre­fix. The list is then sorted and stored in a state vari­able and returned so it need not be ini­tial­ized again.

    (As an aside, although perlcritic stern­ly warns against it I’ve cho­sen the expres­sion forms of grep and map here over their block forms for sim­plic­i­ty’s sake. It’s OK to bend the rules if you have a good reason.)

    sub call_method is where the real action takes place. Its para­me­ters are the class that called it, the name of a FOAAS $method (default­ed to the emp­ty string), and an array of option­al argu­ments in @args. I build a hash or asso­cia­tive array from the ear­li­er methods method which I then use to see if the passed method name is one I know about. If not, I throw a NoMethodException using the throw_no_method alias func­tion cre­at­ed when I used Exception::Class at the begin­ning. Using a func­tion instead of NoMethodException->throw() means that it’s checked at com­pile time rather than run­time, catch­ing typos.

    I get the sub­rou­tine (denot­ed by a & sig­il) named by $method from the $foaas stash and pass it any fur­ther received argu­ments from @args. If that WebService::FOAAS sub­rou­tine throws an excep­tion it’ll be caught and re-​thrown as a ServiceException; oth­er­wise call_method returns the result. It’s up to the caller to deter­mine what, if any­thing, to do with that result or any thrown exceptions.

    Testing the modulino with mocks

    This is where I start using those Test2::Suite tools I men­tioned at the begin­ning. The test class method starts by build­ing a fil­tered list of all subs begin­ning with _test_ in the cur­rent class, much like methods did above with WebService::FOAAS. I then loop through that list of subs, run­ning each as a subtest con­tain­ing a class method with any excep­tions report­ed as diag­nos­tics.

    The rest of the mod­uli­no is sub­test meth­ods, start­ing with a sim­ple _test_can san­i­ty check for the pub­lic meth­ods in the class. Following that is _test_methods, which starts by mocking the WebService::FOAAS pack­age and telling Test2::Mock I want to track any added, over­rid­den, or set subs. I then loop through all the method names returned by the methods class method, overrideing each one to return a sim­ple true val­ue. I then test pass­ing those names to call_method and use the hash ref­er­ence returned by sub_tracking to check that the over­rid­den sub was called. This seems a lot sim­pler than the Test::Builder-based mock­ing libraries I’ve tried like Test::MockModule and Test::MockObject.

    _test_service_failure acts in much the same way, check­ing that call_method cor­rect­ly throws ServiceExceptions if the wrapped WebService::FOAAS func­tion dies. The main dif­fer­ence is that the mocked WebService::FOAAS subs are now over­rid­den with a code ref­er­ence (sub { die 'mocked' }), which call_method uses to pop­u­late the rethrown ServiceException​’s error field.

    Wrapping up

    With luck, this arti­cle has giv­en you some ideas, whether it’s in mak­ing scripts (per­haps lega­cy code) testable to improve them, or writ­ing bet­ter unit tests that mock depen­den­cies, or delv­ing a lit­tle into metapro­gram­ming so you can dynam­i­cal­ly sup­port and test new fea­tures of said depen­den­cies. I hope you haven’t come away too offend­ed, at least. Let me know in the com­ments what you think.

  • Video: ​“A Year of Being Wrong on the Internet”

    I’m busy this week host­ing my par­ents’ first vis­it to Houston, but I didn’t want to let this Tuesday go by with­out link­ing to my talk from last week’s Ephemeral Miniconf. Thanks so much to Thibault Duponchelle for orga­niz­ing such a ter­rif­ic event, to all the oth­er speak­ers for com­ing togeth­er to present, and to every­one who attend­ed for wel­com­ing me.

  • Multiple ways to inheritance in Perl

    Multiple ways to inheritance in Perl

    Inspired by my par­ents com­ing to vis­it at the end of the week, I thought I’d write about how Perl class­es can have ​“par­ents” as well, from which they inher­it meth­ods. Although it might seem on the sur­face as though there’s more than one way to do it, these tech­niques all share the same under­ly­ing mechanism.

    Where it all BEGINs: @ISA

    Perl class­es are just repur­posed packages, i.e., a name­space for vari­ables and sub­rou­tines. The two key dif­fer­ences are:

    If you want­ed to do every­thing by hand at the low­est lev­el, you could make a sub­class at com­pile time like this:

    package Local::MyChildClass;
    BEGIN { # don't do this:
        require Local::MyParentClass;
        push @ISA, 'Local::MyParentClass';
    }

    Don’t do that though, because we have…

    base and parent

    In 1997 Perl 5.004_04 intro­duced the base prag­ma (back when Perl used that kind of ver­sion­ing scheme; in these days of seman­tic ver­sion­ing we’d call it ver­sion 5.4.4). It does the above BEGIN block in a sin­gle line:

    use base 'Local::MyParentClass'; # don't do this unless you're also using fields

    You might see use base in old­er code espe­cial­ly if it’s also using the fields prag­ma. However, Perl devel­op­ers dis­cour­age both as the for­mer silences cer­tain mod­ule load­ing errors while the lat­ter is at odds with the object-​oriented pro­gram­ming prin­ci­ple of encap­su­la­tion.

    So use parent instead, which Perl has includ­ed since ver­sion 5.10.1 in 2009:

    use parent 'Local::MyParentClass';

    A cou­ple of years ago my Newfold Digital col­league David Oswald cre­at­ed a fork of par­ent called parent::versioned that sup­ports spec­i­fy­ing the low­est ver­sion for super­class­es. You call it like this:

    use parent::versioned ['Local::MyParentClass' => 1.23];

    Within an OO system

    There are dozens of object-​oriented pro­gram­ming sys­tems on CPAN that pro­vide syn­tac­tic sug­ar and extra fea­tures to Perl’s min­i­mal but flex­i­ble basics. Two of the more pop­u­lar ones, Moose and Moo, offer an extends key­word that you should use instead of use parent so that your sub­class­es may take advan­tage of their features:

    package Local::MyChildClass;
    use Moo;
    extends 'Local::MyParentClass';

    Moose can also spec­i­fy a required super­class version:

    package Local::MyChildClass;
    use Moose;
    extends 'Local::MyParentClass' => {-version => 1.23};

    Also, use the MooseX::NonMoose mod­ule when extend­ing non-​Moose class­es, again so you get Moose fea­tures even though your meth­ods are com­ing from some­where else:

    package Local::MyMooseClass;
    use Moose;
    use MooseX::NonMoose;
    extends 'Local::MyPlainParentClass';

    The exper­i­men­tal Object::Pad mod­ule spec­i­fies a sin­gle super­class while defin­ing the class name with an option­al ver­sion. Per the author’s sug­gest­ed file lay­out, includ­ing a required min­i­mum ver­sion, it would look like:

    use Object::Pad 0.41;
    package Local::MyChildClass;
    class Local::MyChildClass isa Local::MyParentClass 1.23;

    Object::Pad and Corinna, its inspi­ra­tion, are works in progress so this syn­tax isn’t set in stone. The latter’s design­er Curtis ​“Ovid” Poe blogged ear­li­er this week about con­sid­er­ing a more self-​consistent syntax.

    Multiple inheritance vs. roles

    To quote the Perl doc­u­men­ta­tion, ​“mul­ti­ple inher­i­tance often indi­cates a design prob­lem, but Perl always gives you enough rope to hang your­self with if you ask for it.” All the tech­niques described above except for Object::Pad sup­port mul­ti­ple inher­i­tance by spec­i­fy­ing a list of super­class­es. For example:

    package Local::MyChildClass;
    use parent qw(Local::MyParentClass1 Local::MyParentClass2);

    If you’re using roles instead of or on top of super­class­es (I’ve seen both sit­u­a­tions) and your OO sys­tem doesn’t sup­port them on its own, you can use the Role::Tiny mod­ule, first by describ­ing your role in one pack­age and then con­sum­ing it in another:

    package Local::DoesSomething;
    use Role::Tiny;
    
    ...
    
    1;
    package Local::MyConsumer;
    use Role::Tiny::With;
    with 'Local::DoesSomething';
    
    ...
    
    1;

    Moo::Role uses Role::Tiny under the hood and Moo can com­pose roles from either. The syn­tax for both Moo and Moose is similar:

    package Local::DoesSomething;
    use Moo::Role; # or "use Moose::Role;"
    
    ...
    
    1;
    package Local::MyConsumer;
    use Moo; # or "use Moose;"
    with 'Local::DoesSomething';
    
    ...
    
    1;

    Object::Pad spec­i­fies roles with the role key­word, and both class­es and roles use does to con­sume them:

    use Object::Pad 0.56;
    package Local::DoesSomething;
    role Local::DoesSomething does Local::DoesSomethingElse;
    
    ...
    
    1;
    use Object::Pad 0.56;
    package Local::MyConsumer;
    class Local::MyConsumer does Local::DoesSomething;
    
    ...
    
    1;

    The pre­vi­ous caveat about pos­si­ble changes to this syn­tax applies.

    Like parent, (sort of) like child

    Of course, the whole point of inher­i­tance or role con­sump­tion is so your child or con­sumer class can reuse func­tions and meth­ods. Each of the tech­niques above has its ways of over­rid­ing that code, from the Perl built-​in SUPER pseudo-​class to Moose’s override and super key­words, to Moose’s and Moo’s method mod­i­fiers. (You can use the lat­ter out­side of Moo since it’s pro­vid­ed by Class::Method::Modifiers.)

    I’ve writ­ten about choos­ing between over­rid­ing and mod­i­fy­ing meth­ods before, and when it comes to Moose and Moo code I’m now on the side of using the around method mod­i­fi­er if a method needs to call an inher­it­ed or con­sumed method of the same name. Object::Pad doesn’t have method mod­i­fiers (yet), so classes that use it will have to sat­is­fy them­selves with SUPER in their methods with an :override attribute that will throw an error if a par­ent doesn’t also pro­vide the same method.

    The Parent Wrap

    In the end, your choice of Perl OO sys­tem will deter­mine how (or whether) you han­dle inher­i­tance and may even be a decid­ing fac­tor. Which would you choose? And more impor­tant­ly, have I made my par­ents proud with this post?

  • This week: The ePhEmeRaL miniconf

    This week: The ePhEmeRaL miniconf

    After a lot of pro­cras­ti­na­tion, I’ve decid­ed my talk for this week’s ePhEmeRaL mini­conf will be ​“Cunningham’s Law: A Year of Being Wrong on the Internet, or «prêch­er le faux pour savoir le vrai.»”

    The event starts at 8:00 AM CST on Thursday, November 18; you can find out more about it includ­ing the full sched­ule and a time zone con­vert­er here.