1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
=pod
=head1 NAME
Moose::Cookbook::WTF - For when things go wrong with Moose
=head1 COMMON PROBLEMS
=head2 Speed
=head3 Why is my code taking so long to load?
Moose does have a compile time performance burden,
which it inherits from Class::MOP. If load/compile
time is a concern for your application, Moose may not
be the right tool for you.
Although, you should note that we are exploring the
use of L<Module::Compile> to try and reduce this problem,
but nothing is ready yet.
=head3 Why are my objects taking so long to construct?
Moose uses a lot of introspection when constructing an
instance, and introspection can be slow. This problem
can be solved by making your class immutable. This can
be done with the following code:
MyClass->meta->make_immutable();
Moose will then memoize a number of meta-level methods
and inline a constructor for you. For more information
on this see the L<Constructors> section below and in the
L<Moose::Cookbook::FAQ>.
=head2 Constructors & Immutability
=head3 I made my class immutable, but C<new> it is still slow!
Do you have a custom C<new> method in your class? Moose
will not overwrite your custom C<new> method, you would
probably do better to try and convert this to use the
C<BUILD> method or possibly set C<default> values in
the attribute declaration.
=head3 I made my class immutable, and now my (before | after |
around) C<new> is not being called?
Making a I<before>, I<after> or I<around> wrap around the
C<new> method, will actually create a C<new> method within
your class. This will prevent Moose from creating one itself
when you make the class immutable.
=head2 Accessors
=head3 I created an attribute, where are my accessors?
Accessors are B<not> created implicitly, you B<must> ask Moose
to create them for you. My guess is that you have this:
has 'foo' => (isa => 'Bar');
when what you really want to say is:
has 'foo' => (isa => 'Bar', is => 'rw');
The reason this is so, is because it is a perfectly valid use
case to I<not> have an accessor. The simplest one is that you
want to write your own. If Moose created on automatically, then
because of the order in which classes are constructed, Moose
would overwrite your custom accessor. You wouldn't want that
would you?
=head2 Method Modifiers
=head3 How come I can't change C<@_> in a C<before> modifier?
The C<before> modifier simply is called I<before> the main method.
Its return values are simply ignored, and are B<not> passed onto
the main method body.
There are a number of reasons for this, but those arguments are
too lengthy for this document. Instead, I suggest using an C<around>
modifier instead. Here is some sample code:
around 'foo' => sub {
my $next = shift;
my ($self, @args) = @_;
# do something silly here to @args
$next->($self, reverse(@args));
};
=head3 How come I can't 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;
};
=head2 Moose and Attributes
=head3 Why don't attributes I inherited from a superclass work?
Currently when you subclass a module, this 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/ }
=head2 Moose and Other Modules
=head3 Why can't I get Catalyst and Moose to work together?
See L<Moose and Attributes>.
=head2 Roles
=head3 How come BUILD is not called for my composed roles?
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 un-ordered, it would be impossible to
determine the order in which to execute the 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<http://search.cpan.org/~stevan/Moose-0.21/lib/Moose/Cookbook/Recipe3.pod>)
=item *
Use attibutes triggers, which fire after an attribute it set, to faciliate
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> intialization, they should either
provide sane defaults or should be documented as needing specific
initialization. One such way to "document" this is to have a seperate
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.
=head1 AUTHOR
Stevan Little E<lt>stevan@iinteractive.comE<gt>
Anders Nor Berle E<lt>debolaz@gmail.comE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright 2006-2008 by Infinity Interactive, Inc.
L<http://www.iinteractive.com>
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
|