A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Jump to

Quick reference

What good Perl looks like

This is a selection (not an exhaustive list) of points which make Perl code a joy to maintain:

QUALITY
    * Named parameters to subroutines, passed as a hashref. Some cases of subroutines taking only one or two positional parameters may be acceptable, if it's obvious what they should be.
    * Parameters to subroutines are validated (e.g. Params::Validate, MooseX::Params::Validate, Type::Tiny with Moo
    * use strict; use warnings; # or equivalent (e.g. Moose or NAP::policy) for every file. A test to ensure this, e.g. Perl::Critic's RequireUseStrict and RequireUseWarnings.
    * Does not use the Switch module, the bugs in that module are extremely dangerous and even affect code which doesn't appear to use switch at all.
    * Well factored - write several subroutines or subclasses with meaningful names and avoid large "if/then" blocks.
    * Semantic classes, not utility classes
    * Modules have @EXPORT_OK (instead of @EXPORT), so imported methods have to be declared whenever used, and it's easy to trace where they came from
    * Variable names are full words with underscores separating words, no abbreviations just "to save typing"
    * No magic numbers or magic strings, use constants with comments explaining them. Even better, encapsulate in a method so constants don't have to be defined everywhere.
    * Do not re-use variables, i.e. don't use them for different purposes in different parts of the code. Use two variables instead.
    * Code written in the language of the problem domain (e.g. $album->{artist}) and not the solution domain (e.g. $hash->{lookup_field}).
    * Never perform an eval without checking the error and re-throwing the exception if it's not recognised
    * Code written to be easily understandable by other developers. No cleverness or "magic" without detailed explanatory comments.
    * Logging via at least one abstraction layer so log output can be easily controlled. Ideally use Log::Any which implements the Observer pattern, so you don't have to pass a log object into your classes.

DOCUMENTATION
    * Comments to explain the intention of every distinct section of the code
    * At least a few words of POD for _all_ classes and methods explaining the reason for existence, and what it represents in the real world
    * POD for functional tests (not needed for unit tests)
    * Everything built with a developer in mind who has never seen the system before (there will be many of these in the software's future).

TESTS
    * Test suite can run anywhere (checkout dir, dev env, test env, etc.)
    * Test suite not brittle, tests pass when run in any order
    * Tests clearly separated into:
        * environment - if these fail, bail out
        * unit tests - only test one module, with dependencies mocked out
        * integration tests - tests involving multiple in-team systems
        * monitoring - "tests" of external systems - not really tests but a form of monitoring
    * Appropriate mix of unit and integration tests
    * Tests for POD, syntax, etc. even if with a blacklist

ARCHITECTURE
    * No logic in the templates, proper MVC separation
    * No logic in scripts, only in re-usable modules

FORMATTING
    * No mixed tabs and spaces
    * Indent with 4 spaces
    * Consistent indenting
    * No indenting for longer than about 50 lines. If that happens, break some of the logic out into a different subroutine.

The opinions above are my own.

A nod of the head to Damian Conway's "Perl Best Practices".