Introduction: The current state of play
Perl has ​“very minÂiÂmal” supÂport for object-​oriented (OO) proÂgramÂming out of the box by its own admisÂsion. It’s class-​based but classÂes are just packÂages used difÂferÂentÂly. Objects are just data strucÂtures blessed into a class, methÂods are just subÂrouÂtines whose first arguÂment is an object or class name, and attributes/​properties are often just the key-​value pair of a hash stored in the object. (This last is a feaÂture shared with JavaScript, whose prototype-​based objects are just colÂlecÂtions of key-​value pairs with the keys addressed as propÂerÂties.) You’ve got polyÂmorÂphism, inherÂiÂtance, and it’s up to you to enforce encapÂsuÂlaÂtion.
This can take a lot of work to use effecÂtiveÂly. To help address that, sevÂerÂal sysÂtems have been develÂoped over the years to reduce boilÂerÂplate and proÂvide modÂern (or ​“postÂmodÂern”) OO feaÂtures that develÂopÂers from othÂer lanÂguages expect. My favorite for a while has been Moo: it’s got the feaÂtures I need 90% of the time like built-​in conÂstrucÂtors, roles (an alterÂnaÂtive to comÂpoÂsiÂtion through inherÂiÂtance), attribÂutÂes, type valÂiÂdaÂtion, and method modÂiÂfiers for enhanced polyÂmorÂphism. And if I need to dig around in the guts of classÂes, attribÂutÂes, and the like I can always upgrade to Moo’s big brothÂer Moose and its meta-​object proÂtoÂcol with minÂiÂmal effort.
Corinna, Object::Pad, and porting dbcritic
But there’s a new kid on the block. Curtis ​“Ovid” Poe has been spearÂheadÂing Corinna, an effort ​“to bring effecÂtive OO to the Perl core and leapfrog [emphaÂsis his] the capaÂbilÂiÂties of many OO lanÂguages today.” No CPAN modÂules, no chain of depenÂdenÂcies; just solÂid OO feaÂtures and synÂtax built-​in. And while Corinna is a ways off from shipÂping, Paul ​“LeoNerd” Evans (maybe I should get a cool nickÂname too?) has been impleÂmentÂing some of these ideas as new Perl keyÂword synÂtax in his Object::Pad module.
Both Ovid and LeoNerd have been askÂing develÂopÂers to try out Object::Pad, not just as a new toy, but to get feedÂback on what works and what needs to be added. So I thought I’d try portÂing an oldÂer small Moo-​based project named dbcritÂic to this new realÂiÂty. In the process, I learned some of the advanÂtages and disÂadÂvanÂtages of workÂing with Object::Pad. Hopefully, this can inform both it and Corinna’s evoÂluÂtion as well as othÂer curiÂous develÂopÂers’ evalÂuÂaÂtions. You can folÂlow my codÂing efforts in this GitHub branch.
First, the marÂquee result: the code for App::DBCritic (the class I startÂed with) is cleanÂer and shortÂer, with 33 lines shaved off so far. Mainly this is due to Object::Pad’s more conÂcise attribute synÂtax (called ​“slots” in its docÂuÂmenÂtaÂtion) and lack of explicÂit supÂport for Moo’s attribute coerÂcion. I only used the latÂter for one attribute in the Moo verÂsion and I’m not sure it worked parÂticÂuÂlarÂly well, so it wasÂn’t hard to jetÂtiÂson. But if your code supÂports coerÂcions extenÂsiveÂly, you’ll have to look into Object::Pad’s BUILD or ADJUST phase blocks for now.
Before, a Moo attribute with varÂiÂous options:
has schema => (
is => 'ro',
coerce => 1,
lazy => 1,
default => \&_build_schema,
coerce => \&_coerce_schema,
predicate => 1,
);
After, an Object::Pad slot. No coerÂcion and builder code is hanÂdled in a latÂer ADJUST block:
has $schema :reader :param = undef;
Speaking of ADJUST blocks, it took a litÂtle bit of insight from the #perl IRC chanÂnel to realÂize that they were the approÂpriÂate place for setÂting slot defaults that are comÂputÂed from othÂer slots. Previously I was using a maze of depenÂdenÂcies mixÂing Moo lazy attribÂutÂes and builder methÂods. Clarifying the main set of optionÂal conÂstrucÂtor arguÂments into a sinÂgle ADJUST block helped untanÂgle things, so this might be an indiÂcaÂtion that lazy attribÂutÂes are an antipatÂtern when tryÂing to write clean code. It’s also worth notÂing that Object::Pad ADJUST blocks run on object conÂstrucÂtion, whereÂas Moo lazy attribÂutÂes are only built when needÂed. This tends to matÂter for dataÂbase access.
The ADJUST block for the $schema slot:
ADJUST {
my @connect_info = ( $dsn, $username, $password );
if ($class_name and eval "require $class_name") {
$schema = $class_name->connect(@connect_info);
}
elsif ( not ( blessed($schema) and $schema->isa('DBIx::Class::Schema') ) ) {
local $SIG{__WARN__} = sub {
if ( $_[0] !~ / has no primary key at /ms ) {
print {*STDERR} $_[0];
}
};
$schema = App::DBCritic::Loader->connect(@connect_info);
}
croak 'No schema defined' if not $schema;
}
Object::Pad’s slots have one great advanÂtage over Moo and Moose attribÂutÂes: they directÂly supÂport Perl array and hash data strucÂtures, while the latÂter only supÂports scalars and refÂerÂences conÂtained in scalars. This means methÂods in your class can elimÂiÂnate a derefÂerÂencÂing step, again leadÂing to cleanÂer code. I used this specifÂiÂcalÂly in the @violations array and %elements hash slots and was very pleased with the results.
The @violations and %elements slots and their ADJUST blocks:
has %elements;
ADJUST {
%elements = (
Schema => [$schema],
ResultSource => [ map { $schema->source($_) } $schema->sources ],
ResultSet => [ map { $schema->resultset($_) } $schema->sources ],
);
}
has @violations;
ADJUST {
@violations = map { $self->_policy_loop( $_, $elements{$_} ) }
keys %elements;
}
method violations { wantarray ? @violations : \@violations }
Issues
I did have some develÂopÂment lifeÂcyÂcle issues with Object::Pad, but they’re mainÂly a result of its future-​facing synÂtax. I had to give up using perltidy and perlcritic in my build and test phasÂes, respecÂtiveÂly: perltidy doesÂn’t underÂstand slot attribÂutÂes like :reader and :param and will emit an error file (but code still comÂpiles), and sevÂerÂal of the perlcritic poliÂcies I use report probÂlems because its PPI parsÂer doesÂn’t recÂogÂnize the new synÂtax. I could add excepÂtions in the perlcriticrc file and litÂter my code with more ## no critic annoÂtaÂtions than it already had, but at this point, it was easÂiÂer to just disÂable it entirely.
Another thing I had to disÂable for now was my Dist::Zilla::Plugin::Test::UnusedVars-genÂerÂatÂed Test::Vars test for detectÂing unused variÂables, as it reports mulÂtiÂple failÂures for the hidÂden @(Object::Pad/slots) variÂable. It does have options for ignorÂing cerÂtain variÂables, though, so I can explore using those and posÂsiÂbly file a pull request to ignore that variÂable by default.
Conclusion: The future looks bright
Overall I’m satÂisÂfied with Object::Pad and by extenÂsion some of the synÂtax that Corinna will introÂduce. I’m going to try portÂing the rest of dbcritÂic and see if I can work around the issues I listÂed above withÂout givÂing up the kwaliÂtee improveÂment tools I’m used to. I’ll post my findÂings if I feel it merÂits anothÂer blog.
What do you think? Is this the future of object-​oriented Perl? Let me know in the comÂments below.

