calling Moose->init_meta yourself really shouldn't be recommended
[gitmo/Moose.git] / lib / Moose / Cookbook / Extending / ExtensionOverview.pod
1 package Moose::Cookbook::Extending::ExtensionOverview;
2
3 # ABSTRACT: Moose extension overview
4
5 __END__
6
7
8 =pod
9
10 =head1 DESCRIPTION
11
12 Moose provides several ways in which extensions can hook into Moose
13 and change its behavior. Moose also has a lot of behavior that can be
14 changed. This recipe will provide an overview of each extension method
15 and give you some recommendations on what tools to use.
16
17 If you haven't yet read the recipes on metaclasses, go read those
18 first. You can't write Moose extensions without understanding the
19 metaclasses, and those recipes also demonstrate some basic extension
20 mechanisms, such as metaclass subclasses and traits.
21
22 =head2 Playing Nice With Others
23
24 One of the goals of this overview is to help you build extensions that
25 cooperate well with other extensions. This is especially important if
26 you plan to release your extension to CPAN.
27
28 Moose comes with several modules that exist to help your write
29 cooperative extensions. These are L<Moose::Exporter> and
30 L<Moose::Util::MetaRole>. By using these two modules, you will ensure
31 that your extension works with both the Moose core features and any
32 other CPAN extension using those modules.
33
34 =head1 PARTS OF Moose YOU CAN EXTEND
35
36 The types of things you might want to do in Moose extensions fall into
37 a few broad categories.
38
39 =head2 Metaclass Extensions
40
41 One way of extending Moose is by extending one or more Moose
42 metaclasses. For example, in L<Moose::Cookbook::Meta::Table_MetaclassTrait> we saw
43 a metaclass role that added a C<table> attribute to the
44 metaclass. If you were writing an ORM, this would be a logical
45 extension.
46
47 Many of the Moose extensions on CPAN work by providing an attribute
48 metaclass role. For example, the L<MooseX::Aliases> module
49 provides an attribute metaclass trait that lets you specify aliases
50 to install for methods and attribute accessors.
51
52 A metaclass extension can be packaged as a role/trait or a subclass. If you
53 can, we recommend using traits instead of subclasses, since it's much easier
54 to combine disparate traits than it is to combine a bunch of subclasses.
55
56 When your extensions are implemented as roles, you can apply them with
57 the L<Moose::Util::MetaRole> module.
58
59 =head2 Providing Sugar Functions
60
61 As part of a metaclass extension, you may also want to provide some
62 sugar functions, just like L<Moose.pm|Moose> does. Moose provides a
63 helper module called L<Moose::Exporter> that makes this much
64 simpler. We will be use L<Moose::Exporter> in several of the extension
65 recipes.
66
67 =head2 Object Class Extensions
68
69 Another common Moose extension technique is to change the default object
70 class's behavior. As with metaclass extensions, this can be done with a
71 role/trait or with a subclass. For example, L<MooseX::StrictConstructor>
72 extension applies a trait that makes the constructor reject arguments which
73 don't match its attributes.
74
75 Object class extensions often include metaclass extensions as well. In
76 particular, if you want your object extension to work when a class is
77 made immutable, you may need to modify the behavior of some or all of the
78 L<Moose::Meta::Instance>, L<Moose::Meta::Method::Constructor>, and
79 L<Moose::Meta::Method::Destructor> objects.
80
81 The L<Moose::Util::MetaRole> module lets you apply roles to the base
82 object class, as well as the meta classes just mentioned.
83
84 =head2 Providing a Role
85
86 Some extensions come in the form of a role for you to consume. The
87 L<MooseX::Object::Pluggable> extension is a great example of this. In
88 fact, despite the C<MooseX> name, it does not actually change anything
89 about Moose's behavior. Instead, it is just a role that an object
90 which wants to be pluggable can consume.
91
92 If you are implementing this sort of extension, you don't need to do
93 anything special. You simply create a role and document that it should
94 be used via the normal C<with> sugar:
95
96    package MyApp::User;
97
98    use Moose;
99
100    with 'My::Role';
101
102 Don't use "MooseX" in the name for such packages.
103
104 =head2 New Types
105
106 Another common Moose extension is a new type for the Moose type
107 system. In this case, you simply create a type in your module. When
108 people load your module, the type is created, and they can refer to it
109 by name after that. The L<MooseX::Types::URI> and
110 L<MooseX::Types::DateTime> distributions are two good examples of how
111 this works. These both build on top of the L<MooseX::Types> extension.
112
113 =head1 ROLES VS TRAITS VS SUBCLASSES
114
115 It is important to understand that B<roles and traits are the same thing>. A
116 trait is simply a role applied to a instance. The only thing that may
117 distinguish the two is that a trait can be packaged in a way that lets Moose
118 resolve a short name to a class name. In other words, with a trait, the caller
119 can refer to it by a short name like "Big", and Moose will resolve it to a
120 class like C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
121
122 See L<Moose::Cookbook::Meta::Labeled_AttributeTrait> and
123 L<Moose::Cookbook::Meta::Table_MetaclassTrait> for examples of traits in
124 action. In particular, both of these recipes demonstrate the trait resolution
125 mechanism.
126
127 Implementing an extension as a (set of) metaclass or base object
128 role(s) will make your extension more cooperative. It is hard for an
129 end-user to effectively combine together multiple metaclass
130 subclasses, but it is very easy to combine roles.
131
132 =head1 USING YOUR EXTENSION
133
134 There are a number of ways in which an extension can be applied. In
135 some cases you can provide multiple ways of consuming your extension.
136
137 =head2 Extensions as Metaclass Traits
138
139 If your extension is available as a trait, you can ask end users to
140 simply specify it in a list of traits. Currently, this only works for
141 (class) metaclass and attribute metaclass traits:
142
143   use Moose -traits => [ 'Big', 'Blue' ];
144
145   has 'animal' => (
146       traits => [ 'Big', 'Blue' ],
147       ...
148   );
149
150 If your extension applies to any other metaclass, or the object base
151 class, you cannot use the trait mechanism.
152
153 The benefit of the trait mechanism is that is very easy to see where a
154 trait is applied in the code, and consumers have fine-grained control
155 over what the trait applies to. This is especially true for attribute
156 traits, where you can apply the trait to just one attribute in a
157 class.
158
159 =head2 Extensions as Metaclass (and Base Object) Roles
160
161 Implementing your extensions as metaclass roles makes your extensions
162 easy to apply, and cooperative with other role-based extensions for
163 metaclasses.
164
165 Just as with a subclass, you will probably want to package your
166 extensions for consumption with a single module that uses
167 L<Moose::Exporter>. However, in this case, you will use
168 L<Moose::Util::MetaRole> to apply all of your roles. The advantage of
169 using this module is that I<it preserves any subclassing or roles
170 already applied to the user's metaclasses>. This means that your
171 extension is cooperative I<by default>, and consumers of your
172 extension can easily use it with other role-based extensions. Most
173 uses of L<Moose::Util::MetaRole> can be handled by L<Moose::Exporter>
174 directly; see the L<Moose::Exporter> docs.
175
176   package MooseX::Embiggen;
177
178   use Moose::Exporter;
179
180   use MooseX::Embiggen::Role::Meta::Class;
181   use MooseX::Embiggen::Role::Meta::Attribute;
182   use MooseX::Embiggen::Role::Meta::Method::Constructor;
183   use MooseX::Embiggen::Role::Object;
184
185   Moose::Exporter->setup_import_methods(
186       class_metaroles => {
187           class     => ['MooseX::Embiggen::Role::Meta::Class'],
188           attribute => ['MooseX::Embiggen::Role::Meta::Attribute'],
189           constructor =>
190               ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
191       },
192       base_class_roles => ['MooseX::Embiggen::Role::Object'],
193   );
194
195 As you can see from this example, you can use L<Moose::Util::MetaRole>
196 to apply roles to any metaclass, as well as the base object class. If
197 some other extension has already applied its own roles, they will be
198 preserved when your extension applies its roles, and vice versa.
199
200 =head2 Providing Sugar
201
202 With L<Moose::Exporter>, you can also export your own sugar functions:
203
204   package MooseX::Embiggen;
205
206   use Moose::Exporter;
207
208   Moose::Exporter->setup_import_methods(
209       with_meta       => ['embiggen'],
210       class_metaroles => {
211           class => ['MooseX::Embiggen::Role::Meta::Class'],
212       },
213   );
214
215   sub embiggen {
216       my $meta = shift;
217       $meta->embiggen(@_);
218   }
219
220 And then the consumer of your extension can use your C<embiggen> sub:
221
222   package Consumer;
223
224   use Moose;
225   use MooseX::Embiggen;
226
227   extends 'Thing';
228
229   embiggen ...;
230
231 This can be combined with metaclass and base class roles quite easily.
232
233 =head2 More advanced extensions
234
235 Providing your extension simply as a set of traits that gets applied to the
236 appropriate metaobjects is easy, but sometimes not sufficient. For instance,
237 sometimes you need to supply not just a base object role, but an actual base
238 object class (due to needing to interact with existing systems that only
239 provide a base class). To write extensions like this, you will need to provide
240 a custom C<init_meta> method in your exporter. For instance:
241
242   package MooseX::Embiggen;
243
244   use Moose::Exporter;
245
246   my ($import, $unimport, $init_meta) = Moose::Exporter->build_import_methods(
247       install         => ['import', 'unimport'],
248       with_meta       => ['embiggen'],
249       class_metaroles => {
250           class => ['MooseX::Embiggen::Role::Meta::Class'],
251       },
252   );
253
254   sub embiggen {
255       my $meta = shift;
256       $meta->embiggen(@_);
257   }
258
259   sub init_meta {
260       my $package = shift;
261       my %options = @_;
262       if (my $meta = Class::MOP::class_of($options{for_class})) {
263           if ($meta->isa('Class::MOP::Class')) {
264               my @supers = $meta->superclasses;
265               $meta->superclasses('MooseX::Embiggen::Base::Class')
266                   if @supers == 1 && $supers[0] eq 'Moose::Object';
267           }
268       }
269       $package->$init_meta(%options);
270   }
271
272 In the previous examples, C<init_meta> was generated for you, but here you must
273 override it in order to add additional functionality. Some differences to note:
274
275 =over 4
276
277 =item C<build_import_methods> instead of C<setup_import_methods>
278
279 C<build_import_methods> simply returns the C<import>, C<unimport>, and
280 C<init_meta> methods, rather than installing them under the appropriate names.
281 This way, you can write your own which wrap the existing functionality.
282 C<build_import_methods> also takes an additional C<install> parameter, which
283 tells it to just go ahead and install these methods (since we don't need to
284 modify them).
285
286 =item C<sub init_meta>
287
288 Next, we must write our C<init_meta> wrapper. The important things to remember
289 are that it is called as a method, and that C<%options> needs to be passed
290 through to the existing implementation. Calling the base implementation just
291 uses the C<$init_meta> subroutine reference that was returned by
292 C<build_import_methods> earlier.
293
294 =item Additional implementation
295
296 This extension sets a different default base object class. To do so, it first
297 checks to see if it's being applied to a class, and then checks to see if
298 L<Moose::Object> is that class's only superclass, and if so, replaces that with
299 the superclass that this extension requires.
300
301 Note that two extensions that do this same thing will not work together
302 properly (the second extension to be loaded won't see L<Moose::Object> as the
303 base object, since it has already been overridden). This is why using a base
304 object role is recommended for the general case.
305
306 This C<init_meta> also works defensively, by only applying its functionality if
307 a metaclass already exists. This makes sure it doesn't break with legacy
308 extensions which override the metaclass directly (and so must be the first
309 extension to initialize the metaclass). This is likely not necessary, since
310 almost no extensions work this way anymore, but just provides an additional
311 level of protection. The common case of C<use Moose; use MooseX::Embiggen;>
312 is not affected regardless.
313
314 =back
315
316 This is just one example of what can be done with a custom C<init_meta> method.
317 It can also be used for preventing an extension from being applied to a role,
318 doing other kinds of validation on the class being applied to, or pretty much
319 anything that would otherwise be done in an C<import> method.
320
321 =head1 LEGACY EXTENSION MECHANISMS
322
323 Before the existence of L<Moose::Exporter> and
324 L<Moose::Util::MetaRole>, there were a number of other ways to extend
325 Moose. In general, these methods were less cooperative, and only
326 worked well with a single extension.
327
328 These methods include L<metaclass.pm|metaclass>, L<Moose::Policy>
329 (which uses L<metaclass.pm|metaclass> under the hood), and various
330 hacks to do what L<Moose::Exporter> does. Please do not use these for
331 your own extensions.
332
333 Note that if you write a cooperative extension, it should cooperate
334 with older extensions, though older extensions generally do not
335 cooperate with each other.
336
337 =head1 CONCLUSION
338
339 If you can write your extension as one or more metaclass and base
340 object roles, please consider doing so. Make sure to read the docs for
341 L<Moose::Exporter> and L<Moose::Util::MetaRole> as well.
342
343 =cut