Using Moose for Perl Objects

Even though Perl has fallen out of favor in recent years, it is still widely used among sysadmins for back-end automation.  

I was introduced to Perl early in my career while writing shell scripts for Linux and UNIX.  Perl offered the portability to write something once and deploy to multiple platforms.  

Perl is also a highly expressive language that excels with text processing and has native regular-expression syntax.   CPAN contains a vast collection of modules updated on a regular basis so you don't have to re-invent the wheel.   

One of the major pain points in Perl is its primitive object system.   In other languages, you can declare a class along with its methods and properties and be on your merry way.   But Perl requires you to do some additional work like blessing references, etc.

package Person;

sub new 
{
    my ($class, $args) = @_;
    my $self = 
    {
        firstname  => $args->{firstname},
        lastname => $args->{lastname},
        age  => $args->{age}
    };
    return bless $self, $class;
}

sub get_firstname
{
    my $self = shift;
    return $self->{firstname};
}

sub set_firstname
{
    my ($self, $firstname) = @_;
    $self->{firstname} = $firstname;
}
 
sub get_lastname 
{
    my $self = shift;
    return $self->{lastname};
}

sub set_lastname
{
    my ($self, $lastname) = @_;
    $self->{lastname} = $lastname;
}

sub get_age 
{
    my $self = shift;
    return $self->{age};
}

sub set_age
{
	my ($self, $age) = @_;
    $self->{age} = $age;
}

1;

This is where Moose makes life easier.  It's an object framework built on top of the native object system in Perl.   It includes features such as type checking, modifiers, and accessor methods.

With Moose, you can declare your object's attributes and some metadata about them.

package Person;

use Moose;
use namespace::autoclean;

# Attributes
has firstname =>       (is => 'rw', isa => 'Str', required => 1);
has lastname =>        (is => 'rw', isa => 'Str', required => 1);
has age =>             (is => 'rw', isa => 'Int', required => 1);
 
1;

Moose will handle some household tasks automatically:

  • Enable strict and warnings 
  • Create a constructor which validates that attributes are the correct type 
  • Create accessors and mutators for each attribute based on whether it is read-only (ro) or read-write (rw)
    • $object->firstname will return the value of firstname attribute
    • $object->firstname('Amir') will set the firstname attribute