I’m busy this week hosting my parents’ first visit to Houston, but I didn’t want to let this Tuesday go by without linking to my talk from last week’s Ephemeral Miniconf. Thanks so much to Thibault Duponchelle for organizing such a terrific event, to all the other speakers for coming together to present, and to everyone who attended for welcoming me.
Tag: Perl
-

Multiple ways to inheritance in Perl
Inspired by my parents coming to visit at the end of the week, I thought I’d write about how Perl classes can have “parents” as well, from which they inherit methods. Although it might seem on the surface as though there’s more than one way to do it, these techniques all share the same underlying mechanism.
Where it all
BEGINs:@ISAPerl classes are just repurposed
packages, i.e., a namespace for variables and subroutines. The two key differences are:- Subroutines may expect either an object referenceor the name of a class as their first argument.
- When you call a method that isn’t defined in a class, Perl will search through the special
@ISAarrayin the package for the name of a class that has that method. (You can change the search order with themro(method resolution order) pragma.)
If you wanted to do everything by hand at the lowest level, you could make a subclass at compile 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…
baseandparentIn 1997 Perl 5.004_04 introducedthe
basepragma (back when Perl used that kind of versioning scheme; in these days of semantic versioningwe’d call it version 5.4.4). It does the aboveBEGINblockin a single line:use base 'Local::MyParentClass'; # don't do this unless you're also using fieldsYou might see
use basein older code especially if it’s also using thefieldspragma. However, Perl developers discourageboth as the former silences certain module loading errorswhile the latter is at odds with the object-oriented programming principle of encapsulation.So
use parentinstead, which Perl has included since version 5.10.1in 2009:use parent 'Local::MyParentClass';A couple of years ago my Newfold Digitalcolleague David Oswaldcreated a fork of parent called parent::versionedthat supports specifying the lowest version for superclasses. You call it like this:
use parent::versioned ['Local::MyParentClass' => 1.23];Within an OO system
There are dozens of object-oriented programming systemson CPANthat provide syntactic sugarand extra features to Perl’s minimal but flexible basics. Two of the more popular ones, Mooseand Moo, offer an
extendskeyword that you should use instead ofuse parentso that your subclasses may take advantage of their features:package Local::MyChildClass; use Moo; extends 'Local::MyParentClass';Moose can also specify a required superclass version:
package Local::MyChildClass; use Moose; extends 'Local::MyParentClass' => {-version => 1.23};Also, use the MooseX::NonMoosemodule when extending non-Moose classes, again so you get Moose features even though your methods are coming from somewhere else:
package Local::MyMooseClass; use Moose; use MooseX::NonMoose; extends 'Local::MyPlainParentClass';The experimental Object::Padmodule specifies a single superclass while defining the class name with an optional version. Per the author’s suggested file layout, including a required minimum version, 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 inspiration, are works in progress so this syntax isn’t set in stone. The latter’s designer Curtis “Ovid” Poe blogged earlier this weekabout considering a more self-consistent syntax.
Multiple inheritancevs. roles
To quote the Perl documentation, “multiple inheritance often indicates a design problem, but Perl always gives you enough rope to hang yourself with if you ask for it.” All the techniques described above except for Object::Pad support multiple inheritance by specifying a list of superclasses. For example:
package Local::MyChildClass; use parent qw(Local::MyParentClass1 Local::MyParentClass2);If you’re using roles instead of or on top of superclasses (I’ve seen both situations) and your OO system doesn’t support them on its own, you can use the Role::Tiny module, first by describing your role in one package and then consuming 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 compose roles from either. The syntax 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 specifies roles with the
rolekeyword, and both classes and roles usedoesto consume 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 previous caveatabout possible changes to this syntax applies.
Like parent, (sort of) like child
Of course, the whole point of inheritance or role consumption is so your child or consumer class can reuse functions and methods. Each of the techniques above has its ways of overriding that code, from the Perl built-in
SUPERpseudo-classto Moose’soverrideandsuperkeywords, to Moose’sand Moo’smethod modifiers. (You can use the latter outside of Moo since it’s provided by Class::Method::Modifiers.)I’ve written about choosing between overridingand modifying methodsbefore, and when it comes to Moose and Moo code I’m now on the side of using the
aroundmethod modifierif a method needs to call an inherited or consumed method of the same name. Object::Pad doesn’t have method modifiers (yet), soclasses that use it will have to satisfy themselves withSUPERin theirmethods with an:overrideattribute that will throw an error if a parent doesn’t also provide the same method.The Parent Wrap
In the end, your choice of Perl OO systemwill determine how (or whether) you handle inheritance and may even be a deciding factor. Which would you choose? And more importantly, have I made my parents proud with this post?
-

This week: The ePhEmeRaL miniconf
After a lot of procrastination, I’ve decided my talk for this week’s ePhEmeRaL miniconfwill be “Cunningham’s Law: A Year of Being Wrong on the Internet, or «prêcher 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 including the full schedule and a time zone converter here.
-

