Perl Advent Calendar 2008-12-23

Resolution for next year: 1280x1024 or better

by Yanick Champoux

The problem with New Year resolutions is that they are always so… radical. It's always "I'll never do this again", or "from now on, I'll always do that." No wonder everyone breaks them even before Boxing Day sales are over: only saints can switch from indulgence to intransigence in the blink of an eye.

Programmers are no exception. Undoubtedly, on New Year's you'll vow to up your level of leetness, and perhaps make use of some of the widgets you've read about here. In the new year, your code is going to be leaner, meaner and better documented. It'll read like Tolstoy, and run like Seabiscuit. Oh yes, from now on, it's going to be best practices all the way. The straight and narrow is going to be your only path, and Perl::Critic is going to be your shepherd.

And so, high on your new resolution, you'll rush to add Test::Perl::Critic to our distribution's tests (perhaps even with some custom rules)… and that's when the bubble bursts ¤ Your new-found enthusiasm is suddenly crushed. Your hopes for a better life flattened. If you have a reasonably large and flabby suite of scripts or modules, chances are with even the gentlest Perll::Critic you'll wind up staring numbly at screens upon screens upon screens of remonstrances and warnings. Surely, you'll think, there is no way I can fix those thousands of violations. You'll sigh, remove the test, and resort to eggnog dregs to soothe the pain.

It needn't be that way. The key to success is to realize that gradual change is easier to achieve than a sudden overhaul. This is where Test::Perl::Critic::Progressive saves the day, and your self-esteem.

TPC::Progressive is meant to slowly ease a codebase into conformance. Instead of enforcing an "all-or-nothing" approach, its test will pass as long as the number of violations for the current run is less or equal than it was on previous runs. That way, it can be added to a distribution without automatically dooming it to a long-term stay in test failure purgatory.

But, of course, your resolution is not to only keep your modules at their current level of excellence, but rather to elevate them to perfection. No problem: with some extra setting TPC::Progressive can require that, to be successful, new test runs must knock out a minimum number of violations. Thus the unmovable mountain is reduced into a pile of small, manageable pebbles. A big pile of pebbles, mind you. But then, that's why it's called a New Year's resolution, and not a new week's resolution, isn't it?

   1 use strict;
   2 use warnings;
   3 use Test::More;
   4 use Data::Dumper;
   6 use Test::Perl::Critic::Progressive ':all';
   8 set_total_step_size(3);    # must remove 3 violations each run
  10 set_step_size_per_policy(  # must remove at least one of those too
  11     'ValuesAndExpressions::ProhibitNoisyQuotes' => 1,
  12 );
  14 progressive_critic_ok();
  16 # show summary of violations, beginning with the
  17 # worst offender
  19 my $file = get_history_file();
  21 my %violation = %{ ${ do $file }[-1] };    # get last run
  23 for (
  24     reverse sort { $violation{$a} <=> $violation{$b} }
  25     keys %violation
  26   ) {
  28     last unless $violation{$_};    # don't report policies with no violation
  30     diag sprintf "%3d %s\n", $violation{$_}, $_;
  32 }
View Source (POD)