bump version to 0.87
[gitmo/Moose.git] / lib / Moose / Cookbook / Extending / Recipe1.pod
CommitLineData
c8d5f1e1 1
2=pod
3
4=head1 NAME
5
5f2aa10a 6Moose::Cookbook::Extending::Recipe1 - Moose extension overview
c8d5f1e1 7
8=head1 DESCRIPTION
9
0558aab4 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.
c8d5f1e1 14
15If you haven't yet read the recipes on metaclasses, go read those
0558aab4 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.
c8d5f1e1 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
0558aab4 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.
c8d5f1e1 31
32=head1 PARTS OF Moose YOU CAN EXTEND
33
0558aab4 34The types of things you might want to do in Moose extensions fall into
35a few broad categories.
c8d5f1e1 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
0558aab4 46metaclass extension. For example, the L<MooseX::AttributeHelpers>
6549b0d1 47distribution provides a new attribute metaclass that lets you delegate
c8d5f1e1 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
38f0beac 52subclasses, since it's much easier to combine disparate traits than it
0558aab4 53is to combine a bunch of subclasses.
c8d5f1e1 54
55When your extensions are implemented as roles, you can apply them with
56the L<Moose::Util::MetaRole> module.
57
0558aab4 58=head2 Providing Sugar Functions
c8d5f1e1 59
60As part of a metaclass extension, you may also want to provide some
0558aab4 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.
c8d5f1e1 65
66=head2 Object Class Extensions
67
0558aab4 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.
c8d5f1e1 73
0558aab4 74Object class extensions often include metaclass extensions as well. In
c8d5f1e1 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
0558aab4 77L<Moose::Meta::Instance>, L<Moose::Meta::Method::Constructor>, and
78L<Moose::Meta::Method::Destructor> objects.
c8d5f1e1 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
0558aab4 86L<MooseX::Object::Pluggable> extension is a great example of this. In
c8d5f1e1 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
0558aab4 95 package MyApp::User;
c8d5f1e1 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
0558aab4 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.
c8d5f1e1 109
110=head1 ROLES VS TRAITS VS SUBCLASSES
111
112It is important to understand that B<roles and traits are the same
113thing>. A role can be used as a trait, and a trait is a role. The only
114thing that distinguishes the two is that a trait is packaged in a way
115that lets Moose resolve a short name to a class name. In other words,
0558aab4 116with a trait, the caller can refer to it by a short name like "Big",
c8d5f1e1 117and Moose will resolve it to a class like
118C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
119
120See L<Moose::Cookbook::Meta::Recipe3> and
121L<Moose::Cookbook::Meta::Recipe5> for examples of traits in action. In
122particular, both of these recipes demonstrate the trait resolution
123mechanism.
124
125Implementing an extension as a (set of) metaclass or base object
126role(s) will make your extension more cooperative. It is hard for an
127end-user to effectively combine together multiple metaclass
0558aab4 128subclasses, but it is very easy to combine roles.
c8d5f1e1 129
130=head1 USING YOUR EXTENSION
131
132There are a number of ways in which an extension can be applied. In
133some cases you can provide multiple ways of consuming your extension.
134
135=head2 Extensions as Metaclass Traits
136
137If your extension is available as a trait, you can ask end users to
138simply specify it in a list of traits. Currently, this only works for
0558aab4 139(class) metaclass and attribute metaclass traits:
c8d5f1e1 140
141 use Moose -traits => [ 'Big', 'Blue' ];
142
6a7e3999 143 has 'animal' => (
144 traits => [ 'Big', 'Blue' ],
145 ...
146 );
c8d5f1e1 147
148If your extension applies to any other metaclass, or the object base
149class, you cannot use the trait mechanism.
150
151The benefit of the trait mechanism is that is very easy to see where a
152trait is applied in the code, and consumers have fine-grained control
153over what the trait applies to. This is especially true for attribute
154traits, where you can apply the trait to just one attribute in a
155class.
156
157=head2 Extensions as Metaclass (and Base Object) Subclasses
158
159Moose does not provide any simple APIs for consumers to use a subclass
4223567e 160extension, except for attribute metaclasses. The attribute declaration
16fb3624 161options include a C<metaclass> option a consumer of your extension can
162use to specify your subclass.
c8d5f1e1 163
164This is one reason why implementing an extension as a subclass can be
165a poor choice. However, you can force the use of certain subclasses at
166import time by calling C<< Moose->init_meta >> for the caller, and
167providing an alternate metaclass or base object class.
168
0558aab4 169If you do want to do this, you should look at using L<Moose::Exporter>
170to re-export the L<Moose.pm|Moose> sugar function. With
171L<Moose::Exporter>, if your exporting class has an C<init_meta>
c8d5f1e1 172method, L<Moose::Exporter> makes sure that this C<init_meta> method
173gets called when your class is imported.
174
175Then in your C<init_meta> you can arrange for the caller to use your
176subclasses:
177
178 package MooseX::Embiggen;
179
180 use Moose ();
181 use Moose::Exporter;
182
183 use MooseX::Embiggen::Meta::Class;
184 use MooseX::Embiggen::Object;
185
186 Moose::Exporter->setup_import_methods( also => 'Moose' );
187
188 sub init_meta {
6a7e3999 189 shift; # just your package name
c8d5f1e1 190 my %options = @_;
191
192 return Moose->init_meta(
193 for_class => $options{for_class},
194 metaclass => 'MooseX::Embiggen::Meta::Class',
195 base_class => 'MooseX::Embiggen::Object',
196 );
197 }
198
a8de959b 199NOTE: Make sure that your C<init_meta> returns the metaclass object, just as
200C<< Moose->init_meta >> does.
201
c8d5f1e1 202=head2 Extensions as Metaclass (and Base Object) Roles
203
204Implementing your extensions as metaclass roles makes your extensions
0558aab4 205easy to apply, and cooperative with other role-based extensions for
206metaclasses.
c8d5f1e1 207
208Just as with a subclass, you will probably want to package your
209extensions for consumption with a single module that uses
210L<Moose::Exporter>. However, in this case, you will use
211L<Moose::Util::MetaRole> to apply all of your roles. The advantage of
212using this module is that I<it preserves any subclassing or roles
0558aab4 213already applied to the user's metaclasses>. This means that your
c8d5f1e1 214extension is cooperative I<by default>, and consumers of your
215extension can easily use it with other role-based extensions.
216
217 package MooseX::Embiggen;
218
219 use Moose ();
220 use Moose::Exporter;
221 use Moose::Util::MetaRole;
222
223 use MooseX::Embiggen::Role::Meta::Class;
224 use MooseX::Embiggen::Role::Meta::Attribute;
6a7e3999 225 use MooseX::Embiggen::Role::Meta::Method::Constructor;
c8d5f1e1 226 use MooseX::Embiggen::Role::Object;
227
228 Moose::Exporter->setup_import_methods( also => 'Moose' );
229
230 sub init_meta {
6a7e3999 231 shift; # just your package name
c8d5f1e1 232 my %options = @_;
233
234 Moose->init_meta(%options);
235
236 my $meta = Moose::Util::MetaRole::apply_metaclass_roles(
237 for_class => $options{for_class},
238 metaclass_roles => ['MooseX::Embiggen::Role::Meta::Class'],
239 attribute_metaclass_roles =>
240 ['MooseX::Embiggen::Role::Meta::Attribute'],
241 constructor_class_roles =>
242 ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
243 );
244
245 Moose::Util::MetaRole::apply_base_class_roles(
246 for_class => $options{for_class},
247 roles => ['MooseX::Embiggen::Role::Object'],
248 );
249
250 return $meta;
251 }
252
0558aab4 253As you can see from this example, you can use L<Moose::Util::MetaRole>
c8d5f1e1 254to apply roles to any metaclass, as well as the base object class. If
255some other extension has already applied its own roles, they will be
256preserved when your extension applies its roles, and vice versa.
257
258=head2 Providing Sugar
259
0558aab4 260With L<Moose::Exporter>, you can also export your own sugar functions,
261as well as those from other modules:
c8d5f1e1 262
263 package MooseX::Embiggen;
264
265 use Moose ();
266 use Moose::Exporter;
267
268 Moose::Exporter->setup_import_methods(
269 with_caller => ['embiggen'],
270 also => 'Moose',
271 );
272
273 sub init_meta { ... }
274
275 sub embiggen {
276 my $caller = shift;
277 $caller->meta()->embiggen(@_);
278 }
279
280And then the consumer of your extension can use your C<embiggen> sub:
281
282 package Consumer;
283
284 use MooseX::Embiggen;
285
286 extends 'Thing';
287
288 embiggen ...;
289
290This can be combined with metaclass and base class roles quite easily.
291
0558aab4 292=head1 LEGACY EXTENSION MECHANISMS
c8d5f1e1 293
294Before the existence of L<Moose::Exporter> and
295L<Moose::Util::MetaRole>, there were a number of other ways to extend
296Moose. In general, these methods were less cooperative, and only
297worked well with a single extension.
298
0558aab4 299These methods include L<metaclass.pm|metaclass>, L<Moose::Policy>
300(which uses L<metaclass.pm|metaclass> under the hood), and various
301hacks to do what L<Moose::Exporter> does. Please do not use these for
302your own extensions.
c8d5f1e1 303
304Note that if you write a cooperative extension, it should cooperate
305with older extensions, though older extensions generally do not
8745c929 306cooperate with each other.
c8d5f1e1 307
308=head1 CONCLUSION
309
310If you can write your extension as one or more metaclass and base
311object roles, please consider doing so. Make sure to read the docs for
312L<Moose::Exporter> and L<Moose::Util::MetaRole> as well.
313
314=head1 AUTHOR
315
316Dave Rolsky E<lt>autarch@urth.orgE<gt>
317
318=head1 COPYRIGHT AND LICENSE
319
2840a3b2 320Copyright 2009 by Infinity Interactive, Inc.
c8d5f1e1 321
322L<http://www.iinteractive.com>
323
324This library is free software; you can redistribute it and/or modify
325it under the same terms as Perl itself.
326
327=cut