Commit | Line | Data |
696cf5df |
1 | =pod |
2 | |
fd8a7262 |
3 | =head1 RECOMMENDATIONS |
4 | |
3bfacd05 |
5 | Moose has a lot of features, and there's definitely more than one way |
6 | to do it. However, we think that picking a subset of these features |
7 | and using them consistently makes everyone's life easier. |
8 | |
9 | Of course, as with any list of "best practices", these are really just |
10 | opinions. Feel free to ignore us. |
11 | |
12 | =head2 "No Moose" and Immutabilize |
fd8a7262 |
13 | |
14 | We recommend that you end your Moose class definitions by removing the |
15 | Moose sugar and making your class immutable. |
16 | |
17 | package Person; |
18 | |
19 | use Moose; |
20 | |
21 | # extends, roles, attributes, etc. |
22 | |
23 | # methods |
24 | |
25 | no Moose; |
26 | |
27 | __PACKAGE__->meta->make_immutable; |
28 | |
29 | 1; |
30 | |
3bfacd05 |
31 | The "no Moose" bit is simply good code hygiene, and making classes |
32 | immutable speeds up a lot of things, most notably object construction. |
33 | |
fd8a7262 |
34 | =head2 Always call SUPER::BUILDARGS |
35 | |
3bfacd05 |
36 | If you override the C<BUILDARGS> method in your class, make sure to |
37 | play nice and call C<SUPER::BUILDARGS> to handle cases you're not |
0f62a437 |
38 | checking for explicitly. |
3bfacd05 |
39 | |
40 | The default C<BUILDARGS> method in L<Moose::Object> handles both a |
41 | list and hashref of named parameters correctly, and also checks for a |
42 | I<non-hashref> single argument. |
43 | |
44 | =head2 Don't Use the initializer Feature |
45 | |
46 | Don't know what we're talking about? That's fine. |
47 | |
48 | =head2 Use builder Instead of default Most of the Time. |
49 | |
50 | Builders can be inherited, they have explicit names, and they're just |
51 | plain cleaner. |
52 | |
53 | However, I<do> use a default when the default is a non-reference, |
54 | I<or> when the default is simply an empty reference of some sort. |
55 | |
56 | Also, keep your builder methods private. |
fd8a7262 |
57 | |
3bfacd05 |
58 | =head2 Use lazy_build |
fd8a7262 |
59 | |
3bfacd05 |
60 | Lazy is good, and often solves initialization ordering problems. It's |
61 | also good for deferring work that may never have to be done. If you're |
62 | going to be lazy, use I<lazy_build> to save yourself some typing and |
63 | standardize names. |
fd8a7262 |
64 | |
3bfacd05 |
65 | =head2 Consider Keeping clearers & predicates Private |
fd8a7262 |
66 | |
3bfacd05 |
67 | Does everyone I<really> need to be able to clear an attribute? |
68 | Probably not. Don't expose this functionality outside your class |
69 | by default. |
b6477964 |
70 | |
3bfacd05 |
71 | Predicates are less problematic, but there's no reason to make your |
72 | public API bigger than it has to be. |
fd8a7262 |
73 | |
3bfacd05 |
74 | =head2 Default to read-only, and Consider Keeping writers Private |
fd8a7262 |
75 | |
3bfacd05 |
76 | Making attributes mutable just means more complexity to account for in |
77 | your program. The alternative to mutable state is to encourage users |
78 | of your class to simply make new objects as needed. |
fd8a7262 |
79 | |
3bfacd05 |
80 | If you I<must> make an attribute read-write, consider making the |
81 | writer a separate private method. Narrower APIs are easy to maintain, |
82 | and mutable state is trouble. |
b6477964 |
83 | |
541027c5 |
84 | =head2 Think Twice Before Changing an Attribute's Type in a Subclass |
85 | |
3bfacd05 |
86 | Down this path lies great confusion. If the attribute is an object |
87 | itself, at least make sure that it has the same interface as the type |
88 | of object in the parent class. |
89 | |
90 | =head2 Use MooseX::AttributeHelpers Instead of auto_deref |
91 | |
92 | The C<auto_deref> feature is a big troublesome. Directly exposing a |
93 | complex attribute is ugly. Instead, consider using |
94 | C<MooseX::AttributeHelpers> to define an API that exposes those pieces |
95 | of functionality that need exposing. Then you can expose just the |
96 | functionality that you want. |
541027c5 |
97 | |
98 | =head2 Namespace Your Types |
99 | |
3bfacd05 |
100 | Use some sort of namespacing convention for type names. We recommend |
101 | something like "MyApp.Type.Foo". I<Never> use "::" as the namespace |
102 | separator, since that overlaps with actual class names. |
541027c5 |
103 | |
104 | =head2 Coercion Instead of Unions |
105 | |
3bfacd05 |
106 | Consider using a type coercion instead of a type union. This was |
107 | covered at length in L<Moose::Manual::Types>. |
108 | |
541027c5 |
109 | =head2 Define All Your Types in One Module |
3bfacd05 |
110 | |
111 | Define all your types and coercions in one module. This was also |
112 | covered in L<Moose::Manual::Types>. |
113 | |
114 | =head1 AUTHOR |
115 | |
116 | Dave Rolsky E<lt>autarch@urth.orgE<gt> |
117 | |
118 | =head1 COPYRIGHT AND LICENSE |
119 | |
2840a3b2 |
120 | Copyright 2009 by Infinity Interactive, Inc. |
3bfacd05 |
121 | |
122 | L<http://www.iinteractive.com> |
123 | |
124 | This library is free software; you can redistribute it and/or modify |
125 | it under the same terms as Perl itself. |
126 | |
127 | =cut |