Commit | Line | Data |
9632a49e |
1 | =pod |
2 | |
3 | =head1 NAME |
4 | |
5 | Moose::Cookbook::Style - How to cook Moose with style |
6 | |
7 | =for authors |
8 | |
9 | Please annotate all bad examples with comments so that they won't be copied by accodent |
10 | |
11 | =cut |
12 | |
13 | =head1 Benefits of Good Style |
14 | |
15 | Good Moose style, as defined by this document, helps ensure your code has the |
16 | following desirable properties: |
17 | |
18 | =over 4 |
19 | |
20 | =item Play well with others |
21 | |
22 | Your code will be more reusable and easier to extend. |
23 | |
24 | =item Ease maintenance |
25 | |
26 | The code will be easier to understand because it follows an accepted set of |
27 | conventions and idioms. |
28 | |
29 | This will help others maintaining your code, and also help you to get support |
30 | on IRC for instance. |
31 | |
32 | =item Help Moose generate better code |
33 | |
34 | By using the most appropriate features, the generated code will be safer and |
35 | more efficient. |
36 | |
37 | =item Benefit from meta programming |
38 | |
39 | Code that operates on the metaclass will benefit from clean meta definitions. |
40 | |
41 | If you are manually converting argument types with C<around 'new'> there is no |
42 | meta data explaining your intention. If on the other hand you use coercions, |
43 | there is introspectable meta data that makes this clear. |
44 | |
45 | This means that e.g. MooseX extensions that work by introspecting your class |
46 | will be able to do the right thing more often, because they don't need to |
47 | guess. |
48 | |
49 | =back |
50 | |
51 | =head1 Don't change C<new> |
52 | |
53 | It is generally considered bad style to override L<Moose::Object/new> for a |
54 | number of reasons. |
55 | |
56 | The first reason is consistency. Subclasses of your class and code |
57 | instantiating your class would be simpler if your constructor works closer to |
58 | the default. |
59 | |
60 | The second reason is performance. By calling C<make_immutable> on your metaclass: |
61 | |
62 | __PACKAGE__->meta->make_immutable; |
63 | |
64 | And opting out of any class definition changes from that point on, you allow |
65 | Moose to create more efficient versions of certain generic methods. Moose will |
66 | generate a tight, optimal C<new> for you, based on the minimal set of features |
67 | you use. |
68 | |
69 | Moose provides many features that allow you to do common object construction |
70 | tasks at the right level of abstraction. |
71 | |
72 | When attributes have the ability to provide the necessary functionality, use |
73 | that. If that isn't sufficient, L<Moose::Object> has numerous features you can |
74 | use at construction time. |
75 | |
76 | =head2 Use C<BUILD> instead of custom initialization or overriding C<new> |
77 | |
78 | Instead of changing C<new>, do initialization in C<BUILD>. |
79 | |
80 | The construction parameters are passed in, so you don't need to replicate |
81 | C<BUILDARGS>, and since C<BUILD> is called for each superclass that defines it, |
82 | you will never forget to invoke your initializers if you extend them. |
83 | |
84 | =head2 Use C<default>, C<builder> or C<lazy_build> |
85 | |
86 | To initialize attributes there is a plethora of methods preferable to assigning |
87 | the value at initialization time. |
88 | |
89 | If you want to translate parameter data, use coercions. |
90 | |
91 | If you want to ensure a parameter can't be overridden by the constructor, set |
92 | the C<init_arg> to C<undef> instead of overwriting it in C<BUILD>. |
93 | |
94 | =head2 Use C<BUILDARGS> to alter C<@_> processing |
95 | |
96 | If you need to change the way L<@_> is processed, use C<BUILDARGS>, instead of |
97 | wrapping C<new>. This ensures the behavior is subclassible, it keeps this logic |
98 | independent of the other aspects of construction, and can be made efficient |
99 | using C<make_immutable>. |
100 | |
101 | =head1 Don't pollute the global type registry |
102 | |
103 | =head2 Use fully qualified type names for your own data |
104 | |
105 | L<MooseX::Types> provides a convenient method to do this. |
106 | |
107 | If you define |
108 | |
109 | # Bad style: |
110 | |
111 | subtype Person => ( |
112 | as 'Object', |
113 | where { $_->can("name") }, |
114 | ); |
115 | |
116 | Then the global name C<Person> is registered, and this could conflict with |
117 | other bad usage of the sort. |
118 | |
119 | Instead, prefix type name with your project namespace, or class name: |
120 | |
121 | subtype 'My::Foo::Person' => ( |
122 | as 'Object', |
123 | where { $_->can("name") }, |
124 | ); |
125 | |
126 | Or with L<MooseX::Types>: |
127 | |
128 | use MooseX::Types ( |
129 | -declare => [qw(Person)], |
130 | ); |
131 | |
132 | subtype Person() => ( # note parenthesis, "Person" is a function, not a string |
133 | as 'Object', |
134 | where { $_->can("name") }, |
135 | ); |
136 | |
23306f77 |
137 | =head3 Coerce in a subtype |
138 | |
9632a49e |
139 | Likewise use fully qualified subtypes of other types for defining coercions, so |
140 | that they won't affect unrelated code, causing action at a distance. |
141 | |
142 | This is important because the type registry is global, kind of like the symbol |
143 | table. |
144 | |
145 | This means that code like: |
146 | |
147 | # Bad style: |
148 | |
149 | coerce ArrayRef => ( |
150 | from Str => via { [ split /,/ ] }, |
151 | ); |
152 | |
153 | Will add a coercion to B<all> attributes like: |
154 | |
155 | has foo => ( |
156 | isa => "ArrayRef", |
157 | coerce => 1, |
158 | ); |
159 | |
160 | in a specific way. |
161 | |
d9fa4da9 |
162 | =head1 Clean up your package |
163 | |
164 | Use C<namespace::clean> or C<no Moose> to remove the sugar exports. |
165 | |
166 | This will make sure the sugar isn't accidentally called as methods on your objects. |
167 | |
168 | For instance: |
169 | |
170 | $obj->can("has"); |
171 | |
172 | will return true, even though C<has> is not a method. |
173 | |
9632a49e |
174 | |