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