POD fix (thanks arcanehl)
[gitmo/MooseX-Role-Parameterized.git] / lib / MooseX / Role / Parameterized / Tutorial.pm
1 package MooseX::Role::Parameterized::Tutorial;
2 confess "Don't use this module, read it!";
3
4 __END__
5
6 =head1 NAME
7
8 MooseX::Role::Parameterized::Tutorial - why and how
9
10 =head1 MOTIVATION
11
12 Roles are composable units of behavior. They are useful for factoring out
13 functionality common to many classes from any part of your class hierarchy.See
14 L<Moose::Cookbook::Roles::Recipe1> for an introduction to L<Moose::Role>.
15
16 While combining roles affords you a great deal of flexibility, individual roles
17 have very little in the way of configurability.  Core Moose provides C<alias>
18 for renaming methods to avoid conflicts, and C<excludes> for ignoring methods
19 you don't want or need (see L<Moose::Cookbook::Roles::Recipe2> for more
20 about C<alias> and C<excludes>).
21
22 Because roles serve many different masters, they usually provide only the least
23 common denominator of functionality. To empower roles further, more
24 configurability than C<alias> and C<excludes> is required. Perhaps your role
25 needs to know which method to call when it is done. Or what default value to
26 use for its url attribute.
27
28 Parameterized roles offer exactly this solution.
29
30 =head1 USAGE
31
32 =head3 C<with>
33
34 The syntax of a class consuming a parameterized role has not changed from the
35 standard C<with>. You pass in parameters just like you pass in C<alias> and
36 C<excludes> to ordinary roles:
37
38     with 'MyRole::InstrumentMethod' => {
39         method_name => 'dbh_do',
40         log_to      => 'query.log',
41     };
42
43 =head3 C<parameter>
44
45 Inside your parameterized role, you specify a set of parameters. This is
46 exactly like specifying the attributes of a class. Instead of C<has> you use
47 the keyword C<parameter>, but your parameters can use any options to C<has>.
48
49     parameter 'delegation' => (
50         is        => 'ro',
51         isa       => 'HashRef|ArrayRef|RegexpRef',
52         predicate => 'has_delegation',
53     );
54
55 Behind the scenes, C<parameter> uses C<has> to add attributes to a parameter
56 class. The arguments to C<with> are used to construct a parameter object, which
57 has the attributes specified by calls to C<parameter>. The parameter object is
58 then passed to...
59
60 =head3 C<role>
61
62 C<role> takes a block of code that will be used to generate your role with its
63 parameters bound. Here is where you declare parameterized components: use
64 C<has>, method modifiers, and so on. You receive as an argument the parameter
65 object constructed by C<with>. You can access the parameters just like regular
66 attributes on that object (assuming you declared them readable).
67
68 Each time you compose this parameterized role, the role {} block will be
69 executed. It will receive a new parameter object and produce an entirely new
70 role.
71
72 Due to limitations inherent in Perl, you must declare methods with
73 C<< method name => sub { ... } >> instead of the usual C<sub name { ... }>.
74 Your methods may, of course, close over the parameter object. This means that
75 your methods may use parameters however they wish!
76
77 =head1 IMPLEMENTATION NOTES
78
79 =head1 USES
80
81 Ideally these will become fully-explained examples in something resembling
82 L<Moose::Cookbook>. But for now, only a braindump.
83
84 =over 4
85
86 =item Configure a role's attributes
87
88 You can rename methods with core Moose, but now you can rename attributes. You
89 can now also choose type, default value, whether it's required, B<traits>, etc.
90
91     parameter traits => (
92         is      => 'ro',
93         isa     => 'ArrayRef[Str]',
94         default => sub { [] },
95     );
96
97     has action => (
98         traits => $p->traits,
99         ...
100     );
101
102 =item Inform a role of your class' attributes and methods
103
104 Core roles can require only methods with specific names. Now your roles can
105 require that you specify a method name you wish the role to instrument, or
106 which attributes to dump to a file.
107
108     parameter instrument_method => (
109         is       => 'ro',
110         isa      => 'Str',
111         required => 1,
112     );
113
114     around $p->instrument_method => sub { ... };
115
116 =item Arbitrary execution choices
117
118 Your role may be able to provide configuration in how the role's methods
119 operate. For example, you can tell the role whether to save intermediate
120 states.
121
122     parameter save_intermediate => (
123         is      => 'ro',
124         isa     => 'Bool',
125         default => 0,
126     );
127
128     method process => sub {
129         ...
130         if ($p->save_intermediate) { ... }
131         ...
132     };
133
134 =item Deciding a backend
135
136 Your role may be able to freeze and thaw your instances using L<YAML>, L<JSON>,
137 L<Storable>. Which backend to use can be a parameter.
138
139     parameter format => (
140         is => 'ro',
141         isa => (enum ['Storable', 'YAML', 'JSON']),
142         default => 'Storable',
143     );
144
145     if ($p->format eq 'Storable') {
146         method freeze => sub { ... };
147         method thaw   => sub { ... };
148     }
149     elsif ($p->format eq 'YAML') ...
150     ...
151
152 =back
153
154 =cut
155