The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Moose::Cookbook::FAQ - Frequenty asked questions about Moose

FREQUENTLY ASKED QUESTIONS

Module Stability

Is Moose "production ready"?

Yes and No. Currently I have one web application in production using Moose, and at $work we are re-writing our core offering to use Moose. Several other people on #moose either have sites in production which use Moose, or are in the process of deploying sites which use Moose.

The biggest barrier to widespread use of Moose in production right now is speed of development and speed of execution.

Since development is still happening, regular upgrades are a fact of life. This can be hairy in production, so if this makes you quake with fear, you might want to wait a few months.

Then comes speed of execution. In some ways, Moose is actually pretty fast and makes great effort to stay out of your way when you don't want it there. However, certain parts of Moose are slow, such as compile time setup, introspection and object construction (only because it uses introspection). See "Is Moose slow?" below for a deeper discussion on the subject.

Is Moose's API stable?

Yes and No. The external API, the one 90% of users will interact with, is very stable and any changes will be 100% backwards compatible. The introspection API is mostly stable, I still reserve the right to tweak that if needed, but I will do my absolute best to maintain backwards comptability here as well.

Is Moose slow?

Again, this one is tricky, so Yes and No.

First let me say that nothing in life is free, and that some Moose features do cost more than others. It is also the policy of Moose to only charge you for the features you use, and to do our absolute best to not place any extra burdens on the execution of your code for features you are not using.

Next, I will point out again that we are still in the "early adopter" phase, so speed it not that important yet. We are actually optimizing for "theoretical correctness" first, and we will optimize for speed later. It has been our experience that taking this approach allows for greater optimization capacity.

And lastly, I want to reassure the speed junkies out there that we are working on it.

We have the immutable classes in Class::MOP, but which are not yet integrated with Moose. These allow you to "close" a class and then for many of it's more expensive methods to me memoized. Our tests indicated a performance comparable (and in some instances exceeding) that of hand-coded Perl.

We are also discussing and experimenting with Module::Compile, and the idea of compiling highly optimized .pmc files. And we have also mapped out some core methods as canidates for conversion to XS.

When will Moose be 1.0 ready?

I expect (barring unforseen circumstances) that Moose will be at 1.0 by the end of this year (2006). Which means that it will be completely stable and provide a number of optimization options to suit the need for speed.

Will I have addressed all your concerns by then? Will all the features you want be included? I don't know unless you tell me, so come over to #moose and we can talk.

Constructors

How do I write custom constructors with Moose?

Ideally, you should never write your own new method, and should use Moose's other features to handle your specific object construction needs. Here are a few scenarios, and the Moose way to solve them;

If you need to call initializtion code post instance construction, then use the BUILD method. This feature is taken directly from Perl 6. Every BUILD method in your inheritence chain is called (in the correct order) immediately after the instance is constructed. This allows you to ensure that all your superclasses are initialized properly as well. This is the best approach to take (when possible) because it makes subclassing your class much easier.

If you need to affect the constructor's parameters prior to the instance actually being constructed, you have a number of options.

First, there are coercions (See the Moose::Cookbook::Recipe5 for a complete example and explaination of coercions). With coercions it is possible to morph argument values into the correct expected types. This approach is the most flexible and robust, but does have a slightly higher learning curve.

Second, using an around method modifier on new can be an effective way to affect the contents of @_ prior to letting Moose deal with it. This carries with it the extra burden for your subclasses, in that they have to be sure to explicitly call your new and/or work around your new to get to the version from Moose::Object.

The last approach is to use the standard Perl technique of calling the SUPER::new within your own custom version of new. This of course brings with it all the issues of the around solution along with any issues SUPER:: might add as well.

In short, try to use BUILD and coercions, they are your best bets.

How do I make non-Moose constuctors work with Moose?

Moose provides it's own constructor, but it does it by making all Moose-based classes inherit from Moose::Object. When inheriting from a non-Moose class, the inheritence chain to Moose::Object is broken. The simplest way to fix this is to simply explicitly inherit from Moose::Object yourself. However, this does not always fix the issue of a constructor. Here is a basic example of how this can be worked around:

  package My::HTML::Template;
  use Moose;
  
  # explict inheritence 
  extends 'HTML::Template', 'Moose::Object';
  
  # explicit constructor
  sub new {
      my $class = shift;
      # call HTML::Template's constructor
      my $obj = $class->SUPER::new(@_);
      return $class->meta->new_object(
          # pass in the constructed object
          # using the special key __INSTANCE__
          __INSTANCE__ => $obj, @_
      );
  }

