The Role of Critique

Over the last week I’ve been noodling with a minor improvement to Perl Critic to do with private methods and roles.

Sometimes I write roles that are essentially importers for utility methods – methods that are essentially imported into the class but don’t become part of the public interface.

Here’s an example of such a role, something that allows you to write $self->_select("SELECT * FROM foo WHERE foo_id",123) on any class that has a dbh attribute.

package SuperProject::Role::WithSelect;

use Moo::Role;

requires 'dbh';

sub _select {
  my $self  = shift;
  my $sql   = shift;
  my @binds = @_;
  return $self->dbh->selectall_arrayref( $sql, { Slice => {} }, @binds);


So what’s the problem (aside from the fact that I should have been using DBIx::Class for the databse stuff?)

bash$ perlcritic --verbose 10 SuperProject/Role/
Private subroutine/method '_select' declared but not used at line 7, column 1.
 Subroutines::ProhibitUnusedPrivateSubroutines (Severity: 3)
   By convention Perl authors (like authors in many other languages)
   indicate private methods and variables by inserting a leading underscore
   before the identifier. This policy catches such subroutines which are
   not used in the file which declares them.

   This module defines a 'use' of a subroutine as a subroutine or method
   call to it (other than from inside the subroutine itself), a reference
   to it (i.e. `my $foo = \&_foo'), a `goto' to it outside the subroutine
   itself (i.e. `goto &_foo'), or the use of the subroutine's name as an
   even-numbered argument to `use overload'.

Ooops. Perl::Critic is complaining about that private subroutine that’s not used in the role class. I guess I could change the method name from _select to select, but I don’t want select to become part of the public interface to the class that’s consuming this role.

Another option would be to use a ## no critic declaration. But that’s tedious, almost every role I write is going to be littered with extranious ## no critic delcarations and that’s often a sign that something is seriously wrong. What we need is some way to turn off Subroutines::ProhibitUnusedPrivateSubroutines for all our roles, but leave it on for everything else.

And that’s what I’ve been working on with help from Jeff Thalhammer over the last week. With the release of Perl::Critic that was released today you can tweak Subroutines::ProhibitUnusedPrivateSubroutines in your perlcriticrc to automatically turn itself off for a file if somewhere in that file you use a particular module, like, say, Moo::Role.

skip_when_using = Moo::Role

Critical Hit

Last night I braved Winter Storm Juno to venture out to Albany Perl Mongers’ technical meeting in East Greenbush.  Our special guest star Jeff Thalhammer had agreed to teleconference in from San Francisco to talk us through Perl::Critic.  This arrangement worked pretty well for us, with Jeff able to chat with the small number of us that had braved the storm and answer our questions. The only flaw with the setup was Jeff wasn’t able to try the pokemon cupcakes I’d baked. Bring on cupcake-over-ip technology is what I say.

I’ve been using Perl::Critic for many years now, and I wasn’t sure I would get much out of the technical meeting, but I was very wrong. Jeff was able to give several tips, answer questions, and point out a bunch of improvements that I was unaware of since I first started using Perl::Critic years ago.


The biggest win for me was learning about using the only option directly in a .perlcriticrc itself. This allows you to only run the rules specified in the critic file rather than any installed rules and is awesome for continuous integration test suites running off our in-house .perldcriticrc because if a new rule gets installed (due to an update our distribution dependencies) we don’t start automatically using it (and failing it) without some sort of review.


The various levels of verbose output that Perl::Critic’s verbose options now provides are very helpful. Bumping the output to level 8 (with --verbose=8) helpfully tells you the name of the policy that you’re violating, which is useful if you want to disable it with a ## no critic (...), or tweak the .perlcriticrc or simply read the documentation for the module so you can better understand what the policy is complaining about


My ancient personal .perlcriticrc file is getting a bit long in the tooth. Not only has my coding style changed over the many years as I’ve learned more about Perl, but Perl::Critic itself has improved introducing new policies both in the core distribution and on the CPAN itself. This is why I was excited to learn about the profile-proto which can spit out a fully-documented default .perlcriticrc

Let’s Go Shopping

Jeff took us on a brief shopping tour of the CPAN to show us some of the cool new policies that are available. Some standouts include:


Thanks to both Jeff for taking the time to talk to us, and to Patrick Cronin for once again organising the meeting, providing pizza and all the other thankless stuff he does to organise our meetings.

Getting Choosy

Today I released a new version of Mac::Choose which wraps the choose command line utility. Basically this lets you, from Perl, pop open a fuzzy match dialog like quicksilver, alfred, et al. This is probably best shown rather than explained:

use Mac::Choose qw(choose);
print choose qw(
) or die "User canceled selection";


The exciting thing about this release is that while previous versions required you to go to Tiny Robot Software’s website to download a copy of choose, this version of Mac::Choose ships with the choose binary and installs a copy alongside the Perl module.

Using File::ShareDir

In order to handle the intallation of the binary in a place where my code could once again find it I altered my distribution to use the File::ShareDir infrastructure. Essentially this infrastructure comes in two halves, an installer to install things in the shared dirctory and a module that can give you access to the files again.

In my Module::Intall powered Makefile.PL in order to use Module::Intall::Share I simply had to add the line:


This installs everything in the share directory of my distribution (which just contained one file, the choose binary) when you make install.

The changes to my module were also very simple:

use File::ShareDir qw(dist_file);
our $executable_path = dist_file("Mac-Choose","choose");


After those changes, everything worked flawlessly…apart from the test suite! The problem is that until the module is installed the files aren’t in the shared directory, and traditionally we test a module before we install them.

This isn’t insurmountable however, we just need to make some changes to our tests to quietly override File::ShareDir’s functionality with that from Test::File::ShareDir:

use File::Spec::Functions qw(:ALL);
use FindBin;
use Test::File::ShareDir (
    -root => catdir($FindBin::Bin, updir),
    -share => { -dist => { "Mac-Choose" => "share" } },

Posted in 1

Permalink 2 Comments

Internet Famous

Did I ever tell you guys the story of how I once made the front page of imgur with a Perl script?

As we’re all aware, imgur is a imaging sharing network traditionally dedicated to such topics as funny cat photos, internet memes and other recycled content often direct from its sister site reddit.  It’s internet fluff in the best possible way, and what I like to browse when I’m eating lunch and I need to disconnect my brain after a morning of coding.  While it’s got a minority of hardcore technical members, it’s not at all known for it’s technical content due to posts being promoted based mostly on up and down votes given by the masses;  As far as I know I’m the only person ever to get to the front page with actual code.

So how did I end up posting code of all things to imgur? Well, like most good Internet stories it started like this:

One lunchtime I saw a front page post featuring an image claiming that startling was the only nine letter word that you could remove one letter at a time and still get a valid word (i.e. starting, staring, string, sting, sing, sin, in, I.)  I was pretty sure that wasn’t right and there must be others. So I did what any Perl programmer does in this situation.  I wrote a Perl program to prove that wasn’t true:

And then for giggles, I posted the above image back to imgur.  Not exactly my best code, but I wrote it in about five minutes flat.  Five hours later it hit the front page and I had done my duty.


One of the topics that I had scheduled for the Perl Advent Calendar this year that didn’t finally make the cut was Regexp::Debugger (It might make it next year, but let’s all pretend I never made this post if that’s the case.)

I really wanted to write an article on Regexp::Debugger because it has such wow factor.  You just stick a line in the source code and bam instant visual debugger.  Suddenly I was finding out in minutes what was wrong with the regular expression that I’d spent half an hour figuring out writing numerous tests.  Sometimes there’s no substitute for getting in there and seeing what’s going on.

The problem with the article is that that’s pretty much all I could say about the module.  It’s almost too simple to use – there’s just nothing else to comment on.  Go.  Go use it.  You won’t regret it.  Hmm.

The other big problem is that it’s almost impossible to describe in words how to use the debugger.  It’s something that works best in a screencast or something similar and we’re not (yet) set up to include those kinds of things in the Perl Advent Calendar.  The article on ack had a couple of animated gifs, but I’m unsure if the one I prepared for Regexp::Debugger really conveys what’s going on without an audio track.  Still, for posterity, here’s the gif I prepared:

Regexp::Debugger demo gif

Posted in 1

Permalink 3 Comments

Perl Advent Calendar 2014 Stats

The Perl Advent Calendar is finally done and dusted for another year (apart from the typo corrections – there are always typo corrections.)  Which is lucky, since I committed the last submission just two days before Christmas Eve.

Let’s look at some statistics shall we?

The advent calendar is a team effort:

  • Total articles: 25 (24 articles + xmas day)
  • Articles written by people than me: 13
  • Total number of authors (including me): 13
  • Number of Pull Requests For Typos (so far): 8

It’s big:

  • Total number of lines: 5,318
  • Total number of words: 27,323
  • Total number of graphics: 7 (including two animated gifs)
  • Longest articleChristmas Eve’s Article (an epic 745 lines)
  • Perl examples: 159

It’s Perl:

  • References to Perl: 171 
  • References to Moo/Moose: 38
  • References to PHP: 2 (in the example about finding and deleting all the php code)

It’s fun

  • References to Santa: 38
  • References to Elves: 44

So, maybe now I’m not writing 2,575 lines (12,310 words) into the advent calendar (and copy editing and adding content to the other articles) I can finally get back on the Perl Ironman bandwagon in time for new year? Jarvis, load my blog editor…

Posted in 1

Permalink 1 Comment

Tell me more, tell me more

A new version of Test::DatabaseRow has just escaped onto the CPAN, with a minor new feature verbose data to make working out what went wrong in the database test even easier when the worst happens

In a nutshell this feature allows you to output in diagnostics all the results the database returned (not just listing the first thing that didn’t match, which is the default thing row_ok does in a similar way to Test::More’s is_deeply does.)

In other words instead of writing this:

       table => "contacts",
       where => [ cid => 123 ],
       tests => [ name => "trelane" ],
       store_rows => \@rows,
       description => "contact 123's name is trelane"
     ) or diag explain \@rows;

You can just write this:

       table => "contacts",
       where => [ cid => 123 ],
       tests => [ name => "trelane" ],
       verbose_data => 1,
       description => "contact 123's name is trelane"

Or even just write this:

       table => "contacts",
       where => [ cid => 123 ],
       tests => [ name => "trelane" ],
       description => "contact 123's name is trelane"

And turn on verbosity from the command line when you run the tests