Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Alias (5735)

Alias
  (email not shown publicly)
http://ali.as/

Journal of Alias (5735)

Wednesday November 04, 2009
08:26 PM

My favourite Perl Design Pattern

[ #39845 ]

Design Patterns have been an on-again, off-again fad for a while now. Statements like "Perl doesn't need Design Patterns, we have the CPAN" are common because most of the well-known patterns come from Java, where you can't do much of anything without 100 lines of structural boilerplate.

But a design pattern, at it's core, is a method for solving a particular problem that can't be done using a language's native structures and can't be (elegantly) solved as a module.

For example, Class::Adapter is my CPAN module for implementing the "Adapter" pattern from the gang of four book. An Adapter may be a pattern in Java, but it doesn't really rate being called such in Perl.

So I'd like to issue this blog challenge.

I want to see a post on your favourite Perl Design Pattern, some technique or trick that can't be done elegantly with Perl's native language resources, isn't so small that it might be classed as an idiom, and can't be easily packed up into a CPAN module.

I'll happily kick things off by presenting mine, the "Constant Global" (Haskell people might call it the Curried Global, which admit has quite a ring to it)

I use it all the time for debugging and tracing.

A Constant Global is a combination of global variable and a constant which is useful for debugging, assertions, and other situations where you want to add optional functionality to a very performance-sensitive module, so a feature can be enabled (or disabled) from outside that module.

The code for the canonical debugging version looks like this...

package My::Module;

use strict;
use vars qw{$DEBUG};
BEGIN {
        $DEBUG = !! $DEBUG;
}
use constant DEBUG => $DEBUG;

sub foo {
        print STDERR "Running foo" if DEBUG;
}

1;

This usage allows you to define variables in your top level script or test that will turn features on or off before you load the module, without incurring the penalty of all those if ( ... ) { ... } statements, since they will be compiled out.

Loading the module will look something like the following...

#!/usr/bin/perl

BEGIN {
        $My::Module::DEBUG = 1;
}

use My::Module;

Now, you only get one chance to choose if a feature will be enabled or disabled, so most use cases will either be debugging, and testing special cases, or features in modules which you would never really use twice, differently, in two different places in your code.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I think Perl has continually defied these attempts to package patterns because of it's meta programmability.

    Things we previously thought were not possible to package are now on CPAN as usable modules.

    Design patterns are thus getting more and more refined, and in time converge simply with the best practices for the software that helps to implement them.

    In the Java community metaprogramming is a much more difficult thing, so in order to produce extensible, reusable and clean code you need to have a much stric

  • <plug>

    I also use the $DEBUG/DEBUG idiom in pretty much every module I write.  Being rather lazy I wrote Badger::Debug to do the job for me.

    If you add the following to the top of your module:

        package Your::Module;
        use Badger::Debug default => 0;

    Then you'll get both the $DEBUG package variable and DEBUG compile time constant defined for you (in this case, set to 0). The end result is almost exactly as per your example.

    It also has a 'modules' option which you can use to
  • I have a semi-finished blog post sitting around that interprets much of the content of HOP as a catalog of design patterns for Perl. Chapter 4 [plover.com] is probably the best example. Most of that chapter is concerned with methods of implementing generator functions that enumerate large quantities of data, one element at a time.
  • See ifdef [cpan.org].

    In response to the criticism that it is a source filter, it filters for content within pod sections, which avoids almost all of the ambiguities that otherwise make parsing Perl so fun.