Getting your antlers (A Moose article)

user-pic

Wiki Extras for this post

Perl's Object system has always been flexible, but it also has had a clear DIY (Do It Yourself) feel to it.  Many CPAN modules have been released to make the DIY portion a bit easier, but none have gone so far or indeed provided as much as Moose does. Moose is one of the most exciting developments in recent history.  It revolutionizes Perl's object system and provides a solid base for all object oriented development.  In today's article, we get an introduction to Moose and a view into what makes this module so important.

 

 

What is Moose?

Moose is a rather ingeniously designed Object Oriented framework put together originally by Stevan Little.  Moose is rapidly becoming the gold standard for Object Oriented Programming in Perl.

 

What does it do for you?

Moose takes care of all the rather unsavory set up often required to use Perl's OO features.   In addition to the basics, using Moose provides you with a straightforward interface to a large number of modern OO features such as roles (like interfaces or mixins in other languages) and object delegation.  The modules in the ever growing MooseX:: namespace provide even more advanced Object oriented functionality.

 

Why should I use it over something like Class::Accessor::Fast?

Moose is much much more feature rich than Class::Accessor::*.  Strictly speaking, Class::Accessor provides only the equivalent methods that has and new do in Moose. Although not a bad choice originally for setting up accessors and reducing redundant copy/pasting, Moose runs a much larger gamut than Class::Accessor and friends.

 

Why is it Moose important?

Perl's object oriented features have always been a double-edged sword.  On one hand, Perl's flexibility and introspection abilities were fantastic, on the other, they required a lot of do-it-yourself hacking and magic to really use effectively. Moose does away with all of that. 

Moose brings things up to par with more modern OO technologies, and helps you keep your code clean and simple. Moose provides a simple interface to defining attributes via the has() method.  Subclassing is simple using Moose's extends() method. 

One of the nicest things provided by Moose is the concept of Roles.  Where superclasses generally describe what a class is, Roles are used to describe what a class does.  In that respect, Moose Roles are similar to mixins or interfaces in other languages.

On the whole, Moose breathes new life into Perl OO programming and provides new and exciting features and functionality that were between difficult and impossible to achieve before Moose.

 

What do you do with Moose?

Like the rest of Perl, you can do anything with Moose.  Mainly however, Moose takes the headache out of object oriented programming in Perl.  With Moose you can create very concise and straightforward OO classes that are easy to extended and easy to maintain.

Some of the things Moose provides are:

  • Roles - allow you to create simple plugins for your classes or application.
  • Meta methods - allow you to add new functionality to Moose, without the need to do a bunch of source code diving, and the subsequent maintainance of those differernces.
  • Method modifiers - provide an unprecidented level of control over your objects and classes by giving you the ability to add to and adjust what happens before, after and during a method call.

 

How do you create an object with Moose?

Creating an object in Moose is very easy.  I think the best way to demonstrate this is to simply show an example:

package MyMoose;

use Moose;

has 'name' => (
      is  => 'rw',   # read/write attribute
      isa => 'Str',  # of the type String

  );
__PACKAGE__;

## somewhere else

use MyMoose;

my $obj = MyMoose->new;  # tada!

 

That's it. Then you have a real live Perl object.

 

Can you mix Moose and Non-Moose objects?

Of course.  One of the coolest things about Moose is that it has some fascinating new concepts (the sheer extension of Perl's OO system alone is wonderful), uses some  syntactic sugar, but it's completely compatible with "normal" Perl.

 

What neat things does Moose let you do?

One of the features I find most interesting about Moose are method modifiers.  As we touched on before, method modifiers allow you to change the behavior of a method by adding code to run before, after or around it.  You can also override it entirely (and do a few other things). 

The importance of this isn't really clear until you start using Roles.  Roles are not classes, instead they define behavior that a class uses.  You add a Role to a class (referred to as composing) and that class then provides the behavior that Role defines. What is REALLY cool, though, is when you use method modifiers along with Roles.... allowing the Role to actually change the behavior of the class it's composed into. 

This can be a little confusing, so let's explore an example.  Let's start with a Person class:

package Person;

use Moose;

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

sub sayname {
    my ($self) = @_;
    print $self->name . "\n";
}

__PACKAGE__;

When you create a Person object, calling the sayname method will print their name:

use Person;

my $user = Person->new();

$user->name('Bob');

$user->sayname();

As we expect, our output would be simply:

Bob

But, if we add an Addressable role:

package Addressable;

use Moose::Role;

requires 'sayname';

before 'sayname' => sub {
      my $self = shift;
      print "The honorable ";
};

__PACKAGE__;

And compose it into our Person class using 'with':

package Person;

use Moose;
with 'Addressable';

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

sub sayname {
    my ($self) = @_;
    print $self->name . "\n";
}

__PACKAGE__;

Now when we call $user->sayname() we get this instead:

The honorable Bob

What we have just done with the Addressable Role is created general functionality that can be added to any class without knowing in advance what those classes are or what they are going to look like.  

 

Are there any other interesting tips for using Moose in your own applications?

One of the cool things about Moose is it allows you to extend and change things without having to get too incredibly close to the metal.  Moose provides a meta method that allows you to do things like add additional traits to attributes. 

Let's say we want to add a "label" trait to each attribute.  We could go about it like this:

has url => (
    traits => [qw/Labeled/],
    is     => 'rw',
    isa    => 'Str',
    label  => "The site's URL",
);

My::Class->meta()->get_attribute('url')->label();

This is just one simple example.  Using metaclasses, you could literally create your own flavor of Moose.

I think every Mooser should take full advantage of the control over the objects that Moose provides.  These capabilities add a whole new level of flexibility and feature richness without a ton of effort.

 

For those interested in getting familiar with Moose, ultimately the best advice I can give you is to use it a lot. Create roles. Create classes. Go nuts!  Your time will not be wasted.  There are a lot of things under development using Moose, including Reaction, which is a UI MVC framework built on top of Catalyst; Kiokudb, which is an object oriented database management system written in Moose; and several workhorses that have been or are being rewritten using Moose, including Catalyst, DBIx::Class, and more.

Moose is a truly fantastic system.  This has been only a brief overview of Moose, so please, read the Moose documentation.  If you'd like to see how Moose makes perl OO that much better, check out this document:  Moose::Unsweetened - Moose idioms in plain old Perl 5 without the sugar


Other links:

The original Moose spec, good talks included

Introduction to Moose talk

Sartak's Frozen Perl 2009 Moose Talk

No TrackBacks

TrackBack URL: http://www.catalyzed.org/mt/mt-tb.fcgi/5

2 Comments

| Leave a comment

Nice and clear discussion about Moose with lots of handy links. However, gives me a 404. Otherwise excellent stuff.

Thanks for the catch. Curse the dangling )

Leave a comment

All comments are moderated. Spammers don't waste your time

Sponsored By


Ionzero: Rescue your dev project.
OpenID accepted here Learn more about OpenID

Following

Not following anyone

Note to spammers: all comments are moderated. Don't waste your time