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