Published on

Object-Oriented... Perl

Did you know perl could be used for Object-Oriented Programming? Neither did I. Here's how to do it.

Authors

So I had to write a script to parse logfiles from named for statistical purposes on a DNS-based experiment we're running at work. I've been using Perl a lot lately because one of our larger clients has much of their legacy code written in it. One of the original engineers in their organization was pretty good with it (I never got to meet him, though), and I've learned some neat tricks from maintaining and extending it. The string parsing and manipulation is just too good to pass up, so I decided to employ it for this project.

There was just one problem with all the perl code I'd seen so far. It was all procedural. There were functions, but no encapsulation, and lotsa side effects. I wanted to write mine a bit more cleanly than that.

First off, there are a few interesting aspects of OOP in Perl. Basically everything is still treated like a script, so at the end of every class file, you've got to return something:

Return Something... Or Else!!

package Account;

use strict;
use warnings;
...
...
...
1; # Absolutely necessary or you get a syntax error every time you import this file

Bless This Class, and the Self We Are About to Receive

Another interesting quirk was the 'bless' function. This was an entirely foreign concept to me, but basically the $self object is always the first argument of any class method:

##
# Loads data from the database
##
sub load {
  my $self = shift; # This right here is what I'm talking about

  # And now that it's defined, we can access our object attributes:
  my $uuid = $self->{uuid};

  ...
  ...
}

...Unless we're talking about the constructor function. In that bad-boy you've the first argument you un-shift is the 'class', and then you have to 'bless' the selfandself and class variables before you return:

##
# Constructor
##
sub new {
  my $class = shift;
  my $uuid  = shift;

  my $self = {
    uuid => (defined $uuid)        ? $uuid        : undef,
  };

  bless $self, $class; # This is the magic, right here.

  return $self;
}

Basically we're telling the interpreter that the selfreferenceisoftheclassself reference is of the class class, and all the attributes and methods associated with that class should be available to this reference. In perl, every object instantiation basically just a complicated hash.

You can dig a little deeper into the Perl way of instantiating objects in the perlobj documentation or the bless function documentation.

But just remember to bless your selfwithsomeself with some class when you construct an object, and unshift your $self at the start of every method. You'll be fine.

After that, using ojects in Perl doesn't look much different that any other language:

sub getAccountQueries {
  my $uuid = shift;
  my $account = Account->new($uuid);
  $account->load($uuid);
  return $account->Queries();
}

Advice

A few things really helped me out learning to do this:

Keep the Perl docs handy

They might say funky things like "This function tells the thingy referenced by REF that it is now an object..." 1 but they are still your best bet. Sometimes it's just difficult thinking about things "The Perl way". Still not sure I'm there either...

Always have strict and warnings enabled

This is probably on just about every Perl coding blog somewhere, but that's because it's great fookin' advice. It's way easier to debug a clean, well-written classfile than some sloppy POS that's barfing all over itself. Take the time to clean up all the little things, and the real demons will be easier to battle.

Reach Out to Somebody

This is probably the thing that I'm least likely to do, admitting weakness and taking help from others is something I'm working on in my life, but I want to put the offer of help out there for you.

If you need a hand getting your Perl code to work in an Object-Oriented fashion and keep crashing out with weird errors, shoot me an email and I'll help guide you through it. nathandcornell -at- gmail -dot- com.

Footnotes

  1. Actual excerpt from the perlobj documentation