471 lines
15 KiB
Plaintext
471 lines
15 KiB
Plaintext
# PODNAME: Moose::Manual::FAQ
|
|
# ABSTRACT: Frequently asked questions about Moose
|
|
|
|
__END__
|
|
|
|
=pod
|
|
|
|
=encoding UTF-8
|
|
|
|
=head1 NAME
|
|
|
|
Moose::Manual::FAQ - Frequently asked questions about Moose
|
|
|
|
=head1 VERSION
|
|
|
|
version 2.2207
|
|
|
|
=head1 FREQUENTLY ASKED QUESTIONS
|
|
|
|
=head2 Module Stability
|
|
|
|
=head3 Is Moose "production ready"?
|
|
|
|
Yes! Many sites with household names are using Moose to build
|
|
high-traffic services. Countless others are using Moose in production.
|
|
See L<http://moose.iinteractive.com/about.html#organizations> for
|
|
a partial list.
|
|
|
|
As of this writing, Moose is a dependency of several hundred CPAN
|
|
modules. L<https://metacpan.org/requires/module/Moose>
|
|
|
|
=head3 Is Moose's API stable?
|
|
|
|
Yes. The sugary API, the one 95% of users will interact with, is
|
|
B<very stable>. Any changes will be B<100% backwards compatible>.
|
|
|
|
The meta API is less set in stone. We reserve the right to tweak
|
|
parts of it to improve efficiency or consistency. This will not be
|
|
done lightly. We do perform deprecation cycles. We I<really>
|
|
do not like making ourselves look bad by breaking your code.
|
|
Submitting test cases is the best way to ensure that your code is not
|
|
inadvertently broken by refactoring.
|
|
|
|
=head3 I heard Moose is slow, is this true?
|
|
|
|
Again, this one is tricky, so Yes I<and> No.
|
|
|
|
Firstly, I<nothing> in life is free, and some Moose features do cost
|
|
more than others. It is also the policy of Moose to B<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. Of course using Moose itself does involve some overhead,
|
|
but it is mostly compile time. At this point we do have some options
|
|
available for getting the speed you need.
|
|
|
|
Currently we provide the option of making your classes immutable as a
|
|
means of boosting speed. This will mean a slightly larger compile time
|
|
cost, but the runtime speed increase (especially in object
|
|
construction) is pretty significant. This can be done with the
|
|
following code:
|
|
|
|
MyClass->meta->make_immutable();
|
|
|
|
=head2 Constructors
|
|
|
|
=head3 How do I write custom constructors with Moose?
|
|
|
|
Ideally, you should never write your own C<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 initialization code post instance construction,
|
|
then use the C<BUILD> method. This feature is taken directly from Perl
|
|
6. Every C<BUILD> method in your inheritance 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.
|
|
|
|
To change the parameter processing as a whole, you can use the
|
|
C<BUILDARGS> method. The default implementation accepts key/value
|
|
pairs or a hash reference. You can override it to take positional
|
|
args, or any other format
|
|
|
|
To change the handling of individual parameters, there are I<coercions> (See
|
|
the L<Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion> for a complete
|
|
example and explanation 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.
|
|
|
|
=head3 How do I make non-Moose constructors work with Moose?
|
|
|
|
Usually the correct approach to subclassing a non-Moose class is
|
|
delegation. Moose makes this easy using the C<handles> keyword,
|
|
coercions, and C<lazy_build>, so subclassing is often not the ideal
|
|
route.
|
|
|
|
That said, if you really need to inherit from a non-Moose class, see
|
|
L<Moose::Cookbook::Basics::DateTime_ExtendingNonMooseParent> for an example of how to do it,
|
|
or take a look at L<Moose::Manual::MooseX/"MooseX::NonMoose">.
|
|
|
|
=head2 Accessors
|
|
|
|
=head3 How do I tell Moose to use get/set accessors?
|
|
|
|
The easiest way to accomplish this is to use the C<reader> and
|
|
C<writer> attribute options:
|
|
|
|
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 classes, please see L<MooseX::FollowPBP>. This extension will
|
|
allow you to write:
|
|
|
|
has 'bar' => (
|
|
isa => 'Baz',
|
|
is => 'rw',
|
|
);
|
|
|
|
Moose will create separate C<get_bar> and C<set_bar> methods instead
|
|
of a single C<bar> method.
|
|
|
|
If you like C<bar> and C<set_bar>, see
|
|
L<MooseX::SemiAffordanceAccessor>.
|
|
|
|
NOTE: This B<cannot> be set globally in Moose, as that would break
|
|
other classes which are built with Moose. You can still save on typing
|
|
by defining a new C<MyApp::Moose> that exports Moose's sugar and then
|
|
turns on L<MooseX::FollowPBP>. See
|
|
L<Moose::Cookbook::Extending::Mooseish_MooseSugar>.
|
|
|
|
=head3 How can I inflate/deflate values in accessors?
|
|
|
|
Well, the first question to ask is if you actually need both inflate
|
|
and deflate.
|
|
|
|
If you only need to inflate, then we suggest using coercions. Here is
|
|
some basic sample code for inflating a L<DateTime> object:
|
|
|
|
class_type 'DateTime';
|
|
|
|
coerce 'DateTime'
|
|
=> from 'Str'
|
|
=> via { DateTime::Format::MySQL->parse_datetime($_) };
|
|
|
|
has 'timestamp' => (is => 'rw', isa => 'DateTime', coerce => 1);
|
|
|
|
This creates a custom type for L<DateTime> objects, then attaches
|
|
a coercion to that type. The C<timestamp> attribute is then told
|
|
to expect a C<DateTime> type, and to try to coerce it. When a C<Str>
|
|
type is given to the C<timestamp> accessor, it will attempt to
|
|
coerce the value into a C<DateTime> object using the code in found
|
|
in the C<via> block.
|
|
|
|
For a more comprehensive example of using coercions, see the
|
|
L<Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion>.
|
|
|
|
If you need to deflate your attribute's value, the current best
|
|
practice is to add an C<around> modifier to your accessor:
|
|
|
|
# a timestamp which stores as
|
|
# seconds from the epoch
|
|
has 'timestamp' => (is => 'rw', isa => 'Int');
|
|
|
|
around 'timestamp' => sub {
|
|
my $next = shift;
|
|
my $self = shift;
|
|
|
|
return $self->$next unless @_;
|
|
|
|
# assume we get a DateTime object ...
|
|
my $timestamp = shift;
|
|
return $self->$next( $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 we would be happy to
|
|
explain it on #moose or the mailing list.
|
|
|
|
=head2 Method Modifiers
|
|
|
|
=head3 How can I affect the values in C<@_> using C<before>?
|
|
|
|
You can't, actually: C<before> only runs before the main method, and
|
|
it cannot easily affect the method's execution.
|
|
|
|
You similarly can't use C<after> to affect the return value of a
|
|
method.
|
|
|
|
We limit C<before> and C<after> because this lets you write more
|
|
concise code. You do not have to worry about passing C<@_> to the
|
|
original method, or forwarding its return value (being careful to
|
|
preserve context).
|
|
|
|
The C<around> method modifier has neither of these limitations, but is
|
|
a little more verbose.
|
|
|
|
Alternatively, the L<MooseX::Mangle> extension provides the
|
|
C<mangle_args> function, which does allow you to affect C<@_>.
|
|
|
|
=head3 Can I use C<before> to stop execution of a method?
|
|
|
|
Yes, but only if you throw an exception. If this is too drastic a
|
|
measure then we suggest using C<around> instead. The C<around> method
|
|
modifier is the only modifier which can gracefully prevent execution
|
|
of the main method. Here is an example:
|
|
|
|
around 'baz' => sub {
|
|
my $next = shift;
|
|
my ($self, %options) = @_;
|
|
unless ($options->{bar} eq 'foo') {
|
|
return 'bar';
|
|
}
|
|
$self->$next(%options);
|
|
};
|
|
|
|
By choosing not to call the C<$next> method, you can stop the
|
|
execution of the main method.
|
|
|
|
Alternatively, the L<MooseX::Mangle> extension provides the
|
|
C<guard> function, which will conditionally prevent execution
|
|
of the original method.
|
|
|
|
=head3 Why can't I see return values in an C<after> modifier?
|
|
|
|
As with the C<before> modifier, the C<after> modifier is simply called
|
|
I<after> the main method. It is passed the original contents of C<@_>
|
|
and B<not> the return values of the main method.
|
|
|
|
Again, the arguments are too lengthy as to why this has to be. And as
|
|
with C<before> I recommend using an C<around> modifier instead. Here
|
|
is some sample code:
|
|
|
|
around 'foo' => sub {
|
|
my $next = shift;
|
|
my ($self, @args) = @_;
|
|
my @rv = $next->($self, @args);
|
|
# do something silly with the return values
|
|
return reverse @rv;
|
|
};
|
|
|
|
Alternatively, the L<MooseX::Mangle> extension provides the
|
|
C<mangle_return> function, which allows modifying the return values
|
|
of the original method.
|
|
|
|
=head2 Type Constraints
|
|
|
|
=head3 How can I provide a custom error message for a type constraint?
|
|
|
|
Use the C<message> option when building the subtype:
|
|
|
|
subtype 'NaturalLessThanTen'
|
|
=> as 'Natural'
|
|
=> where { $_ < 10 }
|
|
=> message { "This number ($_) is not less than ten!" };
|
|
|
|
This C<message> block will be called when a value fails to pass the
|
|
C<NaturalLessThanTen> constraint check.
|
|
|
|
=head3 Can I turn off type constraint checking?
|
|
|
|
There's no support for it in the core of Moose yet. This option may
|
|
come in a future release.
|
|
|
|
Meanwhile there's a L<MooseX
|
|
extension|MooseX::Attribute::TypeConstraint::CustomizeFatal> that
|
|
allows you to do this on a per-attribute basis, and if it doesn't do
|
|
what you it's easy to write one that fits your use case.
|
|
|
|
=head3 My coercions stopped working with recent Moose, why did you break it?
|
|
|
|
Moose 0.76 fixed a case where coercions were being applied even if the original
|
|
constraint passed. This has caused some edge cases to fail where people were
|
|
doing something like
|
|
|
|
subtype 'Address', as 'Str';
|
|
coerce 'Address', from 'Str', via { get_address($_) };
|
|
|
|
This is not what they intended, because the type constraint C<Address> is too
|
|
loose in this case. It is saying that all strings are Addresses, which is
|
|
obviously not the case. The solution is to provide a C<where> clause that
|
|
properly restricts the type constraint:
|
|
|
|
subtype 'Address', as 'Str', where { looks_like_address($_) };
|
|
|
|
This will allow the coercion to apply only to strings that fail to look like an
|
|
Address.
|
|
|
|
=head2 Roles
|
|
|
|
=head3 Why is BUILD not called for my composed roles?
|
|
|
|
C<BUILD> is never called in composed roles. The primary reason is that
|
|
roles are B<not> order sensitive. Roles are composed in such a way
|
|
that the order of composition does not matter (for information on the
|
|
deeper theory of this read the original traits papers here
|
|
L<http://www.iam.unibe.ch/~scg/Research/Traits/>).
|
|
|
|
Because roles are essentially unordered, it would be impossible to
|
|
determine the order in which to execute the C<BUILD> methods.
|
|
|
|
As for alternate solutions, there are a couple.
|
|
|
|
=over 4
|
|
|
|
=item *
|
|
|
|
Using a combination of lazy and default in your attributes to defer
|
|
initialization (see the Binary Tree example in the cookbook for a good example
|
|
of lazy/default usage
|
|
L<Moose::Cookbook::Basics::BinaryTree_AttributeFeatures>)
|
|
|
|
=item *
|
|
|
|
Use attribute triggers, which fire after an attribute is set, to
|
|
facilitate initialization. These are described in the L<Moose> docs,
|
|
and examples can be found in the test suite.
|
|
|
|
=back
|
|
|
|
In general, roles should not I<require> initialization; they should
|
|
either provide sane defaults or should be documented as needing
|
|
specific initialization. One such way to "document" this is to have a
|
|
separate attribute initializer which is required for the role. Here is
|
|
an example of how to do this:
|
|
|
|
package My::Role;
|
|
use Moose::Role;
|
|
|
|
has 'height' => (
|
|
is => 'rw',
|
|
isa => 'Int',
|
|
lazy => 1,
|
|
default => sub {
|
|
my $self = shift;
|
|
$self->init_height;
|
|
}
|
|
);
|
|
|
|
requires 'init_height';
|
|
|
|
In this example, the role will not compose successfully unless the
|
|
class provides a C<init_height> method.
|
|
|
|
If none of those solutions work, then it is possible that a role is
|
|
not the best tool for the job, and you really should be using
|
|
classes. Or, at the very least, you should reduce the amount of
|
|
functionality in your role so that it does not require initialization.
|
|
|
|
=head3 What are traits, and how are they different from roles?
|
|
|
|
In Moose, a trait is almost exactly the same thing as a role, except
|
|
that traits typically register themselves, which allows you to refer
|
|
to them by a short name ("Big" vs "MyApp::Role::Big").
|
|
|
|
In Moose-speak, a I<Role> is usually composed into a I<class> at
|
|
compile time, whereas a I<Trait> is usually composed into an instance
|
|
of a class at runtime to add or modify the behavior of B<just that
|
|
instance>.
|
|
|
|
Outside the context of Moose, traits and roles generally mean exactly
|
|
the same thing. The original paper called them traits, but Perl 6
|
|
will call them roles.
|
|
|
|
=head3 Can an attribute-generated method (e.g. an accessor) satisfy requires?
|
|
|
|
Yes, just be sure to consume the role I<after> declaring your
|
|
attribute. L<Moose::Manual::Roles/Required Attributes> provides
|
|
an example:
|
|
|
|
package Breakable;
|
|
use Moose::Role;
|
|
requires 'stress';
|
|
|
|
package Car;
|
|
use Moose;
|
|
has 'stress' => ( is => 'rw', isa => 'Int' );
|
|
with 'Breakable';
|
|
|
|
If you mistakenly consume the C<Breakable> role before declaring your
|
|
C<stress> attribute, you would see an error like this:
|
|
|
|
'Breakable' requires the method 'stress' to be implemented by 'Car' at...
|
|
|
|
=head2 Moose and Subroutine Attributes
|
|
|
|
=head3 Why don't subroutine attributes I inherited from a superclass work?
|
|
|
|
Currently when subclassing a module is done at runtime with the
|
|
C<extends> keyword, but attributes are checked at compile time by
|
|
Perl. To make attributes work, you must place C<extends> in a C<BEGIN>
|
|
block so that the attribute handlers will be available at compile time,
|
|
like this:
|
|
|
|
BEGIN { extends qw/Foo/ }
|
|
|
|
Note that we're talking about Perl's subroutine attributes here, not
|
|
Moose attributes:
|
|
|
|
sub foo : Bar(27) { ... }
|
|
|
|
=head1 AUTHORS
|
|
|
|
=over 4
|
|
|
|
=item *
|
|
|
|
Stevan Little <stevan@cpan.org>
|
|
|
|
=item *
|
|
|
|
Dave Rolsky <autarch@urth.org>
|
|
|
|
=item *
|
|
|
|
Jesse Luehrs <doy@cpan.org>
|
|
|
|
=item *
|
|
|
|
Shawn M Moore <sartak@cpan.org>
|
|
|
|
=item *
|
|
|
|
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
|
|
|
=item *
|
|
|
|
Karen Etheridge <ether@cpan.org>
|
|
|
|
=item *
|
|
|
|
Florian Ragwitz <rafl@debian.org>
|
|
|
|
=item *
|
|
|
|
Hans Dieter Pearcey <hdp@cpan.org>
|
|
|
|
=item *
|
|
|
|
Chris Prather <chris@prather.org>
|
|
|
|
=item *
|
|
|
|
Matt S Trout <mstrout@cpan.org>
|
|
|
|
=back
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
|
|
|
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
|
|
|
This is free software; you can redistribute it and/or modify it under
|
|
the same terms as the Perl 5 programming language system itself.
|
|
|
|
=cut
|