Tiny little spelling error in Moose::Cookbook::Extending::Recipe1
[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
10Moose has quite a number of ways in which extensions can hook into
11Moose and change its behavior. Moose also has a lot of behavior that
12can be changed. This recipe will provide an overview of each extension
13method and 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 really write Moose extensions without understanding
17the metaclasses, and those recipes also demonstrate some basic
18extensions mechanisms 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 to implement your
29extensions, you will ensure that your extension works with both the
30Moose core features and any other 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 broadly
35fall into a few 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 C<MooseX::AttributeHelpers>
47distro 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 generally much easier to combine disparate
53traits then it is 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 Subs
59
60As part of a metaclass extension, you may also want to provide some
61sugar subroutines, much like C<Moose.pm> does. Moose provides a helper
62module called L<Moose::Exporter> that makes this much simpler. This
63will be used in several of the extension recipes.
64
65=head2 Object Class Extensions
66
67Another common Moose extension is to change the default object class
68behavior. For example, the C<MooseX::Singleton> extension changes the
69behavior of your objects so that they are singletons. The
70C<MooseX::StrictConstructor> extension makes the constructor reject
71arguments which don't match its attributes.
72
73Object class extensions often also include metaclass extensions. In
74particular, if you want your object extension to work when a class is
75made immutable, you may need to extend some or all of the
76C<Moose::Meta::Instance>, C<Moose::Meta::Method::Constructor>, and
77C<Moose::Meta::Method::Destructor> objects.
78
79The L<Moose::Util::MetaRole> module lets you apply roles to the base
80object class, as well as the meta classes just mentioned.
81
82=head2 Providing a Role
83
84Some extensions come in the form of a role for you to consume. The
85C<MooseX::Object::Pluggable> extension is a great example of this. In
86fact, despite the C<MooseX> name, it does not actually change anything
87about Moose's behavior. Instead, it is just a role that an object
88which wants to be pluggable can consume.
89
90If you are implementing this sort of extension, you don't need to do
91anything special. You simply create a role and document that it should
92be used via the normal C<with> sugar:
93
94 package RoleConsumer;
95
96 use Moose;
97
98 with 'MooseX::My::Role';
99
100=head2 New Types
101
102Another common Moose extension is a new type for the Moose type
103system. In this case, you simply create a type in your module. When
104people load your module, the type is created, and they can refer to it
105by name after that. The C<MooseX::Types::URI> and
106C<MooseX::Types::DateTime> distros are two good examples of how this
107works.
108
109=head1 ROLES VS TRAITS VS SUBCLASSES
110
111It is important to understand that B<roles and traits are the same
112thing>. A role can be used as a trait, and a trait is a role. The only
113thing that distinguishes the two is that a trait is packaged in a way
114that lets Moose resolve a short name to a class name. In other words,
115with a trait, the caller can specify it by a short name like "Big",
116and Moose will resolve it to a class like
117C<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 can be 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
138metaclass 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
4223567e 159extension, except for attribute metaclasses. The attribute declaration
c8d5f1e1 160parameters include a C<metaclass> parameter a consumer of your
161extension can use 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 C<Moose::Exporter>
169to re-export the C<Moose.pm> sugar subroutines. When you use
170L<Moose::Exporter> and 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
198=head2 Extensions as Metaclass (and Base Object) Roles
199
200Implementing your extensions as metaclass roles makes your extensions
201easy to apply, and cooperative with other metaclass role-based extensions.
202
203Just as with a subclass, you will probably want to package your
204extensions for consumption with a single module that uses
205L<Moose::Exporter>. However, in this case, you will use
206L<Moose::Util::MetaRole> to apply all of your roles. The advantage of
207using this module is that I<it preserves any subclassing or roles
208already applied to the users metaclasses>. This means that your
209extension is cooperative I<by default>, and consumers of your
210extension can easily use it with other role-based extensions.
211
212 package MooseX::Embiggen;
213
214 use Moose ();
215 use Moose::Exporter;
216 use Moose::Util::MetaRole;
217
218 use MooseX::Embiggen::Role::Meta::Class;
219 use MooseX::Embiggen::Role::Meta::Attribute;
220 use MooseX::Embiggen::Role::Meta::Method::Constructor
221 use MooseX::Embiggen::Role::Object;
222
223 Moose::Exporter->setup_import_methods( also => 'Moose' );
224
225 sub init_meta {
226 shift; # just your package name
227 my %options = @_;
228
229 Moose->init_meta(%options);
230
231 my $meta = Moose::Util::MetaRole::apply_metaclass_roles(
232 for_class => $options{for_class},
233 metaclass_roles => ['MooseX::Embiggen::Role::Meta::Class'],
234 attribute_metaclass_roles =>
235 ['MooseX::Embiggen::Role::Meta::Attribute'],
236 constructor_class_roles =>
237 ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
238 );
239
240 Moose::Util::MetaRole::apply_base_class_roles(
241 for_class => $options{for_class},
242 roles => ['MooseX::Embiggen::Role::Object'],
243 );
244
245 return $meta;
246 }
247
248As you can see from this example, you can use C<Moose::Util::MetaRole>
249to apply roles to any metaclass, as well as the base object class. If
250some other extension has already applied its own roles, they will be
251preserved when your extension applies its roles, and vice versa.
252
253=head2 Providing Sugar
254
255With L<Moose::Exporter>, you can also export your own sugar subs, as
256well as those from other sugar modules:
257
258 package MooseX::Embiggen;
259
260 use Moose ();
261 use Moose::Exporter;
262
263 Moose::Exporter->setup_import_methods(
264 with_caller => ['embiggen'],
265 also => 'Moose',
266 );
267
268 sub init_meta { ... }
269
270 sub embiggen {
271 my $caller = shift;
272 $caller->meta()->embiggen(@_);
273 }
274
275And then the consumer of your extension can use your C<embiggen> sub:
276
277 package Consumer;
278
279 use MooseX::Embiggen;
280
281 extends 'Thing';
282
283 embiggen ...;
284
285This can be combined with metaclass and base class roles quite easily.
286
287=head1 LEGACY EXTENSION METHODOLOGIES
288
289Before the existence of L<Moose::Exporter> and
290L<Moose::Util::MetaRole>, there were a number of other ways to extend
291Moose. In general, these methods were less cooperative, and only
292worked well with a single extension.
293
294These methods include C<metaclass.pm>, C<Moose::Policy> (which uses
295C<metaclass.pm> under the hood), and various hacks to do what
296L<Moose::Exporter> does. Please do not use these for your own
297extensions.
298
299Note that if you write a cooperative extension, it should cooperate
300with older extensions, though older extensions generally do not
301cooperate with each oether.
302
303=head1 CONCLUSION
304
305If you can write your extension as one or more metaclass and base
306object roles, please consider doing so. Make sure to read the docs for
307L<Moose::Exporter> and L<Moose::Util::MetaRole> as well.
308
6b956db7 309=head2 Caveat
310
311The L<Moose::Util::MetaRole> API is still considered an experiment,
312and could go away or change in the future.
313
c8d5f1e1 314=head1 AUTHOR
315
316Dave Rolsky E<lt>autarch@urth.orgE<gt>
317
318=head1 COPYRIGHT AND LICENSE
319
26acc541 320Copyright 2008 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