File: WTF.pod

package info (click to toggle)
libmoose-perl 0.54-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 1,496 kB
  • ctags: 448
  • sloc: perl: 15,125; makefile: 10
file content (206 lines) | stat: -rw-r--r-- 6,357 bytes parent folder | download
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