Taming the Moose: Classing up Perl attributes
At my work, we extensively use the Mooseobject system to take care of what would ordinarily be very tedious boilerplate object-oriented Perl code. In one part of the codebase, we have a family of classesthat, among other things, map Perl methodsto the names of various calls in a third-party API within our larger organization. Those private Perl methods are in turn called from public methods provided by roles consumedby these classes so that other areas aren’t concerned with said API’s details.
Without going into too many specifics, I had a bunch of classes all with sections 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 values returned by these very simple methods might differ from class to class depending on the API call needed, and different classes might have a different mix of these methods depending on what roles they consume.
These methods had built up over time as developers had expanded the classes’ functionality, and this week it was my turn. I decided to apply the DRY (don’t repeat yourself) principleand create them from a simple 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 private read-only attributes!” 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 classes’
withstatements after these definitions so the roles they consume could “see” these runtime-defined attributes. But some of the methods used to read these are class methods (e.g., called asClassName->foo()rather than$object->foo()), and Moose attributes are only set after the construction of a class instance.Then I thought, “Hey, Moose has a MOP (meta-object protocol)! I’ll use that to generate these methods at runtime!”
my $meta = __PACKAGE__->meta; while (my ($method, $api_call) = each %METHOD_MAP) { $meta->add_method( $method => sub {$api_call} ); }The
add_methoddocumentation“strongly encourage[s]” you to pass a metamethod object rather than a code reference, 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 getting ugly. There had to be a better way, and fortunately there was in the form of Dave Rolsky’s MooseX::ClassAttributemodule. It simplifies 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 prevent setting the attribute in the constructor. Although they’re still Moose attributes, they act like class methods so long as the class consumes the roles that require them after the attribute definitions.Lastly, if we were using Mooas a lightweight alternative to Moose, I could have instead selected Toby Inkster’s MooX::ClassAttribute. Although it has some caveats, it’s pretty much the only alternative to our initial class method definitions as Moo lacks a meta-object protocol.
The lesson as always is to check CPAN(or the appropriate mix of your language’s software repository, forums like Stack Overflow, etc.) for anything that could conceivably have application outside of your particular circumstances. Twenty-five years into my career and I’m still leaping into code without first considering that someone smarter than me has already done the work.
-

Some thoughts on Perl template processing
Template processors and enginesare one of those pieces of software where it seems every developer wants to reinvent the wheel. Goodness knows I’ve done it earlier in my career. Tell me if this sounds familiar:
- You need to mix data into a document so you start with Perl’s string interpolation in
"double quotes"orsprintfformats. (Or maybe you investigateformats, but the less said about them the better.) - You realize your documents need to display things based on certain conditions, or you want to loop over a list or some other structure.
- You add these features via keyword parsing and escape characters, thinking it’s OK since this is just a small bespoke project.
- Before you know it you’ve invented another domain-specific language(DSL) and have to support it on top of the application you were trying to deliver in the first place.
Stop. Just stop. Decades of others who have walked this same path have already done this for you. Especially if you’re using a web framework like Dancer, Mojolicious, or Catalyst, where the template processor is either built-in or pluggable from CPAN. Even if you’re not developing a web application there are several general-purpose options of various capabilities like Template Toolkitand Template::Mustache. Investigate the alternatives and determine if they have the features, performance, and support you need. If you’re sure none of them truly meet your unique requirements, then maybe, maybeconsider rolling your own.
Whatever you decide, realize that as your application or website grows your investment in that selection will only deepen. Porting to a new template processor can be as challenging as porting any source code to a new programming language.
Unfortunately, there are about as many opinions on how to choose a template processor as there are template processors. For example, in 2013 Roland Koehler wrote a good Python-oriented article on several considerations and the different approaches available. Although he ended up developing his own (quelle surprise), he makes a good case that a template processor ought to at least provide various logic constructs as well as embedded expressions, if not a full programming language. Koehler specifically warns against the latter, though, as a template developer might change an application’s data model, to say nothing of the possibility of executing arbitrary destructive code.
I can appreciate this reasoning. I’ve successfully used Perl template processors like the aforementioned Template::Toolkit(which has both logic directivesand an optionalfacility for evaluating Perl code) and Text::Xslate(which supports several template syntaxesincluding a subset of Template::Toolkit’s, but without the ability to embed Perl code). We use the latter at work combined with Text::Xslate::Bridge::TT2Like’s emulation of various Template::Toolkit virtual methodsand it’s served us well.
But using those modules’ DSLs means more sophisticated tasks need extra time and effort finding the correct logic and expressions. This also assumes that their designer(s) have anticipated my needs either through built-in features or extensions. I’m already writing Perl; why should I switch to another, more limited language and environment provided I can remain disciplined enough to avoid issues like those described above by Koehler?
So for my personal projects, I favor template processors that use the full power of the Perl language like Mojolicious’ embedded Perlrenderer or the venerable Text::Templatefor non-web applications. It saves me time and I’ll likely want more than any DSL can provide. This may not apply to your situation, though, and I’m open to counter-arguments.
What’s your favorite template processor and why? Let me know in the comments.
- You need to mix data into a document so you start with Perl’s string interpolation in

