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