Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / Moose / Cookbook / Extending / Recipe1.pod
CommitLineData
3fea05b9 1
2=pod
3
4=head1 NAME
5
6Moose::Cookbook::Extending::Recipe1 - Moose extension overview
7
8=head1 DESCRIPTION
9
10Moose provides several ways in which extensions can hook into Moose
11and change its behavior. Moose also has a lot of behavior that can be
12changed. This recipe will provide an overview of each extension method
13and give you some recommendations on what tools to use.
14
15If you haven't yet read the recipes on metaclasses, go read those
16first. You can't write Moose extensions without understanding the
17metaclasses, and those recipes also demonstrate some basic extension
18mechanisms, such as metaclass subclasses and traits.
19
20=head2 Playing Nice With Others
21
22One of the goals of this overview is to help you build extensions that
23cooperate well with other extensions. This is especially important if
24you plan to release your extension to CPAN.
25
26Moose comes with several modules that exist to help your write
27cooperative extensions. These are L<Moose::Exporter> and
28L<Moose::Util::MetaRole>. By using these two modules, you will ensure
29that your extension works with both the Moose core features and any
30other CPAN extension using those modules.
31
32=head1 PARTS OF Moose YOU CAN EXTEND
33
34The types of things you might want to do in Moose extensions fall into
35a few broad categories.
36
37=head2 Metaclass Extensions
38
39One way of extending Moose is by extending one or more Moose
40metaclasses. For example, in L<Moose::Cookbook::Meta::Recipe4> we saw
41a metaclass subclass that added a C<table> attribute to the
42metaclass. If you were writing an ORM, this would be a logical
43extension.
44
45Many of the Moose extensions on CPAN work by providing an attribute
46metaclass extension. For example, the L<MooseX::AttributeHelpers>
47distribution provides a new attribute metaclass that lets you delegate
48behavior to a non-object attribute (a hashref or simple number).
49
50A metaclass extension can be packaged as a subclass or a
51role/trait. If you can, we recommend using traits instead of
52subclasses, since it's much easier to combine disparate traits than it
53is to combine a bunch of subclasses.
54
55When your extensions are implemented as roles, you can apply them with
56the L<Moose::Util::MetaRole> module.
57
58=head2 Providing Sugar Functions
59
60As part of a metaclass extension, you may also want to provide some
61sugar functions, just like L<Moose.pm|Moose> does. Moose provides a
62helper module called L<Moose::Exporter> that makes this much
63simpler. We will be use L<Moose::Exporter> in several of the extension
64recipes.
65
66=head2 Object Class Extensions
67
68Another common Moose extension technique is to change the default
69object class's behavior. For example, the L<MooseX::Singleton>
70extension changes the behavior of your objects so that they are
71singletons. The L<MooseX::StrictConstructor> extension makes the
72constructor reject arguments which don't match its attributes.
73
74Object class extensions often include metaclass extensions as well. In
75particular, if you want your object extension to work when a class is
76made immutable, you may need to extend some or all of the
77L<Moose::Meta::Instance>, L<Moose::Meta::Method::Constructor>, and
78L<Moose::Meta::Method::Destructor> objects.
79
80The L<Moose::Util::MetaRole> module lets you apply roles to the base
81object class, as well as the meta classes just mentioned.
82
83=head2 Providing a Role
84
85Some extensions come in the form of a role for you to consume. The
86L<MooseX::Object::Pluggable> extension is a great example of this. In
87fact, despite the C<MooseX> name, it does not actually change anything
88about Moose's behavior. Instead, it is just a role that an object
89which wants to be pluggable can consume.
90
91If you are implementing this sort of extension, you don't need to do
92anything special. You simply create a role and document that it should
93be used via the normal C<with> sugar:
94
95 package MyApp::User;
96
97 use Moose;
98
99 with 'MooseX::My::Role';
100
101=head2 New Types
102
103Another common Moose extension is a new type for the Moose type
104system. In this case, you simply create a type in your module. When
105people load your module, the type is created, and they can refer to it
106by name after that. The L<MooseX::Types::URI> and
107L<MooseX::Types::DateTime> distributions are two good examples of how
108this works. These both build on top of the L<MooseX::Types> extension.
109
110=head1 ROLES VS TRAITS VS SUBCLASSES
111
112It is important to understand that B<roles and traits are the same thing>. A
113trait is simply a role applied to a instance. The only thing that may
114distinguish the two is that a trait can be packaged in a way that lets Moose
115resolve a short name to a class name. In other words, with a trait, the caller
116can refer to it by a short name like "Big", and Moose will resolve it to a
117class like C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
118
119See L<Moose::Cookbook::Meta::Recipe3> and
120L<Moose::Cookbook::Meta::Recipe5> for examples of traits in action. In
121particular, both of these recipes demonstrate the trait resolution
122mechanism.
123
124Implementing an extension as a (set of) metaclass or base object
125role(s) will make your extension more cooperative. It is hard for an
126end-user to effectively combine together multiple metaclass
127subclasses, but it is very easy to combine roles.
128
129=head1 USING YOUR EXTENSION
130
131There are a number of ways in which an extension can be applied. In
132some cases you can provide multiple ways of consuming your extension.
133
134=head2 Extensions as Metaclass Traits
135
136If your extension is available as a trait, you can ask end users to
137simply specify it in a list of traits. Currently, this only works for
138(class) metaclass and attribute metaclass traits:
139
140 use Moose -traits => [ 'Big', 'Blue' ];
141
142 has 'animal' => (
143 traits => [ 'Big', 'Blue' ],
144 ...
145 );
146
147If your extension applies to any other metaclass, or the object base
148class, you cannot use the trait mechanism.
149
150The benefit of the trait mechanism is that is very easy to see where a
151trait is applied in the code, and consumers have fine-grained control
152over what the trait applies to. This is especially true for attribute
153traits, where you can apply the trait to just one attribute in a
154class.
155
156=head2 Extensions as Metaclass (and Base Object) Subclasses
157
158Moose does not provide any simple APIs for consumers to use a subclass
159extension, except for attribute metaclasses. The attribute declaration
160options include a C<metaclass> option a consumer of your extension can
161use to specify your subclass.
162
163This is one reason why implementing an extension as a subclass can be
164a poor choice. However, you can force the use of certain subclasses at
165import time by calling C<< Moose->init_meta >> for the caller, and
166providing an alternate metaclass or base object class.
167
168If you do want to do this, you should look at using L<Moose::Exporter>
169to re-export the L<Moose.pm|Moose> sugar function. With
170L<Moose::Exporter>, if your exporting class has an C<init_meta>
171method, L<Moose::Exporter> makes sure that this C<init_meta> method
172gets called when your class is imported.
173
174Then in your C<init_meta> you can arrange for the caller to use your
175subclasses:
176
177 package MooseX::Embiggen;
178
179 use Moose ();
180 use Moose::Exporter;
181
182 use MooseX::Embiggen::Meta::Class;
183 use MooseX::Embiggen::Object;
184
185 Moose::Exporter->setup_import_methods( also => 'Moose' );
186
187 sub init_meta {
188 shift; # just your package name
189 my %options = @_;
190
191 return Moose->init_meta(
192 for_class => $options{for_class},
193 metaclass => 'MooseX::Embiggen::Meta::Class',
194 base_class => 'MooseX::Embiggen::Object',
195 );
196 }
197
198NOTE: Make sure that your C<init_meta> returns the metaclass object, just as
199C<< Moose->init_meta >> does.
200
201=head2 Extensions as Metaclass (and Base Object) Roles
202
203Implementing your extensions as metaclass roles makes your extensions
204easy to apply, and cooperative with other role-based extensions for
205metaclasses.
206
207Just as with a subclass, you will probably want to package your
208extensions for consumption with a single module that uses
209L<Moose::Exporter>. However, in this case, you will use
210L<Moose::Util::MetaRole> to apply all of your roles. The advantage of
211using this module is that I<it preserves any subclassing or roles
212already applied to the user's metaclasses>. This means that your
213extension is cooperative I<by default>, and consumers of your
214extension can easily use it with other role-based extensions. Most
215uses of L<Moose::Util::MetaRole> can be handled by L<Moose::Exporter>
216directly; see the L<Moose::Exporter> docs.
217
218 package MooseX::Embiggen;
219
220 use Moose ();
221 use Moose::Exporter;
222
223 use MooseX::Embiggen::Role::Meta::Class;
224 use MooseX::Embiggen::Role::Meta::Attribute;
225 use MooseX::Embiggen::Role::Meta::Method::Constructor;
226 use MooseX::Embiggen::Role::Object;
227
228 my ( $import, $unimport, $init_meta ) = Moose::Exporter->build_import_methods(
229 also => ['Moose'] metaclass_roles =>
230 ['MooseX::Embiggen::Role::Meta::Class'],
231 attribute_metaclass_roles => ['MooseX::Embiggen::Role::Meta::Attribute'],
232 constructor_class_roles =>
233 ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
234 base_class_roles => ['MooseX::Embiggen::Role::Object'],
235 install => [qw(import unimport)],
236 );
237
238 sub init_meta {
239 my $package = shift;
240 my %options = @_;
241 Moose->init_meta(%options);
242 return $package->$init_meta(%options);
243 }
244
245As you can see from this example, you can use L<Moose::Util::MetaRole>
246to apply roles to any metaclass, as well as the base object class. If
247some other extension has already applied its own roles, they will be
248preserved when your extension applies its roles, and vice versa.
249
250=head2 Providing Sugar
251
252With L<Moose::Exporter>, you can also export your own sugar functions,
253as well as those from other modules:
254
255 package MooseX::Embiggen;
256
257 use Moose ();
258 use Moose::Exporter;
259
260 Moose::Exporter->setup_import_methods(
261 with_meta => ['embiggen'],
262 also => 'Moose',
263 );
264
265 sub embiggen {
266 my $meta = shift;
267 $meta->embiggen(@_);
268 }
269
270And then the consumer of your extension can use your C<embiggen> sub:
271
272 package Consumer;
273
274 use MooseX::Embiggen;
275
276 extends 'Thing';
277
278 embiggen ...;
279
280This can be combined with metaclass and base class roles quite easily.
281
282=head1 LEGACY EXTENSION MECHANISMS
283
284Before the existence of L<Moose::Exporter> and
285L<Moose::Util::MetaRole>, there were a number of other ways to extend
286Moose. In general, these methods were less cooperative, and only
287worked well with a single extension.
288
289These methods include L<metaclass.pm|metaclass>, L<Moose::Policy>
290(which uses L<metaclass.pm|metaclass> under the hood), and various
291hacks to do what L<Moose::Exporter> does. Please do not use these for
292your own extensions.
293
294Note that if you write a cooperative extension, it should cooperate
295with older extensions, though older extensions generally do not
296cooperate with each other.
297
298=head1 CONCLUSION
299
300If you can write your extension as one or more metaclass and base
301object roles, please consider doing so. Make sure to read the docs for
302L<Moose::Exporter> and L<Moose::Util::MetaRole> as well.
303
304=head1 AUTHOR
305
306Dave Rolsky E<lt>autarch@urth.orgE<gt>
307
308=head1 COPYRIGHT AND LICENSE
309
310Copyright 2009 by Infinity Interactive, Inc.
311
312L<http://www.iinteractive.com>
313
314This library is free software; you can redistribute it and/or modify
315it under the same terms as Perl itself.
316
317=cut