[ Perl tips index ]
[ Subscribe to Perl tips ]
The best way to do things in Perl keeps changing, just as the language
and the art of programming does. The code you wrote 10 years ago might
have been best practice back then, but chances are it doesn't look too
good by modern standards. Package filehandles, obscure special variables, and
select to control buffering are still supported by Perl, but
they're not things that should exist in modern code.
Perl::Critic reads your source code and tells you what you're doing
wrong. It uses Damian Conway's book Perl Best Practices as a
starting point, however it's extensible enough that you can change its
policies to enable, disable and customise what it complains about.
Whether you're writing new code, or maintaining old code,
can help you avoid bad practices and even teach you new techniques
you may not have known existed.
Chances are, for any serious code,
Perl::Critic is going to find a lot
of things to complain about. To make using it easier, there are five
levels of severity that you can pick from. These are:
Gentle turns on only the most important and worrisome errors that
Perl::Critic finds. The stern severity notes all the things that
Perl::Critic is pretty sure you will want to fix.
The later three levels of severity get more and more picky, down to complaining about your indentation and bracing style, whether you've commented out any code, and the modifiers used on your regular expressions.
It's recommended you start using
Perl::Critic with gentle feedback,
and proceed to the more picky levels in an incremental manner. You may
not agree with all of
Perl::Critic's feedback, but we'll see in a
moment how we can customise it to suit our needs.
The easiest way to use
Perl::Critic is to play with the web interface at
http://perlcritic.com/. Here you can upload your Perl file, select a
severity level and see what it complains about. This is a great way to
Perl::Critic but becomes impractical if you have lots of files
you want to critique or files containing sensitive information.
If you need more power than uploading your script to the web interface, you
Perl::Critic on from CPAN. Then you can use the
perlcritic. This is part of the
distribution and can be used as follows:
perlcritic --gentle myprogram.pl
We can also test all the files in a directory (this time using the stern severity level):
perlcritic --stern directory/
If you don't want to type full severity levels, you can use numerical shortcuts. The following are equivalent to the full lines above:
perlcritic -5 myprogram.pl perlcritic -4 directory/
perlcritic assumes a level of
gentle if no
severity level is set.
perlcritic command generates a colour-coded list of things in
your code that it has issue with. Example output (without the colour)
might look like:
Symbols are exported by default at line 40, column 1. Use '@EXPORT_OK' or '%EXPORT_TAGS' instead. (Severity: 4) Always unpack @_ first at line 60, column 1. See page 178 of PBP. (Severity: 4) Subroutine does not end with "return" at line 60, column 1. See page 197 of PBP. (Severity: 4) Expression form of "eval" at line 71, column 3. See page 161 of PBP.(Severity : 5) Stricture disabled at line 80, column 3. See page 429 of PBP. (Severity: 5) Expression form of "eval" at line 106, column 4. See page 161 of PBP. (Severity: 5) Mixed high and low-precedence booleans at line 158, column 6. See page 70 of PBP. (Severity: 4) Variable declared in conditional statement at line 223, column 2. Declare variables outside of the condition. (Severity: 5) "return" statement with explicit "undef" at line 227, column 2. See page 199 of PBP. (Severity: 5)
Many of the diagnostics
perlcritic provides by default are designed to only
take up one line, although in our output above we've reformatted them
to two lines for clarity. The brief format is to prevent the user
being overwhelmed by output when they already know what the errors
mean. However, when you're just starting, you'll want additional help
understanding what you've done wrong - especially if you don't have a copy
of Perl Best Practices to look up for the page references.
perlcritic comes with pre-defined verbosity levels
from 1 to 11, with 8 and above providing policy names which can be
looked up using
perldoc, and 10 and above providing full policy
perlcritic --stern --verbose 10 lib/MyModule.pm Symbols are exported by default at line 40, column 1. Modules::ProhibitAutomaticExportation (Severity: 4) When using Exporter, symbols placed in the `@EXPORT' variable are automatically exported into the caller's namespace. Although convenient, this practice is not polite, and may cause serious problems if the caller declares the same symbols. The best practice is to place your symbols in `@EXPORT_OK' or `%EXPORT_TAGS' and let the caller choose exactly which symbols to export. package Foo; use base qw(Exporter); our @EXPORT = qw(&foo &bar); # not ok our @EXPORT_OK = qw(&foo &bar); # ok our %EXPORT_TAGS = ( all => [ qw(&foo &bar) ] ); # ok
You can also configure your own format for these diagnostics.
There will be times when you disagree with the rules
For example, at Perl Training Australia we often write code which
constant pragma to allow perl to optimise code away at
Perl::Critic complains about this
on the more strict severity levels.
It's possible to exclude specific lines from criticism by using a
no critic comment with a double-hash:
use constant WINDOWS => ($^O eq 'MSWin32'); ## no critic
However it's also possible to tell
Perl::Critic at the time of
invocation to exclude this rule entirely:
perlcritic --gentle --verbose 10 --exclude ProhibitConstantPragma myprogram.pl
It's also possible to specifically include rules or groups of rules, even if they're more severe that your chosen severity level. In the following example, we enable all the code layout diagnostics:
perlcritic --gentle --verbose 10 --exclude ProhibitConstantPragma --include CodeLayout myprogram.pl
If you find yourself using too many options on the command-line, rather
than aliasing it, put the information into a profile. By default,
perlcritic will look for a .perlcriticrc (or _perlcriticrc for
Windows) file in your current directory first, and then in your home
directory. This allows developers to have per-project configuration,
as well as their own personal preferences.
If we added the following to our .perlcriticrc file:
severity = gentle verbose = 10 exclude = ProhibitConstantPragma include = CodeLayout
then we can condense the previous example back to:
As all good programmers write code with detailed test suites, you will be
glad to know that there's a very easy way to use
Perl::Critic in your
test suite. Just use the
Test::Perl::Critic module from the CPAN:
use Test::Perl::Critic; use Test::More tests => 1; critic_ok($file);
For CPAN distributions, the recommended usage is a little longer, to
ensure that end-users don't have to unnecessarily run what are
normally author-only tests. Consult the
documentation for more information.
Adding coding standards to legacy code can be challenging. Rather than
trying to make all of your code
Perl::Critic compliant at once, you may
find it useful to use
Test::Perl::Critic::Progressive. This is designed
to prevent further deterioration of your code, and does so by breaking on a
test run if there are more
Perl::Critic violations than the last
successful test. When run as part of your revision control commit tests,
this will ensure that the code in your repository can only get better.
use Test::Perl::Critic::Progressive qw( progressive_critic_ok ); progressive_critic_ok();
command line tool documentation.
Perl Training Australia book offers. Get discount books with your courses, or free books when you book by our early bird date.
[ Perl tips index ]
[ Subscribe to Perl tips ]
This Perl tip and associated text is copyright Perl Training Australia. You may freely distribute this text so long as it is distributed in full with this Copyright noticed attached.
If you have any questions please don't hesitate to contact us:
|Phone:||03 9354 6001 (Australia)|
|International:||+61 3 9354 6001|
Copyright Perl Training Australia. Contact us at email@example.com