Of course this only works if both your Moose class, and the inherited non-Moose class use the same instance type (typically HASH refs).

Other techniques can be used as well, such as creating the object using Moose::Object::new, but calling the inherited non-Moose class's initializtion methods (if available).

It is also entirely possible to just rely on HASH autovivification to create the slot's needed for Moose based attributes. Although this does somewhat restrict use of construction time attribute features.

In short, there are several ways to go about this, it is best to evaluate each case based on the class you wish to extend, and the features you wish to employ. As always, both IRC and the mailing list are great ways to get help finding the best approach.

Accessors

How do I tell Moose to use get/set accessors?

The easiest way to accomplish this is to use the reader and writer attribute options. Here is some example code:

  has 'bar' => (
      isa    => 'Baz',
      reader => 'get_bar', 
      writer => 'set_bar',
  );

Moose will still take advantage of type constraints, triggers, etc. when creating these methods.

If you do not like this much typing, and wish it to be a default for your class. Please see Moose::Policy, and more specifically the Moose::Policy::FollowPBP. This will allow you to write this:

  has 'bar' => (
      isa => 'Baz',
      is  => 'rw',
  );

And have Moose create get_bar and set_bar instead of the usual bar.

NOTE: This cannot be set globally in Moose, as this would break other classes which are built with Moose.

How can I get Moose to inflate/deflate values in the accessor?

Well, the first question to ask is if you actually need both inflate and deflate.

If you only need to inflate, then I suggest using coercions. Here is some basic sample code for inflating a DateTime object.

  subtype 'DateTime'
      => as 'Object'
      => where { $_->isa('DateTime') };
      
  coerce 'DateTime'
      => from 'Str'
        => via { DateTime::Format::MySQL->parse_datetime($_) };
        
  has 'timestamp' => (is => 'rw', isa => 'DateTime', coerce => 1);

This creates a custom subtype for DateTime objects, then attaches a coercion to that subtype. The timestamp attribute is then told to expect a DateTime type, and to try and coerce it. When a Str type is given to the timestamp accessor, it will attempt to coerce the value into a DateTime object using the code in found in the via block.

For a more detailed and complete example of coercions, see the Moose::Cookbook::Recipe5.

If you need to deflate your attribute, the current best practice is to add an around modifier to your accessor. Here is some example code:

  # a timestamp which stores as 
  # seconds from the epoch
  has 'timestamp' => (is => 'rw', isa => 'Int');
  
  around 'timestamp' => sub {
      my $next = shift;
      my ($self, $timestamp) = @_;
      # assume we get a DateTime object ...
      $next->($self, $timestamp->epoch);
  };

It is also possible to do deflation using coercion, but this tends to get quite complex and require many subtypes. An example of this is outside the scope of this document, ask on #moose or send a mail to the list.

Still another option is to write a custom attribute metaclass, which is also outside the scope of this document, but I would be happy to explain it on #moose or the mailing list.

Method Modfiers

How can I affect the values in @_ using before?

You can't actually, before only runs before the main method, and it cannot easily affect the execution of it. What you want is an around method.

Can I use before to stop execution of a method?

Yes, but only if you throw an exception. If this is too drastic a measure then I suggest using around instead. The around method modifier is the only modifier which can actually stop the execution of the main method. Here is an example:

  around 'baz' => sub {
      my $next = shift;
      my ($self, %options) = @_;
      if ($options{bar} eq 'foo') {
          $next->($self, %options);
      }
      else {
          return 'bar';
      }
  };

By choosing not to call the $next method, you can stop the execution of the main method.

Type Constraints

How can I have a custom error message for a type constraint?

Use the message option when building the subtype. Like so:

  subtype 'NaturalLessThanTen' 
      => as 'Natural'
      => where { $_ < 10 }
      => message { "This number ($_) is not less than ten!" };

This will be called when a value fails to pass the NaturalLessThanTen constraint check.

AUTHOR

Stevan Little <stevan@iinteractive.com>

COPYRIGHT AND LICENSE

Copyright 2006 by Infinity Interactive, Inc.

http://www.iinteractive.com

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.