Tag: Perl

  • 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…

    baseand parent

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

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

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

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

    use parent 'Local::MyParentClass';

    A cou­ple of years ago my Newfold Digitalcol­league David Oswaldcre­at­ed a fork of par­ent called parent::versionedthat 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­temson CPANthat pro­vide syn­tac­tic sug­arand extra fea­tures to Perl’s min­i­mal but flex­i­ble basics. Two of the more pop­u­lar ones, Mooseand Moo, offer an extendskey­word that you should use instead of use parentso 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::NonMoosemod­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::Padmod­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 weekabout con­sid­er­ing a more self-​consistent syntax.

    Multiple inheritancevs. 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::Roleuses 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 rolekey­word, and both class­es and roles use doesto 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 caveatabout 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 SUPERpseudo-​classto Moose’s overrideand superkey­words, to Moose’sand Moo’smethod 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­ingand mod­i­fy­ing meth­odsbefore, and when it comes to Moose and Moo code I’m now on the side of using the aroundmethod mod­i­fi­erif 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 SUPERin their methods with an :overrideattribute 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­temwill 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­confwill 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.

  • Taming the Moose: Classing up Perl attributes

    Taming the Moose: Classing up Perl attributes

    At my work, we exten­sive­ly use the Mooseobject sys­tem to take care of what would ordi­nar­i­ly be very tedious boil­er­plate object-​oriented Perl code. In one part of the code­base, we have a fam­i­ly of class­esthat, among oth­er things, map Perl meth­odsto the names of var­i­ous calls in a third-​party API with­in our larg­er orga­ni­za­tion. Those pri­vate Perl meth­ods are in turn called from pub­lic meth­ods pro­vid­ed by roles con­sumedby these class­es so that oth­er areas aren’t con­cerned with said API’s details.

    Without going into too many specifics, I had a bunch of class­es all with sec­tions that looked like this:

    sub _create_method    { return 'api_add'     }
    sub _retrieve_method  { return 'api_info'    }
    sub _search_method    { return 'api_list'    }
    sub _update_method    { return 'api_update'  }
    sub _cancel_method    { return 'api_remove'  }
    sub _suspend_method   { return 'api_disable' }
    sub _unsuspend_method { return 'api_restore' }
    
    ... # etc.

    The val­ues returned by these very sim­ple meth­ods might dif­fer from class to class depend­ing on the API call need­ed, and dif­fer­ent class­es might have a dif­fer­ent mix of these meth­ods depend­ing on what roles they consume.

    These meth­ods had built up over time as devel­op­ers had expand­ed the class­es’ func­tion­al­i­ty, and this week it was my turn. I decid­ed to apply the DRY (don’t repeat your­self) prin­ci­pleand cre­ate them from a sim­ple hash table like so:

    my %METHOD_MAP = (
      _create_method    => 'api_add',
      _retrieve_method  => 'api_info',
      _search_method    => 'api_list',
      _update_method    => 'api_update',
      _cancel_method    => 'api_remove',
      _suspend_method   => 'api_disable',
      _unsuspend_method => 'api_restore',
    );

    At first, I thought to myself, ​“These look like pri­vate read-​only attrib­ut­es!” So I wrote:

    use Moose;
    
    ...
    
    has $_ => (
      is       => 'ro',
      init_arg => undef,
      default  => $METHOD_MAP{$_},
    ) for keys %METHOD_MAP;

    Of course, I’d have to move the class­es’ withstate­ments after these def­i­n­i­tions so the roles they con­sume could ​“see” these runtime-​defined attrib­ut­es. But some of the meth­ods used to read these are class meth­ods (e.g., called as ClassName->foo()rather than $object->foo()), and Moose attrib­ut­es are only set after the con­struc­tion of a class instance.

    Then I thought, ​“Hey, Moose has a MOP (meta-​object pro­to­col)! I’ll use that to gen­er­ate these meth­ods at runtime!”

    my $meta = __PACKAGE__->meta;
    
    while (my ($method, $api_call) = each %METHOD_MAP) {
        $meta->add_method( $method => sub {$api_call} );
    }

    The add_methoddoc­u­men­ta­tion“strong­ly encourage[s]” you to pass a metamethod object rather than a code ref­er­ence, though, so that would look like:

    use Moose::Meta::Method;
    
    my $meta = __PACKAGE__->meta;
    
    while (my ($method, $api_call) = each %METHOD_MAP) {
        $meta->add_method( $method = Moose::Meta::Method->wrap(
          sub {$api_call}, __PACKAGE__, $meta,
        );
    }

    This was get­ting ugly. There had to be a bet­ter way, and for­tu­nate­ly there was in the form of Dave Rolsky​’s MooseX::ClassAttributemod­ule. It sim­pli­fies the above to:

    use MooseX::ClassAttribute;
    
    class_has $_ => (
      is      => 'ro',
      default => $METHOD_MAP{$_},
    ) for keys %METHOD_MAP;

    Note there’s no need for init_arg => undefto pre­vent set­ting the attribute in the con­struc­tor. Although they’re still Moose attrib­ut­es, they act like class meth­ods so long as the class con­sumes the roles that require them after the attribute definitions.

    Lastly, if we were using Mooas a light­weight alter­na­tive to Moose, I could have instead select­ed Toby Inkster​’s MooX::ClassAttribute. Although it has some caveats, it’s pret­ty much the only alter­na­tive to our ini­tial class method def­i­n­i­tions as Moo lacks a meta-​object pro­to­col.

    The les­son as always is to check CPAN(or the appro­pri­ate mix of your language’s soft­ware repos­i­to­ry, forums like Stack Overflow, etc.) for any­thing that could con­ceiv­ably have appli­ca­tion out­side of your par­tic­u­lar cir­cum­stances. Twenty-​five years into my career and I’m still leap­ing into code with­out first con­sid­er­ing that some­one smarter than me has already done the work.

  • Some thoughts on Perl template processing

    Some thoughts on Perl template processing

    Template proces­sors and enginesare one of those pieces of soft­ware where it seems every devel­op­er wants to rein­vent the wheel. Goodness knows I’ve done it ear­li­er in my career. Tell me if this sounds familiar:

    1. You need to mix data into a doc­u­ment so you start with Perl’s string inter­po­la­tion in "dou­ble quotes"or sprintffor­mats. (Or maybe you inves­ti­gate formats, but the less said about them the bet­ter.)
    2. You real­ize your doc­u­ments need to dis­play things based on cer­tain con­di­tions, or you want to loop over a list or some oth­er structure.
    3. You add these fea­tures via key­word pars­ing and escape char­ac­ters, think­ing it’s OK since this is just a small bespoke project.
    4. Before you know it you’ve invent­ed anoth­er domain-​specific lan­guage(DSL) and have to sup­port it on top of the appli­ca­tion you were try­ing to deliv­er in the first place.

    Stop. Just stop. Decades of oth­ers who have walked this same path have already done this for you. Especially if you’re using a web frame­work like Dancer, Mojolicious, or Catalyst, where the tem­plate proces­sor is either built-​in or plug­gable from CPAN. Even if you’re not devel­op­ing a web appli­ca­tion there are sev­er­al general-​purpose options of var­i­ous capa­bil­i­ties like Template Toolkitand Template::Mustache. Investigate the alter­na­tives and deter­mine if they have the fea­tures, per­for­mance, and sup­port you need. If you’re sure none of them tru­ly meet your unique require­ments, then maybe, maybecon­sid­er rolling your own.

    Whatever you decide, real­ize that as your appli­ca­tion or web­site grows your invest­ment in that selec­tion will only deep­en. Porting to a new tem­plate proces­sor can be as chal­leng­ing as port­ing any source code to a new pro­gram­ming language.

    Unfortunately, there are about as many opin­ions on how to choose a tem­plate proces­sor as there are tem­plate proces­sors. For exam­ple, in 2013 Roland Koehler wrote a good Python-​oriented arti­cle on sev­er­al con­sid­er­a­tions and the dif­fer­ent approach­es avail­able. Although he end­ed up devel­op­ing his own (quelle sur­prise), he makes a good case that a tem­plate proces­sor ought to at least pro­vide var­i­ous log­ic con­structs as well as embed­ded expres­sions, if not a full pro­gram­ming lan­guage. Koehler specif­i­cal­ly warns against the lat­ter, though, as a tem­plate devel­op­er might change an application’s data mod­el, to say noth­ing of the pos­si­bil­i­ty of exe­cut­ing arbi­trary destruc­tive code.

    I can appre­ci­ate this rea­son­ing. I’ve suc­cess­ful­ly used Perl tem­plate proces­sors like the afore­men­tioned Template::Toolkit(which has both log­ic direc­tivesand an option­alfacil­i­ty for eval­u­at­ing Perl code) and Text::Xslate(which sup­ports sev­er­al tem­plate syn­tax­esinclud­ing a sub­set of Template::Toolkit​’s, but with­out the abil­i­ty to embed Perl code). We use the lat­ter at work com­bined with Text::Xslate::Bridge::TT2Like​’s emu­la­tion of var­i­ous Template::Toolkit vir­tu­al meth­odsand it’s served us well.

    But using those mod­ules’ DSLs means more sophis­ti­cat­ed tasks need extra time and effort find­ing the cor­rect log­ic and expres­sions. This also assumes that their designer(s) have antic­i­pat­ed my needs either through built-​in fea­tures or exten­sions. I’m already writ­ing Perl; why should I switch to anoth­er, more lim­it­ed lan­guage and envi­ron­ment pro­vid­ed I can remain dis­ci­plined enough to avoid issues like those described above by Koehler?

    So for my per­son­al projects, I favor tem­plate proces­sors that use the full pow­er of the Perl lan­guage like Mojolicious’ embed­ded Perlren­der­er or the ven­er­a­ble Text::Templatefor non-​web appli­ca­tions. It saves me time and I’ll like­ly want more than any DSL can pro­vide. This may not apply to your sit­u­a­tion, though, and I’m open to counter-arguments.

    What’s your favorite tem­plate proces­sor and why? Let me know in the comments.