1MooseX::Role::ParameterUiszeerd:C:oTnuttroirbiuatle(d3M)PoeorsleXD:o:cRuomleen:t:aPtairoanmeterized::Tutorial(3)
2
3
4

NAME

6       MooseX::Role::Parameterized::Tutorial - why and how
7

MOTIVATION

9       Roles are composable units of behavior. They are useful for factoring
10       out functionality common to many classes from any part of your class
11       hierarchy. See Moose::Cookbook::Roles::Recipe1 for an introduction to
12       Moose::Role.
13
14       While combining roles affords you a great deal of flexibility,
15       individual roles have very little in the way of configurability. Core
16       Moose provides "alias" for renaming methods and "excludes" for ignoring
17       methods. These options are primarily (perhaps solely) for resolving
18       role conflicts. See Moose::Cookbook::Roles::Recipe2 for more about
19       "alias" and "excludes".
20
21       Because roles serve many different masters, they usually provide only
22       the least common denominator of functionality. To empower roles
23       further, more configurability than "alias" and "excludes" is required.
24       Perhaps your role needs to know which method to call when it is done.
25       Or what default value to use for its "url" attribute.
26
27       Parameterized roles offer a solution to these (and other) kinds of
28       problems.
29

USAGE

31       "with"
32
33       The syntax of a class consuming a parameterized role has not changed
34       from the standard "with". You pass in parameters just like you pass in
35       "alias" and "excludes" to ordinary roles:
36
37           with 'MyRole::InstrumentMethod' => {
38               method_name => 'dbh_do',
39               log_to      => 'query.log',
40           };
41
42       You can still combine parameterized roles. You just need to specify
43       parameters immediately after the role they belong to:
44
45           with (
46               'My::Parameterized::Role' => {
47                   needs_better_example => 1,
48               },
49               'My::Other::Role',
50           );
51
52       "parameter"
53
54       Inside your parameterized role, you specify a set of parameters. This
55       is exactly like specifying the attributes of a class. Instead of "has"
56       in Moose you use the keyword "parameter", but your parameters can use
57       any options to "has".
58
59           parameter 'delegation' => (
60               isa       => 'HashRef|ArrayRef|RegexpRef',
61               predicate => 'has_delegation',
62           );
63
64       You do have to declare what parameters you accept, just like you have
65       to declare what attributes you accept for regular Moose objects.
66
67       One departure from "has" is that we create a reader accessor for you by
68       default. In other words, we assume "is => 'ro'". If you do not want an
69       accessor, you can use "is => 'bare'".
70
71       "role"
72
73       "role" takes a block of code that will be used to generate your role
74       with its parameters bound. Here is where you declare components that
75       depend on parameters. You can declare attributes, methods, modifiers,
76       etc. The first argument to the "role" is an object containing the
77       parameters specified by "with". You can access the parameters just like
78       regular attributes on that object.
79
80       Each time you compose this parameterized role, the "role {}" block will
81       be executed. It will receive a new parameter object and produce an
82       entirely new role. That's the whole point, after all.
83
84       Due to limitations inherent in Perl, you must declare methods with
85       "method name => sub { ... }" instead of the usual "sub name { ... }".
86       Your methods may, of course, close over the parameter object. This
87       means that your methods may use parameters however they wish!
88

USES

90       Ideally these will become fully-explained examples in something
91       resembling Moose::Cookbook. But for now, only a braindump.
92
93       Configure a role's attributes
94           You can rename methods with core Moose, but now you can rename
95           attributes. You can now also choose type, default value, whether
96           it's required, traits, etc.
97
98               parameter traits => (
99                   isa     => 'ArrayRef',
100                   default => sub { [] },
101               );
102
103               parameter type => (
104                   isa     => 'Str',
105                   default => 'Any',
106               );
107
108               role {
109                   my $p = shift;
110
111                   has action => (
112                       traits => $p->traits,
113                       isa    => $p->type,
114                       ...
115                   );
116               }
117
118       Inform a role of your class' attributes and methods
119           Core roles can only require methods with specific names chosen by
120           the role. Now your roles can demand that the class specifies a
121           method name you wish the role to instrument, or which attributes to
122           dump to a file.
123
124               parameter instrument_method => (
125                   isa      => 'Str',
126                   required => 1,
127               );
128
129               role {
130                   my $p = shift;
131                   around $p->instrument_method => sub { ... };
132               }
133
134       Arbitrary execution choices
135           Your role may be able to provide configuration in how the role's
136           methods operate. For example, you can tell the role whether to save
137           intermediate states.
138
139               parameter save_intermediate => (
140                   isa     => 'Bool',
141                   default => 0,
142               );
143
144               role {
145                   my $p = shift;
146                   method process => sub {
147                       ...
148                       if ($p->save_intermediate) { ... }
149                       ...
150                   };
151               }
152
153       Deciding a backend
154           Your role may be able to freeze and thaw your instances using YAML,
155           JSON, Storable. Which backend to use can be a parameter.
156
157               parameter format => (
158                   isa     => (enum ['Storable', 'YAML', 'JSON']),
159                   default => 'Storable',
160               );
161
162               role {
163                   my $p = shift;
164                   if ($p->format eq 'Storable') {
165                       method freeze => \&Storable::freeze;
166                       method thaw   => \&Storable::thaw;
167                   }
168                   elsif ($p->format eq 'YAML') {
169                       method freeze => \&YAML::Dump;
170                       method thaw   => \&YAML::Load;
171                   }
172                   ...
173               }
174
175       Additional validation
176           Ordinary roles can require that its consumers have a particular
177           list of method names. Since parameterized roles have direct access
178           to its consumer, you can inspect it and throw errors if the
179           consumer does not meet your needs.
180
181               role {
182                   my $p    = shift;
183                   my %args = @_;
184                   my $consumer = $args{consumer};
185
186                   $consumer->find_attribute_by_name('stack')
187                       or confess "You must have a 'stack' attribute";
188
189                   my $push = $consumer->find_method_by_name('push')
190                       or confess "You must have a 'push' method";
191
192                   my $params = $push->parsed_signature->positional_params->params;
193                   @$params == 1
194                       or confess "Your push method must take a single parameter";
195
196                   $params->[0]->sigil eq '$'
197                       or confess "Your push parameter must be a scalar";
198
199                   ...
200               }
201
202
203
204perl v5.12.0                      2010-M0o1o-s0e6X::Role::Parameterized::Tutorial(3)
Impressum