One for the Perl geeks

September 4, 2008

When writing a Perl module to wrap various CVS functionality, no matter how much of a good idea you might think it is, you really don’t want to add a method named “import”. You will get the weirdest error messages when you attempt to “use” the module and you will feel like hitting your head on the wall when it finally dawns on you as to what you have just done…


Moose versus Plain Perl

June 11, 2008

Some people have questioned the wisdom of basing future software projects on an Object-Oriented programming technology such as Moose (see previous posts for more details on Moose if you don’t know what it is) rather than doing it the good old-fashioned way in pure, unadulterated Perl.

There are always questions to be considered whenever a new piece of software is introduced into the mix. Is it widely used? It is well written? Does it produce comprehensible and maintainable code? Could someone who has not seen it before pick up where someone else left off in the standard “run over by a bus” scenario? Is it likely to scare the living daylights out of anyone who’s never seen it before? I believe that most of these have been answered on the web by the wider Perl community when it comes to Moose. It seems clear, to me, that something like this is the future of all Perl OO programming, particularly given that it is inspired by work being done for Perl6.

In an attempt to show that Moose produces code which is comprehensible, maintainable and in many ways a big improvement over the pure Perl approach. Here’s an example written both ways: Foo.pm and FooMoose.pm. One thing to notice straight away is that the Moose variant is 49 lines long compared to the 114 lines of the standard version. It allows all the standard handling of getting and setting values to be hidden away. The author can then get on with specifying exactly how the class attributes should be defined.

There’s no doubt that the Moose approach is different, it doesn’t look quite like normal Perl but it is a very perl-ish way of programming. Beyond needing to learn a few basic keywords I don’t think there is much in the code which will scare a Perl programmer who has not previously touched Moose. I’d hope that, if anything, Moose should make it easier for future developers to maintain and extend code written in this way.


Option Handling and Moose

May 28, 2008

Further to my previous post on option handling in Perl. There is a rather useful Moose extension named MooseX::Getopt which allows the building of an object directly from a set of command line options. The class attributes are directly translated into an option profile for Getopt::Long. Here’s a simple example class:

package LCFG::Foo;
use Moose;

with 'MooseX::Getopt';

has 'logname' => ( is => 'rw', isa => 'Str' );

has 'quiet' => ( is => 'rw', isa => 'Bool', default => 0 );

no Moose;
1;

In the script you can then just do:

#!/usr/bin/perl
use strict;
use warnings;

use LCFG::Foo;

my $foo = LCFG::Foo->new_with_options();

if ( !$foo->quiet) {
   print $foo->logname . "\n";
}

The script can then be called like:

my_script.pl --logname Changes --quiet

Option Handling in Perl

May 28, 2008

I’ve often used the Perl module Getopt::Long to handle options for scripts. This time I wanted something a bit more complex, I was aiming for something akin to the command-line interface to cvs. Basically, there are options which apply globally then a command and then command specific options. e.g.

lcfg-reltool --quiet --dir dice/lcfg-foo release --checkcommitted --genchangelog

Normally Getopt::Long expects to handle the whole argument list and will throw an error when it sees unknown options. I discovered that it is possible to configure it instead to pass-through any unknown options.

use Getopt::Long ();
Getopt::Long::Configure('pass_through');

my $dir = '.';
my $quiet = 0;
Getopt::Long::GetOptions( 'dir=s' => \$dir,
                                       'quiet' => \$quiet);

Getopt::Long::Configure('no_pass_through'); # revert to normal behaviour

All matched options will be removed from the @ARGV list and it is then possible to call Getopt::Long for a second time with a command-specific option profile.


perl module conflicts

February 1, 2008

In the process of packaging up the latest Moose and Class::MOP perl modules (and all the other dependencies) I discovered that the build process of some of them is asking for a version of Test::Simple which is more recent than that which is on SL5. Normally this would not be a problem, I would just grab the SRPM for that module, drop in the new source tar.gz and update version/changelog accordingly. There is a problem though with Test::Simple and some other modules as they are included as part of the RHEL/SL core perl package. Building my own package puts the perl modules into different locations but the manpages should go into the same directory /usr/share/man/man3 so we end up with file conflicts. I don’t see an easy way to resolve this issue and with the long lifetime of SL5 we are almost certainly going to be in this situation several times. At the moment this is not an important issue but what happens when we really need a newer version of a core module?

As an aside, it is interesting to contrast this with how Debian handle the problem so much better. The core versions of the modules are put into /usr/share/perl/5.8.8/ and /usr/lib/perl/5.8.8 (replace 5.8.8 with the current version of perl on any Debian system) and non-core modules go into /usr/share/perl5 and /usr/lib/perl5. They use the same manpage directory so file conflicts are avoided by the core versions using a .3perl file name suffix and non-core versions using the .3pm suffix. Why this is not the standard approach everywhere I cannot understand.