Fix a small typo
[gitmo/moose-presentations.git] / moose-class / slides / index.html
CommitLineData
232c184d 1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
b751d33f 2
3<html xmlns="http://www.w3.org/1999/xhtml">
4
5<head>
6<title>Introduction to Moose</title>
55906a14 7<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
b751d33f 8<!-- metadata -->
9<meta name="generator" content="S5" />
10<meta name="version" content="S5 1.2a2" />
11<meta name="author" content="Eric A. Meyer" />
12<meta name="company" content="Complex Spiral Consulting" />
13<!-- configuration parameters -->
14<meta name="defaultView" content="slideshow" />
15<meta name="controlVis" content="hidden" />
16<!-- style sheet links -->
17<link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projection" id="slideProj" />
18<link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" />
19<link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" id="slidePrint" />
20<link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="projection" id="operaFix" />
21<!-- embedded styles -->
22<style type="text/css" media="all">
23.imgcon {width: 525px; margin: 0 auto; padding: 0; text-align: center;}
24#anim {width: 270px; height: 320px; position: relative; margin-top: 0.5em;}
25#anim img {position: absolute; top: 42px; left: 24px;}
26img#me01 {top: 0; left: 0;}
27img#me02 {left: 23px;}
28img#me04 {top: 44px;}
29img#me05 {top: 43px;left: 36px;}
30</style>
31<!-- S5 JS -->
32<script src="ui/default/slides.js" type="text/javascript"></script>
33<link rel="stylesheet" href="ui/custom.css" type="text/css" />
34</head>
35<body>
36
37<div class="layout">
38<div id="controls"><!-- DO NOT EDIT --></div>
39<div id="currentSlide"><!-- DO NOT EDIT --></div>
40<div id="header"></div>
41<div id="footer">
55906a14 42 <div id="license">
43 <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/us/88x31.png" /></a>
7167c54d 44 <br /><span xmlns:dc="http://purl.org/dc/elements/1.1/" href="http://purl.org/dc/dcmitype/Text" property="dc:title" rel="dc:type">Introduction to Moose</span> by <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">David Rolsky</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/">Creative Commons Attribution-Share Alike 3.0 United States License</a>.
55906a14 45 </div>
46
b751d33f 47 <h2>Introduction to Moose</h2>
48</div>
49</div>
50
51<div class="presentation">
52
53<div class="slide">
54 <h1>Introduction to Moose</h1>
55 <h2>YAPC 2009</h2>
56</div>
57
58<div class="slide">
59 <h1>Moose Summed Up</h1>
60
61 <ul>
62 <li><strong>Declarative</strong> OO sugar</li>
63 <li>Introspectable</li>
8d1ce1d7 64 <li>Extensible (MooseX::* on CPAN)</li>
b751d33f 65 </ul>
66</div>
67
68<div class="slide">
55906a14 69 <h1>Moose Background</h1>
b751d33f 70
71 <ul>
55906a14 72 <li>Created by Stevan Little, first released in 2006</li>
b751d33f 73 <li>Moose builds on Perl 5's native OO</li>
74 <li>Borrows ideas from other languages, notably Perl 6</li>
75 <li>Provides semantics for common operations</li>
76 </ul>
77</div>
78
55906a14 79<div class="slide fake-slide0">
80 <h1>Part 0: Moose Concepts</h1>
81</div>
82
b751d33f 83<div class="slide">
84 <h1>Classes</h1>
85
86 <ul>
87 <li>
88 Classes have ...
89 <ul>
90 <li>Attributes</li>
91 <li>Methods</li>
92 <li>Superclasses</li>
93 <li>Method modifiers</li>
94 <li>Constructor and destructor</li>
95 <li>One metaclass object</li>
96 </ul>
97 </li>
98 <li>Classes do roles</li>
99 </ul>
100</div>
101
102<div class="slide">
103 <h1>Class Example</h1>
104
105 <pre><code>package Person;
106<span class="highlight">use Moose;</span></code></pre>
107
108 <ul>
109 <li>Poof, a Moose-based class!</li>
110 </ul>
111</div>
112
113<div class="slide">
114 <h1>Attributes</h1>
115
116 <ul>
117 <li>Aka property, slot, field, member variable</li>
118 <li>A piece of data owned by an object</li>
119 </ul>
120</div>
121
122<div class="slide">
123 <h1>Attributes</h1>
124
125 <ul>
126 <li>
127 Attributes have ...
128 <ul>
129 <li>Access-control (read-only vs read-write)</li>
130 <li>An optional type</li>
131 <li>Accessor methods</li>
132 <li>Delegation methods</li>
133 <li>Optional default value</li>
134 <li>Many more features</li>
135 </ul>
136 </li>
137 <li>Stored in the object, but don't worry about that</li>
138 </ul>
139</div>
140
141<div class="slide">
142 <h1>Attribute Example</h1>
143
144 <pre><code>package Person;
145use Moose;
146
55906a14 147<span class="highlight">has first_name =&gt; ( is =&gt; 'rw' );</span></code></pre>
b751d33f 148
149</div>
150
151<div class="slide">
152 <h1>Methods</h1>
153
154 <ul>
155 <li>Nothing fancy here, just Perl subroutines</li>
156 </ul>
157
158 <pre><code>package Person;
159use Moose;
160
161<span class="highlight">sub greet { ... }</span></code></pre>
162</div>
163
164<div class="slide">
165 <h1>Roles</h1>
166
167 <ul>
168 <li>Classes <strong>do</strong> (or consume) roles</li>
169 <li>Similar to mixins and Java interfaces</li>
170 </ul>
171</div>
172
173<div class="slide">
174 <h1>Roles</h1>
175
176 <ul>
177 <li>Like classes, can have attributes, methods, do roles</li>
178 <li>Roles can require methods</li>
179 <li>Roles are composed (flattened) into classes</li>
180 </ul>
181</div>
182
183<div class="slide">
184 <h1>Role Example</h1>
185
186<pre><code>package HasPermissions;
187<span class="highlight">use Moose::Role;</span>
188
189has is_admin =&gt; ( is =&gt; 'rw' );</code></pre>
190</div>
191
192<div class="slide">
193 <h1>Role Example</h1>
194
195 <p>
196 And then ...
197 </p>
198
199<pre><code>package Person;
200use Moose;
201
202<span class="highlight">with 'HasPermissions';</span></code></pre>
203</div>
204
205<div class="slide">
206 <h1>Method Modifiers</h1>
207
208 <ul>
209 <li>AKA advice</li>
210 <li>&quot;<strong>Before</strong> foo(), do this first&quot;</li>
211 <li>&quot;Do this <strong>after</strong> foo()</li>
212 <li>&quot;Put this code <strong>around</strong> foo()&quot;</li>
213 </ul>
214</div>
215
216<div class="slide">
26164c8d 217 <h1>Before and After</h1>
b751d33f 218
219<pre><code>before 'foo'
220 =&gt; sub { warn 'About to call foo()' };
221
222after 'foo'
223 =&gt; sub { warn 'Leaving foo()' };</code></pre>
224
225</div>
226
227<div class="slide">
228 <h1>Around</h1>
229
230<pre><code>around 'foo' =&gt; sub {
231 my $real_foo = shift;
232 my $self = shift;
233
234 warn 'Just before foo()';
235 my @return =
236 $self-&gt;$real_foo( @_, bar =&gt; 42 );
237
238 return ( @return, 'modify return values' );
239};</code></pre>
240</div>
241
242<div class="slide">
243 <h1>Type Constraints</h1>
244
245 <ul>
246 <li>NOT A FULL-BLOWN TYPE SYSTEM!</li>
247 <li>But still darn useful</li>
248 <li>Constrain attribute values</li>
249 <li>Coerce from other types</li>
250 </ul>
251</div>
252
253<div class="slide">
254 <h1>Type Constraint Example</h1>
255
256<pre><code>package Person;
257use Moose;
258
55906a14 259has weight =&gt; (
260 is =&gt; 'ro',
261 <span class="highlight">isa =&gt; 'Int'</span>,
262);
b751d33f 263
264# kaboom
265Person-&gt;new( weight =&gt; 'fat' );</code></pre>
266</div>
267
268<div class="slide">
269 <h1>Delegation</h1>
270
271 <ul>
272 <li>Attributes can define delegations</li>
273 <li>Lets you hide some implementation details</li>
274 <li>Fewer objects to chase around</li>
275 </ul>
276</div>
277
278<div class="slide">
279 <h1>Delegation</h1>
280
281<pre><code>package Person;
282use Moose;
283
55906a14 284has blog_uri =&gt; (
b751d33f 285 is =&gt; 'rw',
286 isa =&gt; 'URI',
287 <span class="highlight">handles =&gt; { 'blog_hostname' =&gt; 'host' },</span>
288);
289
290<span class="highlight">$person->blog_hostname;</span>
55906a14 291# really calls $person->blog_uri->host</code></pre>
b751d33f 292</div>
293
294<div class="slide">
295 <h1>Constructors</h1>
296
297 <ul>
298 <li>Moose creates <code>new()</code> for you</li>
299 <li>Provide an optional <code>BUILDARGS()</code> and <code>BUILD()</code></li>
300 </ul>
301</div>
302
303<div class="slide">
304 <h1>Destructors</h1>
305
306 <ul>
307 <li>Provide an optional <code>DEMOLISH()</code></li>
308 </ul>
309</div>
310
311<div class="slide">
312 <h1>Moose Meta-API</h1>
313
314 <ul>
315 <li>Answers questions like ...
316 <ul>
317 <li>What methods does this class have?</li>
318 <li>What are its parents?</li>
319 <li>What attributes does it have (including inherited attributes)?</li>
320 <li>What roles does it do?</li>
321 <li>Much, much, more</li>
322 </ul>
323 </li>
324 </ul>
325</div>
326
327<div class="slide">
328 <h1>Moose Meta-API</h1>
329
330 <ul>
331 <li>Not just for introspection ...
332 <ul>
333 <li>Add methods, attributes, roles, etc</li>
334 <li>Extend and alter core features</li>
335 </ul>
336 </li>
337 </ul>
338</div>
339
340<div class="slide">
341 <h1>Why Moose?</h1>
342
343 <ul>
344 <li>A quick bit of propoganda ...</li>
345 </ul>
346</div>
347
348<div class="slide">
349 <h1>With Moose</h1>
350
351 <pre><code>package Person;
352use Moose;
353
354has last_name =&gt; (
355 is =&gt; 'rw',
356 isa =&gt; 'Str',
357);</code></pre>
358</div>
359
360<div class="slide">
361 <h1>Without Moose</h1>
362
363 <pre class="small"><code>package Person;
364use strict;
365use warnings;
366use Carp 'confess';
367
368sub new {
369 my $class = shift;
370 my %args = @_;
371 my $self = {};
372
373 if (exists $args{last_name}) {
374 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
375 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
376 if ref($args{last_name});
377 $self-&gt;{last_nane} = $args{last_name};
378 }
379
380 return bless $self, $class;
381}
382
383sub last_name {
384 my $self = shift;
385
386 if (@_) {
387 my $value = shift;
388 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
389 . &quot;Validation failed for 'Str' with value $value&quot;
390 if ref($value);
391 $self-&gt;{last_name} = $value;
392 }
393
394 return $self-&gt;{last_name};
395}</code></pre>
396
397</div>
398
399<div class="slide">
400 <h1>Side by side</h1>
401
402 <table class="side-by-side">
403 <tr>
404 <td>
405 <pre><code>package Person;
406use Moose;
407
408has last_name =&gt; (
409 is =&gt; 'rw',
410 isa =&gt; 'Str',
411);</code></pre>
412 </td>
413 <td>
414 <pre class="small"><code>package Person;
415use strict;
416use warnings;
417use Carp 'confess';
418
419sub new {
420 my $class = shift;
421 my %args = @_;
422 my $self = {};
423
424 if (exists $args{last_name}) {
425 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
426 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
427 if ref($args{last_name});
428 $self-&gt;{last_nane} = $args{last_name};
429 }
430
431 return bless $self, $class;
432}
433
434sub last_name {
435 my $self = shift;
436
437 if (@_) {
438 my $value = shift;
439 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
440 . &quot;Validation failed for 'Str' with value $value&quot;
441 if ref($value);
442 $self-&gt;{last_name} = $value;
443 }
444
445 return $self-&gt;{last_name};
446}</code></pre>
447 </td>
448 </tr>
449 </table>
450
451</div>
452
453<div class="slide">
454 <h1>Side by side</h1>
455
456 <table class="side-by-side">
457 <tr>
458 <td>
459 <pre><code><span class="match-moose">package Person;</span>
460use Moose;
461
462has last_name =&gt; (
463 is =&gt; 'rw',
464 isa =&gt; 'Str',
465);</code></pre>
466 </td>
467 <td>
468 <pre class="small"><code><span class="match-unsweet">package Person;</span>
469use strict;
470use warnings;
471use Carp 'confess';
472
473sub new {
474 my $class = shift;
475 my %args = @_;
476 my $self = {};
477
478 if (exists $args{last_name}) {
479 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
480 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
481 if ref($args{last_name});
482 $self-&gt;{last_nane} = $args{last_name};
483 }
484
485 return bless $self, $class;
486}
487
488sub last_name {
489 my $self = shift;
490
491 if (@_) {
492 my $value = shift;
493 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
494 . &quot;Validation failed for 'Str' with value $value&quot;
495 if ref($value);
496 $self-&gt;{last_name} = $value;
497 }
498
499 return $self-&gt;{last_name};
500}</code></pre>
501 </td>
502 </tr>
503 </table>
504</div>
505
506<div class="slide">
507 <h1>Side by side</h1>
508
509 <table class="side-by-side">
510 <tr>
511 <td>
512 <pre><code>package Person;
513<span class="match-moose">use Moose;</span>
514
515has last_name =&gt; (
516 is =&gt; 'rw',
517 isa =&gt; 'Str',
518);</code></pre>
519 </td>
520 <td>
521 <pre class="small"><code>package Person;
522<span class="match-unsweet">use strict;
523use warnings;
524use Carp 'confess';
525
526sub new {
527 my $class = shift;
528 my %args = @_;
529 my $self = {};</span>
530
531 if (exists $args{last_name}) {
532 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
533 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
534 if ref($args{last_name});
535 $self-&gt;{last_nane} = $args{last_name};
536 }
537
538 <span class="match-unsweet">return bless $self, $class;
539}</span>
540
541sub last_name {
542 my $self = shift;
543
544 if (@_) {
545 my $value = shift;
546 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
547 . &quot;Validation failed for 'Str' with value $value&quot;
548 if ref($value);
549 $self-&gt;{last_name} = $value;
550 }
551
552 return $self-&gt;{last_name};
553}</code></pre>
554 </td>
555 </tr>
556 </table>
557</div>
558
559<div class="slide">
560 <h1>Side by side</h1>
561
562 <table class="side-by-side">
563 <tr>
564 <td>
565 <pre><code>package Person;
566use Moose;
567
568<span class="match-moose">has last_name =&gt; (</span>
569 is =&gt; 'rw',
570 isa =&gt; 'Str',
571<span class="match-moose">);</span></code></pre>
572 </td>
573 <td>
574 <pre class="small"><code>package Person;
575use strict;
576use warnings;
577use Carp 'confess';
578
579sub new {
580 my $class = shift;
581 my %args = @_;
582 my $self = {};
583
584 <span class="match-unsweet">if (exists $args{last_name}) {</span>
585 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
586 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
587 if ref($args{last_name});
588 <span class="match-unsweet">$self-&gt;{last_nane} = $args{last_name};
589 }</span>
590
591 return bless $self, $class;
592}
593
594sub last_name {
595 my $self = shift;
596
597 if (@_) {
598 my $value = shift;
599 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
600 . &quot;Validation failed for 'Str' with value $value&quot;
601 if ref($value);
602 $self-&gt;{last_name} = $value;
603 }
604
605 return $self-&gt;{last_name};
606}</code></pre>
607 </td>
608 </tr>
609 </table>
610</div>
611
612<div class="slide">
613 <h1>Side by side</h1>
614
615 <table class="side-by-side">
616 <tr>
617 <td>
618 <pre><code>package Person;
619use Moose;
620
621has last_name =&gt; (
622 <span class="match-moose">is =&gt; 'rw',</span>
623 isa =&gt; 'Str',
624);</code></pre>
625 </td>
626 <td>
627 <pre class="small"><code>package Person;
628use strict;
629use warnings;
630use Carp 'confess';
631
632sub new {
633 my $class = shift;
634 my %args = @_;
635 my $self = {};
636
637 if (exists $args{last_name}) {
638 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
639 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
640 if ref($args{last_name});
641 $self-&gt;{last_nane} = $args{last_name};
642 }
643
644 return bless $self, $class;
645}
646
647<span class="match-unsweet">sub last_name {
648 my $self = shift;
649
650 if (@_) {
651 my $value = shift;</span>
652 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
653 . &quot;Validation failed for 'Str' with value $value&quot;
654 if ref($value);
655 <span class="match-unsweet">$self-&gt;{last_name} = $value;
656 }
657
658 return $self-&gt;{last_name};
659}</span></code></pre>
660 </td>
661 </tr>
662 </table>
663</div>
664
665<div class="slide">
666 <h1>Side by side</h1>
667
668 <table class="side-by-side">
669 <tr>
670 <td>
671 <pre><code>package Person;
672use Moose;
673
674has last_name =&gt; (
675 is =&gt; 'rw',
676 <span class="match-moose">isa =&gt; 'Str',</span>
677);</code></pre>
678 </td>
679 <td>
680 <pre class="small"><code>package Person;
681use strict;
682use warnings;
683use Carp 'confess';
684
685sub new {
686 my $class = shift;
687 my %args = @_;
688 my $self = {};
689
690 if (exists $args{last_name}) {
691 <span class="match-unsweet">confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
692 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
693 if ref($args{last_name});</span>
694 $self-&gt;{last_nane} = $args{last_name};
695 }
696
697 return bless $self, $class;
698}
699
700sub last_name {
701 my $self = shift;
702
703 if (@_) {
704 my $value = shift;
705 <span class="match-unsweet">confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
706 . &quot;Validation failed for 'Str' with value $value&quot;
707 if ref($value);</span>
708 $self-&gt;{last_name} = $value;
709 }
710
711 return $self-&gt;{last_name};
712}</code></pre>
713 </td>
714 </tr>
715 </table>
716</div>
717
718<div class="slide">
719 <h1>Side by side</h1>
720
721 <table class="side-by-side">
722 <tr class="incremental">
723 <td>5 lines</td>
724 <td>21 lines</td>
725 </tr>
726 <tr class="incremental">
727 <td>92 characters</td>
728 <td>741 characters</td>
729 </tr>
730 <tr>
731 <td>
732 <pre><code>package Person;
733use Moose;
734
735has last_name =&gt; (
736 is =&gt; 'rw',
737 isa =&gt; 'Str',
738);</code></pre>
739 </td>
740 <td>
741 <pre class="small"><code>package Person;
742use strict;
743use warnings;
744use Carp 'confess';
745
746sub new {
747 my $class = shift;
748 my %args = @_;
749 my $self = {};
750
751 if (exists $args{last_name}) {
752 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
753 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
754 if ref($args{last_name});
755 $self-&gt;{last_nane} = $args{last_name};
756 }
757
758 return bless $self, $class;
759}
760
761sub last_name {
762 my $self = shift;
763
764 if (@_) {
765 my $value = shift;
766 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
767 . &quot;Validation failed for 'Str' with value $value&quot;
768 if ref($value);
769 $self-&gt;{last_name} = $value;
770 }
771
772 return $self-&gt;{last_name};
773}</code></pre>
774 </td>
775 </tr>
776 </table>
777</div>
778
779<div class="slide">
780 <h1>Typo?</h1>
781
782 <pre class="small"><code>sub new {
783 my $class = shift;
784 my %args = @_;
785 my $self = {};
786
787 if (exists $args{last_name}) {
788 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
789 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
790 if ref($args{last_name});
791 $self-&gt;{last_nane} = $args{last_name};
792 }
793
794 return bless $self, $class;
795}</code></pre>
796</div>
797
798<div class="slide">
799 <h1>Typo?</h1>
800
801 <pre class="small"><code>if (exists $args{last_name}) {
802 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
803 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
804 if ref($args{last_name});
805 $self-&gt;{last_nane} = $args{last_name};
806}</code></pre>
807</div>
808
809<div class="slide">
810 <h1>Typo?</h1>
811
812 <code>$self-&gt;{last_nane} = $args{last_name};</code>
813</div>
814
815<div class="slide">
816 <h1>Typo?</h1>
8d1ce1d7 817 <code>$self-&gt;{last_na<span class="wrong">n</span>e}</code>
b751d33f 818</div>
819
820<div class="slide">
821 <h1>Why Moose?</h1>
822
823 <pre><code>package Person;
824use Moose;
825
826has last_name =&gt; (
827 is =&gt; 'rw',
828 isa =&gt; 'Str',
829);</code></pre>
830</div>
831
832<div class="slide fake-slide0">
ba1c9923 833 <h1>Part 1: Moose Classes</h1>
b751d33f 834</div>
835
836<div class="slide">
837 <h1>Moose Classes</h1>
838
839 <ul>
840 <li>Moose classes are Perl packages which <code>use Moose</code></li>
841 </ul>
842</div>
843
844<div class="slide">
845 <h1>Moose.pm and Your Class</h1>
846
847 <pre><code>package Person;
848use Moose;</code></pre>
849
850 <ul>
851 <li><code>Moose.pm</code> provides declarative sugar</li>
9b195048 852 <li>Turns on <code>strict</code> and <code>warnings</code></li>
b751d33f 853 <li>Creates metaclasses for your class: <code>Person-&gt;meta</code></li>
854 <li>Moose classes automatically inherit from <code>Moose::Object</code></li>
855 </ul>
856</div>
857
858<div class="slide">
859 <h1>What <code>Moose::Object</code> Provides</h1>
860
861 <ul>
862 <li>Constructor - <code>new()</code></li>
863 <li>Calls your <code>BUILDARGS()</code> and/or <code>BUILD()</code></li>
864 <li>Calls your <code>DEMOLISH</code> during object destruction</li>
865 </ul>
866</div>
867
868<div class="slide">
869 <h1>extends</h1>
870
871 <ul>
872 <li><code>extends</code> is sugar for declaring parent classes</li>
873 </ul>
874
875 <pre><code>package Employee;
876use Moose;
877<span class="highlight">extends 'Person';</span></code></pre>
878</div>
879
880<div class="slide">
881 <h1>extends</h1>
882
883 <ul>
884 <li>Each call to <code>extends</code> <strong>resets</strong> your parents</li>
885 </ul>
886
5d572684 887 <h2 class="wrong">Wrong</h2>
b751d33f 888
9b195048 889 <pre><code>package EvilEmployee;
b751d33f 890use Moose;
891extends 'Person';
55906a14 892extends 'Thief';</code></pre>
b751d33f 893
5d572684 894 <h2 class="right">Right</h2>
b751d33f 895
9b195048 896 <pre><code>package EvilEmployee;
b751d33f 897use Moose;
55906a14 898extends 'Person', 'Thief';</code></pre>
b751d33f 899</div>
900
901<div class="slide">
902 <h1>Extending un-Moose-y Parents</h1>
903
904 <pre><code>package My::LWP;
905use Moose;
55906a14 906extends 'LWP';</code></pre>
b751d33f 907
908 <ul>
909 <li>No <code>Moose::Object</code>, so ...
910 <ul>
911 <li>No attribute-handling <code>new()</code></li>
912 <li>No <code>BUILDARGS()</code> or <code>BUILD()</code></li>
913 <li>No <code>DEMOLISH()</code></li>
914 </ul>
915 </li>
916 <li>But see <code>MooseX::NonMoose</code> for a workaround</li>
917 </ul>
918</div>
919
920<div class="slide">
9b195048 921 <h1><code>overrides</code> and <code>super</code></h1>
922
923 <ul>
924 <li><code>overrides</code> is another method modifier</li>
925 <li>An alternative to Perl's <code>SUPER::</code></li>
926 </ul>
927</div>
928
929<div class="slide">
930 <h1><code>overrides</code> and <code>super</code></h1>
931
932 <pre><code>package Employee;
933use Moose;
934
26164c8d 935<span class="current incremental">extends 'Person';</span>
9b195048 936
937<span class="incremental">overrides</span> work =&gt; sub {
938 my $self = shift;
939
940 die "Pay me first" unless $self-&gt;got_paid;
941 <span class="incremental">super();</span>
942}<span class="incremental">;</span></code></pre>
55906a14 943</div>
9b195048 944
945<div class="slide">
946 <h1>Caveat <code>super</code></h1>
947
948 <ul>
949 <li>Mostly like <code>$self-&gt;SUPER::work(@_)</code></li>
950 <li><strong>But</strong> cannot change <code>@_</code>!</li>
951 <li>Binds the parent's method at compile time</li>
952 </ul>
953</div>
954
955<div class="slide">
e43c4c2a 956 <h1>Minimal Attributes</h1>
9b195048 957
958 <ul>
959 <li><code>has 'foo'</code></li>
960 <li>Use <code>is =&gt; 'ro'</code> or <code>is =&gt; 'rw'</code></li>
961 <li>Attributes without "is" have no accessors</li>
962 </ul>
963</div>
964
965<div class="slide">
966 <h1>Read-write attributes</h1>
967
968 <pre><code>package Person;
969use Moose;
970
55906a14 971has first_name =&gt; ( <span class="highlight">is =&gt; 'rw'</span> );
9b195048 972
973my $person =
974 Person-&gt;new( first_name =&gt; 'Dave' );
975
976$person-&gt;first_name('Stevan');
977print $person-&gt;first_name; # Stevan</code></pre>
978
979</div>
980
981<div class="slide">
982 <h1>Read-only attributes</h1>
983
984 <pre><code>package Person;
985use Moose;
986
55906a14 987has first_name =&gt; ( <span class="highlight">is =&gt; 'ro'</span> );
9b195048 988
989my $person =
990 Person-&gt;new( first_name =&gt; 'Dave' );
991
992$person-&gt;first_name('Stevan');
993print $person-&gt;first_name; # Dave</code></pre>
994
995</div>
996
997<div class="slide">
998 <h1>There is More to Come</h1>
999
1000 <ul>
1001 <li>Attributes have a <em>lot</em> of features</li>
1002 </ul>
1003</div>
1004
1005<div class="slide">
b751d33f 1006 <h1>Cleaning Up Moose Droppings</h1>
1007
1008 <pre><code>package Person;
1009use Moose;
1010
1011# true
1012Person->can('extends');</code></pre>
1013
1014 <ul>
1015 <li>Not very hygienic</li>
1016 </ul>
1017</div>
1018
1019<div class="slide">
1020 <h1>Cleaning Up Moose Droppings</h1>
1021
1022 <pre><code>package Person;
1023use Moose;
1024
1025...
1026
1027no Moose;
1028
1029# false
1030Person->can('extends');</code></pre>
1031</div>
1032
1033<div class="slide">
1034 <h1>No Moose</h1>
1035
1036 <ul>
1037 <li><code>no Moose</code> at the end of a package is a best practice</li>
1038 <li>Just do it</li>
1039 </ul>
1040</div>
1041
1042<div class="slide">
1043 <h1>Immutability</h1>
1044
1045 <ul>
1046 <li><span style="font-family: URW Chancery L; font-size: 140%">Stevan's Incantation of Fleet-Footedness</span></li>
1047 </ul>
1048
1049 <pre><code>package Person;
1050use Moose;
1051
1052<span class="highlight">__PACKAGE__->meta->make_immutable;</span></code></pre>
1053</div>
1054
9b195048 1055<div class="slide">
1056 <h1>What <code>make_immutable</code> does</h1>
1057
1058 <ul>
1059 <li>Magic</li>
1060 <li>Uses <code>eval</code> to "inline" a constructor</li>
1061 <li>Memoizes a lot of meta-information</li>
1062 <li>Makes loading your class slower</li>
1063 <li>Makes object creation <em>much</em> faster</li>
1064 </ul>
1065</div>
1066
1067<div class="slide">
1068 <h1>When to Immutabilize?</h1>
1069
1070 <ul>
1071 <li><em>Almost</em> always</li>
1072 <li>Startup time vs execution time</li>
1073 </ul>
1074</div>
1075
ddd87d75 1076<div class="slide">
55906a14 1077 <h1>Classes Summary</h1>
1078
1079 <ul>
1080 <li><code>use Moose</code></li>
1081 <li><code>Class-&gt;meta</code></li>
1082 <li><code>Moose::Object</code> base class</li>
1083 <li><code>extends</code>, <code>overrides</code>, and <code>super</code></li>
1084 <li>Simple attributes: <code>has</code>, <code>is&nbsp;=&gt;&nbsp;'ro'</code>, &amp; <code>is&nbsp;=&gt;&nbsp;'rw'</code></li>
1085 <li><code>no Moose</code></li>
1086 <li><code>__PACKAGE__-&gt;meta-&gt;make_immutable</code></li>
1087 </ul>
1088</div>
1089
1090<div class="slide">
26164c8d 1091 <h1>Questions?</h1>
1092</div>
1093
1094<div class="slide">
ba1c9923 1095 <h1>Exercises</h1>
ddd87d75 1096
8d1ce1d7 1097 <pre># cd exercises
ba1c9923 1098$ perl bin/prove -lv t/00-prereq.t
ddd87d75 1099
1100Missing anything? Install it. (see tarballs/)
1101
ba1c9923 1102# perl bin/prove -lv t/01-classes.t
1103
55906a14 1104Iterate til this passes all its tests</pre>
1105</div>
1106
1107<div class="slide fake-slide0">
1108 <h1>Part 2: Roles</h1>
1109</div>
1110
1111<div class="slide">
1112 <h1>Just What Is a Role?</h1>
1113
1114 <ul>
1115 <li>Mixin? Interface? Trait?</li>
1116 <li>Yes ... and more!</li>
1117 </ul>
1118</div>
1119
1120<div class="slide">
1121 <h1>Roles Can Have State <strong>and</strong> Behavior</h1>
1122
1123 <pre><code>package HasPermissions;
1124use Moose::Role;
1125
26164c8d 1126<span class="current incremental"># state
55906a14 1127has access_level =&gt; ( is =&gt; 'rw' );</span>
1128
1129<span class="incremental"># behavior
1130sub can_access {
1131 my $self = shift;
1132 my $required = shift;
1133
1134 return $self-&gt;access_level &gt;= $required;
1135}</span></code></pre>
1136
1137</div>
1138
1139<div class="slide">
1140 <h1>Roles Can Define Interfaces</h1>
1141
1142 <pre><code>package Printable;
1143use Moose::Role;
1144
1145requires 'as_string';</code></pre>
1146</div>
1147
1148<div class="slide">
1149 <h1>Roles Can Do All Three</h1>
1150
1151 <pre><code>package Printable;
1152use Moose::Role;
1153
1154requires 'as_string';
1155
1156has has_been_printed =&gt; ( is =&gt; 'rw' );
1157
1158sub print {
1159 my $self = shift;
1160 print $self-&gt;as_string;
1161 $self-&gt;has_been_printed(1);
1162}</code></pre>
1163</div>
1164
1165<div class="slide">
1166 <h1>Classes Consume Roles</h1>
1167
1168 <pre><code>package Person;
1169use Moose;
1170
1171with 'HasPermissions';</code></pre>
1172</div>
1173
1174<div class="slide">
1175 <h1>Classes Consume Roles</h1>
1176
1177<pre><code>my $person = Person-&gt;new(
1178 first_name => 'Kenichi',
1179 last_name => 'Asai',
1180 access_level =&gt; 42,
1181);
1182
1183print $person-&gt;full_name
1184 . ' has '
1185 . $person-&gt;can_access(42)
1186 ? 'great power'
1187 : 'little power';</code></pre>
1188</div>
1189
1190<div class="slide">
1191 <h1>Roles in Practice</h1>
1192
1193 <ul>
1194 <li>Consuming a role =~ inlining the role</li>
1195 </ul>
1196</div>
1197
1198<div class="slide">
1199 <h1>In Other Words ...</h1>
1200
1201<pre><code>package Person;
1202use Moose;
1203
1204<span class="highlight">with 'Printable';</span></code></pre>
1205</div>
1206
1207<div class="slide">
1208 <h1>In Other Words ...</h1>
1209
1210<pre><code>package Person;
1211use Moose;
1212
1213<span class="delete">with 'Printable';</span>
1214
1215<span class="highlight">has has_been_printed =&gt; ( is =&gt; 'rw' );
1216
1217sub print {
1218 my $self = shift;
1219 print $self-&gt;as_string;
1220 $self-&gt;has_been_printed(1);
1221}</span></code></pre>
1222</div>
1223
1224<div class="slide">
1225 <h1>Except</h1>
1226
1227 <ul>
1228 <li>Role consumption is introspectable</li>
1229 </ul>
1230
1231 <pre><code>if ( Person-&gt;does('Printable') ) { ... }
1232
1233# or ...
1234
1235if ( Person-&gt;meta-&gt;does('Printable') ) { ... }</code></pre>
1236
1237</div>
1238
1239<div class="slide">
1240 <h1>These Names Are the Same</h1>
1241
1242 <ul>
1243 <li>What if a role and class define the same method?</li>
1244 <li>A class's <em>local</em> methods win over the role's</li>
1245 <li>The role's methods win over the class's <em>inherited</em> methods</li>
1246 </ul>
1247</div>
1248
1249<div class="slide">
1250 <h1>Conflicts Between Roles</h1>
1251
1252 <ul>
1253 <li>Two roles with a method of the same name</li>
1254 <li>Generates a compile-time error when consumed by a class</li>
1255 </ul>
1256</div>
1257
1258<div class="slide">
1259 <h1>Conflict Example</h1>
1260
1261 <pre><code>package IsFragile;
1262use Moose::Role;
1263
1264sub break { ... }
1265
1266package CanBreakdance;
1267use Moose::Role;
1268
1269sub break { ... }</code></pre>
1270</div>
1271
1272<div class="slide">
1273 <h1>Conflict Example</h1>
1274
1275 <pre><code>package FragileDancer;
1276use Moose;
1277
1278<span class="highlight">with 'IsFragile', 'CanBreakdance';</span></code></pre>
1279
1280 <ul>
1281 <li>Only one <code>with</code>!</li>
1282 </ul>
1283</div>
1284
1285<div class="slide">
1286 <h1>Conflict Resolution</h1>
1287
1288 <ul>
1289 <li>The consuming class must resolve the conflict by implementing th emethod</li>
1290 <li>Can use some combination of method exclusion and aliasing</li>
1291 </ul>
1292</div>
1293
1294<div class="slide">
1295 <h1>Method Aliasing</h1>
1296
1297 <pre><code>package FragileDancer;
1298use Moose;
1299
1300<span class="highlight">with 'IsFragile' =>
1301 { alias =>
1302 { break => 'break_bone' } },
1303 'CanBreakdance' =>
1304 { alias =>
1305 { break => 'break_it_down' } };</span></code></pre>
1306
1307 <ul>
1308 <li>Renames the roles' methods</li>
1309 <li>Still conflicts, need to <code>exclude</code> as well</li>
1310 </ul>
1311</div>
1312
1313<div class="slide">
1314 <h1>Method Exclusion</h1>
1315
1316 <pre><code>package FragileDancer;
1317use Moose;
1318
1319<span class="highlight">with 'IsFragile' =>
1320 { alias =>
1321 { break => 'break_bone' },
1322 exclude => 'break' },
1323 'CanBreakdance' =>
1324 { alias =>
1325 { break => 'break_dance' },
1326 exclude => 'break' };</span></code></pre>
1327</div>
1328
1329<div class="slide">
1330 <h1>And then ...</h1>
1331
1332 <pre><code>package FragileDancer;
1333use Moose;
ddd87d75 1334
55906a14 1335sub break {
1336 my $self = shift;
1337
1338 $self->break_dance;
232c184d 1339 if ( rand(1) &lt; 0.5 ) {
55906a14 1340 $self->break_bone;
1341 }
1342}</code></pre>
1343</div>
1344
1345<div class="slide">
1346 <h1>Still Full of Fail</h1>
1347
1348 <ul>
1349 <li>Roles are also about semantics!</li>
1350 <li>We've fulfilled the letter and lost the spirit</li>
1351 <li>Roles have a <em>meaning</em></li>
1352 <li>Think twice before blindly aliasing and excluding methods!</li>
1353 </ul>
1354</div>
1355
1356<div class="slide">
1357 <h1>Hot Role-on-Role Action</h1>
1358
1359 <pre><code>package Comparable;
1360use Moose::Role;
1361
1362requires 'compare';</code></pre>
1363</div>
1364
1365<div class="slide">
1366 <h1>Hot Role-on-Role Action</h1>
1367
1368 <pre><code>package TestsEquality;
1369use Moose::Role;
1370
1371with 'Comparable';
1372
1373sub is_equal {
1374 my $self = shift;
1375 return $self->compare(@_) == 0;
1376}</code></pre>
1377</div>
1378
1379<div class="slide">
1380 <h1>And then ...</h1>
1381
1382 <pre><code>package Integer;
1383use Moose;
1384
1385with 'TestsEquality';
1386
1387# Satisfies the Comparable role
1388sub compare { ... }
1389
1390Integer->does('TestsEquality'); # true
1391Integer->does('Comparable'); # also true!</code></pre>
1392</div>
1393
1394<div class="slide">
1395 <h1>Name Conflicts Between Roles</h1>
1396
1397 <pre><code>package HasSubProcess;
1398use Moose::Role;
1399
1400<span class="highlight">sub execute { ... }</span>
1401
1402package Killer;
1403use Moose::Role;
1404
1405with 'HasSubProcess';
1406
1407<span class="highlight">sub execute { ... }</span></code></pre>
1408</div>
1409
1410<div class="slide">
1411 <h1>Delayed Conflict</h1>
1412
1413 <pre><code>package StateOfTexas;
1414with 'Killer';</code></pre>
1415
1416 <ul>
1417 <li><code>StateOfTexas</code> must implement its own <code>execute</code></li>
1418 <li>But loading the <code>Killer</code> role by itself does not cause an error</li>
1419 </ul>
1420</div>
1421
1422<div class="slide">
1423 <h1>Roles as Interfaces</h1>
1424
1425 <ul>
1426 <li>Roles can <code>require</code> methods of their consumers</li>
1427 <li>Compile-time checks</li>
1428 <li>Method must exist when the role is consumed</li>
1429 </ul>
1430</div>
1431
1432<div class="slide">
1433 <h1>The Attribute Gotcha</h1>
1434
1435<pre><code>package HasSize;
1436use Moose::Role;
1437
26164c8d 1438<span class="current incremental">requires 'size';</span>
55906a14 1439
1440package Shirt;
1441use Moose;
1442
1443<span class="incremental">with 'HasSize';
1444
1445has size => ( is => 'ro' );</span></code></pre>
1446</div>
1447
1448<div class="slide">
1449 <h1>The Attribute Gotcha Workaround</h1>
1450
1451 <pre><code>package HasSize;
1452use Moose::Role;
1453
1454requires 'size';
1455
1456package Shirt;
1457use Moose;
1458
1459has size => ( is => 'ro' );
1460
1461with 'HasSize';</code></pre>
1462</div>
1463
1464<div class="slide">
1465 <h1>Compile-time Is a Lie</h1>
1466
1467 <ul>
1468 <li>Really, it's <em>package load</em> time</li>
1469 <li>That's run-time, but before the "real" run-time</li>
1470 <li>Moose does not rewire Perl, it's just sugar!</li>
1471 <li>(but <code>MooseX::Declare</code> <em>does</em> rewire Perl)</li>
1472 </ul>
1473</div>
1474
1475<div class="slide">
1476 <h1>Enforcing Roles</h1>
1477
1478 <pre><code>package Comparison;
1479use Moose;
1480
1481has [ 'left', 'right' ] => (
1482 is => 'ro',
1483 <span class="highlight">does => 'Comparable',</span>
1484);
1485</code></pre>
1486
1487 <ul>
1488 <li>A sneak peek at type constraints</li>
1489 </ul>
1490</div>
1491
1492
1493<div class="slide">
1494 <h1>Roles Can Be Applied to Objects</h1>
1495
1496 <pre><code>use Moose::Util qw( apply_all_roles );
1497
1498my $fragile_person = Person->new( ... );
1499apply_all_roles( $fragile_person, 'IsFragile' );</code></pre>
1500
1501 <ul>
1502 <li>Does not change the <code>Person</code> class</li>
1503 <li>Works with non-Moose classes, great for monkey-patching!</li>
1504 </ul>
1505</div>
1506
1507<div class="slide">
1508 <h1>Roles Are Dirty Too</h1>
1509
1510 <ul>
1511 <li>Once again, clean up those Moose droppings</li>
1512 </ul>
1513
1514 <pre><code>package Comparable;
1515use Moose::Role;
1516
1517requires 'compare';
1518
1519<span class="highlight">no Moose::Role;</span></code></pre>
1520
1521 <ul>
1522 <li>But roles cannot be made immutable</li>
1523 </ul>
1524</div>
1525
1526<div class="slide">
1527 <h1>The Zen of Roles</h1>
1528
1529 <ul>
1530 <li>Roles represent discrete units of ...
1531 <ul>
1532 <li>state</li>
1533 <li>behavior</li>
1534 <li>interface</li>
1535 </ul>
1536 </li>
1537 <li>Roles are shareable between unrelated classes</li>
1538 <li>Roles are what a class <em>does</em>, not what it <em>is</em></li>
1539 <li>Roles <em>add</em> functionality, inheritance <em>specializes</em></li>
1540 </ul>
1541</div>
1542
1543<div class="slide">
1544 <h1>Abstract Examples</h1>
1545
1546 <ul>
1547 <li>Human <em>@ISA</em> Animal</li>
1548 <li>Human <em>does</em> Toolmaker (as <em>does</em> Chimpanzee)</li>
1549 <li>Car <em>@ISA</em> Vehicle</li>
1550 <li>Car <em>does</em> HasEngine</li>
1551 </ul>
1552</div>
1553
1554<div class="slide">
1555 <h1>Real Examples</h1>
1556
1557 <ul>
1558 <li>Objects representing SQL database components and queries
1559 <ul>
1560 <li>Schema, Table, Column, ColumnAlias</li>
1561 <li>Select, Insert, Update, Delete</li>
1562 </ul>
1563 </li>
1564 </ul>
1565</div>
1566
1567<div class="slide">
1568 <h1>Real Examples</h1>
1569
1570 <ul>
1571 <li>Column and ColumnAlias both <em>do</em> ColumnLike</li>
1572 <li>ColumnLike things can be used in certain parts of queries</li>
1573 <li>All queries <em>do</em> HasWhereClause</li>
1574 <li>Select <em>does</em> Comparable and Selectable (for subselects)</li>
1575 <li>A where clause requires its components to <em>do</em> Comparable</li>
1576 </ul>
1577</div>
1578
1579<div class="slide">
26164c8d 1580 <h1>Roles Summary</h1>
1581
1582 <ul>
1583 <li>Roles can define an interface with <code>requires</code></li>
1584 <li>Roles can have state (attributes) and behavior (methods)</li>
1585 <li>Roles can mix interface, state, &amp; behavior</li>
1586 <li>Roles are composed (flattened) into classes</li>
1587 <li>Roles can do other roles</li>
1588 <li>Roles can be used as a type in APIs (must do Comparable)</li>
1589 </ul>
1590</div>
1591
1592<div class="slide">
1593 <h1>Questions?</h1>
1594</div>
1595
1596<div class="slide">
55906a14 1597 <h1>Exercises</h1>
1598
8d1ce1d7 1599 <pre># cd exercises
55906a14 1600# perl bin/prove -lv t/02-roles.t
1601
1602Iterate til this passes all its tests</pre>
1603</div>
1604
8d1ce1d7 1605<div class="slide fake-slide0">
1606 <h1>Part 3: Basic Attributes</h1>
1607</div>
1608
1609<div class="slide">
1610 <h1>Attributes Are Huge</h1>
1611
1612 <ul>
1613 <li>Moose's biggest feature</li>
1614 <li>The target of <em>many</em> MooseX modules</li>
1615 </ul>
1616</div>
1617
1618<div class="slide">
1619 <h1>Quick Review</h1>
1620
1621 <ul>
1622 <li>Declared with <code>has</code></li>
1623 <li>Read-only or read-write</li>
1624 </ul>
1625
1626 <pre><code>package Shirt;
1627use Moose;
1628
1629has 'color' =&gt; ( is =&gt; 'ro' );
1630has 'is_ripped' =&gt; ( is =&gt; 'rw' );</code></pre>
1631</div>
1632
1633<div class="slide">
1634 <h1>Required-ness</h1>
1635
1636 <ul>
1637 <li>Required means "must be passed to the constructor"</li>
1638 <li>But can be <code>undef</code></li>
1639 </ul>
1640</div>
1641
1642<div class="slide">
1643 <h1>Required-ness</h1>
1644
1645 <pre><code>package Person;
1646use Moose;
1647
1648has first_name =&gt; (
1649 is =&gt; 'ro',
26164c8d 1650 <span class="current incremental">required =&gt; 1,</span>
8d1ce1d7 1651);
1652
1653<span class="incremental">Person->new( first_name =&gt; undef ); # ok
1654Person->new(); # kaboom</span></code></pre>
1655</div>
1656
1657<div class="slide">
1658 <h1>Default and Builder</h1>
1659
1660 <ul>
1661 <li>Attributes can have defaults</li>
1662 <li>Simple non-referecne scalars (number, string)</li>
1663 <li>Subroutine reference</li>
1664 <li>A builder method</li>
1665 </ul>
1666</div>
1667
1668<div class="slide">
1669 <h1>Default</h1>
1670
1671 <ul>
1672 <li>Can be a non-reference scalar (including <code>undef</code>)</li>
1673 </ul>
1674
1675 <pre><code>package Person;
1676use Moose;
1677
1678has bank =&gt; (
1679 is =&gt; 'rw',
1680 default =&gt; 'Spire FCU',
1681);</code></pre>
1682</div>
1683
1684<div class="slide">
1685 <h1>Default</h1>
1686
1687 <ul>
1688 <li>Can be a subroutine reference</li>
1689 </ul>
1690
1691 <pre><code>package Person;
1692use Moose;
1693
1694has bank =&gt; (
1695 is =&gt; 'rw',
1696 default =&gt;
1697 sub { Bank-&gt;new(
1698 name =&gt; 'Spire FCU' ) },
1699);</code></pre>
1700</div>
1701
1702<div class="slide">
1703 <h1>Default as a Subroutine Reference</h1>
1704
1705 <ul>
1706 <li>Called as a method on the object</li>
1707 <li>Called anew for each object</li>
1708 </ul>
1709</div>
1710
1711<div class="slide">
1712 <h1>Why No Other Reference Types?</h1>
1713
1714 <pre><code>package Person;
1715use Moose;
1716
1717has bank =&gt; (
1718 is =&gt; 'rw',
1719 <span class="wrong">default =&gt; Bank-&gt;new(
1720 name =&gt; 'Spire FCU' ),</span>
1721);</code></pre>
1722
1723 <ul>
1724 <li>Now <strong>every</strong> person shares the <strong>same</strong> Bank object!</li>
1725 </ul>
1726</div>
1727
1728<div class="slide">
1729 <h1>Defaulting to an Empty Reference</h1>
1730
1731 <pre><code>package Person;
1732use Moose;
1733
1734has packages =&gt; (
1735 is =&gt; 'rw',
1736 default =&gt; <span class="highlight">sub { [] }</span>,
1737);</code></pre>
1738</div>
1739
1740<div class="slide">
1741 <h1>What if I Want to Share?</h1>
1742
1743 <pre><code>package Person;
1744use Moose;
1745
1746my $highlander_bank =
1747 Bank-&gt;new( name =&gt; 'Spire FCU' );
1748
1749has bank =&gt; (
1750 is =&gt; 'rw',
1751 default =&gt; sub { $highlander_bank },
1752);</code></pre>
1753</div>
1754
1755<div class="slide">
1756 <h1>Builder</h1>
1757
1758 <ul>
1759 <li>A method <em>name</em> which returns the default</li>
1760 </ul>
1761</div>
1762
1763<div class="slide">
1764 <h1>Builder</h1>
1765
1766 <pre><code>package Person;
1767use Moose;
1768
1769has bank =&gt; (
1770 is =&gt; 'rw',
1771 builder =&gt; '_build_bank',
1772);
1773
1774sub _build_bank {
1775 my $self = shift;
1776 return Bank-&gt;new( name => 'Spire FCU' );
1777}</code></pre>
1778</div>
1779
1780<div class="slide">
1781 <h1>Default vs Builder</h1>
1782
1783 <ul>
1784 <li>Use default for simple scalars</li>
1785 <li>Use default to return empty references</li>
1786 <li>Use default for <em>very</em> trivial subroutine references</li>
1787 <li>Use builder for everything else</li>
1788 </ul>
1789</div>
1790
1791<div class="slide">
1792 <h1>Builder Bonuses</h1>
1793
1794 <ul>
1795 <li>Can be overridden and method modified, because it's called by <em>name</em></li>
1796 <li>Roles can require a builder</li>
1797 </ul>
1798</div>
1799
1800<div class="slide">
1801 <h1>Role Requires Builder</h1>
1802
1803 <pre><code>package HasBank;
1804use Moose::Role;
1805
1806requires '_build_bank';
1807
1808has bank =&gt; (
1809 is =&gt; 'ro',
1810 builder =&gt; '_build_bank',
1811);</code></pre>
1812</div>
1813
1814<div class="slide">
1815 <h1>Lazy, Good for Nothing Attributes</h1>
1816
1817 <ul>
1818 <li>Normally, defaults are generated during object construction</li>
1819 <li>This can be expensive</li>
1820 <li>We want to default to <code>$self-&gt;size * 2</code>, but attribute initialization order is unpredictable</li>
1821 <li>Use lazy attributes!</li>
1822 </ul>
1823</div>
1824
1825<div class="slide">
1826 <h1>The Power of Dynamic Defaults</h1>
1827
1828 <pre><code>package Person;
1829use Moose;
1830
1831has shoe_size =&gt; (
1832 is =&gt; 'ro',
1833);</code></pre>
1834</div>
1835
1836<div class="slide">
1837 <h1>The Power of Dynamic Defaults</h1>
1838
1839 <pre><code>has shoes =&gt; (
1840 is =&gt; 'ro',
1841 <span class="highlight">lazy =&gt; 1,</span>
1842 builder => '_build_shoes',
1843);
1844
1845sub _build_shoes {
1846 my $self = shift;
1847
1848 return Shoes-&gt;new(
1849 size =&gt; <span class="highlight">$_[0]-&gt;shoe_size</span> );
1850}</code></pre>
1851</div>
1852
1853<div class="slide">
1854 <h1>Lazy is Good</h1>
1855
1856 <ul>
1857 <li>Lazy defaults are executed when the attribute is read</li>
1858 <li>Can see other object attributes</li>
1859 <li>Still need to watch out for circular laziness</li>
1860 </ul>
1861</div>
1862
1863<div class="slide">
1864 <h1>Clearer and Predicate</h1>
1865
1866 <ul>
1867 <li>Attributes can have a value, including <code>undef</code>, or not</li>
1868 <li>Can clear the value with a clearer method</li>
1869 <li>Can check for the existence of a value with a predicate method</li>
1870 <li>By default, these methods are not created</li>
1871 </ul>
1872</div>
1873
1874<div class="slide">
1875 <h1>Clearer and Predicate</h1>
1876
1877 <pre><code>package Person;
1878use Moose;
1879
1880has account =&gt; (
1881 is =&gt; 'ro',
1882 lazy =&gt; 1,
1883 builder =&gt; '_build_account',
1884 <span class="highlight">clearer =&gt; '_clear_account',
1885 predicate =&gt; 'has_account',</span>
1886);</code></pre>
1887</div>
1888
1889<div class="slide">
1890 <h1>Clearer and Lazy Defaults</h1>
1891
1892 <ul>
1893 <li>Lazy defaults are good for computed attributes</li>
1894 <li>Clear the attribute when the source data changes</li>
1895 <li>Recalculated at next access</li>
1896 </ul>
1897</div>
1898
1899<div class="slide">
1900 <h1>Renaming constructor arguments</h1>
1901
1902 <ul>
1903 <li>By default, constructor names = attribute names</li>
1904 <li>Use <code>init_arg</code> to change this</li>
1905 <li>Set <code>init_arg =&gt; undef</code> to make it unconstructable</li>
1906 </ul>
1907</div>
1908
1909<div class="slide">
1910 <h1>Some <code>init_arg</code> examples</h1>
1911
1912 <pre><code>package Person;
1913use Moose;
1914
1915has shoe_size => (
1916 is =&gt; 'ro',
1917 <span class="highlight">init_arg =&gt; 'foot_size',</span>
1918);
1919
1920Person->new( <span class="wrong">shoe_size =&gt; 13</span> );
1921
1922my $person =
1923 Person->new( <span class="right">foot_size =&gt; 13</span> );
1924print $person->shoe_size;</code></pre>
1925</div>
1926
1927<div class="slide">
1928 <h1>Some <code>init_arg</code> examples</h1>
1929
1930<pre><code>package Person;
1931use Moose;
1932
1933has shoes => (
1934 is =&gt; 'ro',
1935 <span class="highlight">init_arg =&gt; undef,</span>
1936);
1937
1938Person->new( <span class="wrong">shoes =&gt; Shoes-&gt;new</span> );</code></pre>
1939</div>
1940
1941<div class="slide">
1942 <h1>Why Set <code>init_arg =&gt; undef</code>?</h1>
1943
1944 <ul>
1945 <li>Use this with a lazy default for attributes-as-cache</li>
1946 <li>Compute the value as needed</li>
1947 <li>Ensure that it is always generated correctly (not set by constructor)</li>
1948 <li>Use triggers or method modifiers (coming soon) to clear the value</li>
1949 </ul>
1950</div>
1951
1952<div class="slide">
1953 <h1>Attribute Inheritance</h1>
1954
1955 <ul>
1956 <li>By default, subclasses inherit attribute as-is</li>
1957 <li>Can change some attribute parameters in subclasses
1958 <ul>
1959 <li>default</li>
1960 <li>builder</li>
1961 <li>required</li>
1962 <li>lazy</li>
1963 <li>others we've not yet covered</li>
1964 </ul>
1965 </li>
1966 </ul>
1967</div>
1968
1969<div class="slide">
1970 <h1>Attribute Inheritance Example</h1>
1971
1972 <pre><code>package Employee;
1973use Moose;
1974
1975extends 'Person';
1976
1977has '<span class="highlight">+first_name</span>' =&gt; (
1978 default =&gt; 'Joe',
1979);</code></pre>
1980</div>
1981
1982<div class="slide">
1983 <h1>Attribute Inheritance Warning</h1>
1984
1985 <ul>
1986 <li>An attribute is a contract about a class's API</li>
1987 <li>Don't break that contract in a subclass</li>
1988 <li>Especially important in the context of types</li>
1989 </ul>
1990</div>
1991
1992<div class="slide">
1993 <h1>Changing Accessor Names</h1>
1994
1995 <pre><code>package Person;
1996use Moose;
1997
1998has first_name =&gt; (
1999 <span class="highlight">reader</span> =&gt; 'first_name',
2000 <span class="highlight">writer</span> =&gt; 'first_name',
2001);</code></pre>
2002
2003 <ul>
2004 <li>The long-hand version of <code>is =&gt; 'rw'</code></li>
2005 </ul>
2006</div>
2007
2008<div class="slide">
2009 <h1>Changing Accessor Names</h1>
2010
2011 <pre><code>package Person;
2012use Moose;
2013
2014has first_name =&gt; (
2015 <span class="highlight">reader</span> =&gt; 'first_name',
2016 <span class="highlight">writer</span> =&gt; undef,
2017);</code></pre>
2018
2019 <ul>
2020 <li>The long-hand version of <code>is =&gt; 'ro'</code></li>
2021 </ul>
2022</div>
2023
2024
2025<div class="slide">
2026 <h1>Changing Accessor Names</h1>
2027
2028 <pre><code>package Person;
2029use Moose;
2030
2031has first_name =&gt; (
2032 <span class="highlight">reader</span> =&gt; 'get_first_name',
2033 <span class="highlight">writer</span> =&gt; 'set_first_name,
2034);</code></pre>
2035</div>
2036
2037<div class="slide">
2038 <h1>Changing Accessor Names</h1>
2039
2040 <pre><code>package Person;
2041use Moose;
2042
2043has first_name =&gt; (
2044 <span class="highlight">is</span> =&gt; 'rw',
2045 <span class="highlight">writer</span> =&gt; '_first_name',
2046);</code></pre>
2047
2048 <ul>
2049 <li>Can also mix-and-match</li>
2050 </ul>
2051</div>
2052
2053<div class="slide">
2054 <h1>ETOOMUCHTYPING</h1>
2055
2056 <ul>
2057 <li><code>MooseX::FollowPBP</code><br /><code>get_foo</code> and <code>set_foo</code></li>
2058 <li><code>MooseX::SemiAffordanceAccessor</code><br /><code>foo</code> and <code>set_foo</code></li>
2059 </ul>
2060</div>
2061
2062<div class="slide">
2063 <h1>ETOOMUCHTYPING</h1>
2064
2065 <pre><code>package Person;
2066use Moose;
2067<span class="highlight">use MooseX::SemiAffordanceAccessor;</span>
2068
2069has first_name =&gt; (
2070 is =&gt; 'rw',
2071);</code></pre>
2072
2073 <ul>
2074 <li>Creates <code>first_name</code> and <code>set_first_name</code></li>
2075 </ul>
2076</div>
2077
2078<div class="slide">
26164c8d 2079 <h1>Basic Attributes Summary</h1>
2080
2081 <ul>
2082 <li>Attributes can be <code>required</code></li>
2083 <li>Attributes can have a <code>default</code> or <code>builder</code></li>
2084 <li>Attributes with a default or builder can be <code>lazy</code></li>
2085 <li>Attributes can have a <code>clearer</code> and/or <code>predicate</code></li>
2086 <li>An attribute's constructor name can be changed with <code>init_arg</code></li>
2087 <li>A subclass can alter its parents' attributes</li>
2088 <li>Attribute accessor names can be changed</li>
2089 </ul>
2090</div>
2091
2092<div class="slide">
2093 <h1>Questions?</h1>
2094</div>
2095
2096<div class="slide">
8d1ce1d7 2097 <h1>Exercises</h1>
2098
2099 <pre># cd exercises
2100# perl bin/prove -lv t/03-basic-attributes.t
2101
2102Iterate til this passes all its tests</pre>
2103</div>
2104
26164c8d 2105<div class="slide fake-slide0">
2106 <h1>Part 4: Method Modifiers</h1>
2107</div>
2108
2109<div class="slide">
2110 <h1>What is a Method Modifier</h1>
2111
2112 <ul>
2113 <li>Apply to an existing method</li>
2114 <li>... from a parent class, the current class, or a role</li>
2115 <li>Roles can provide modifiers that are applied at composition time</li>
2116 </ul>
2117</div>
2118
2119<div class="slide">
2120 <h1>What is a Method Modifier</h1>
2121
2122 <ul>
0a0c7e7c 2123 <li>"Inject" behavior</li>
26164c8d 2124 <li>Add behavior to generated methods (accessors, delegations)</li>
2125 <li>Provide roles which modify existing behavior</li>
2126 </ul>
2127</div>
2128
2129<div class="slide">
2130 <h1>Before and After</h1>
2131
2132 <ul>
2133 <li>Simplest modifiers - <code>before</code> and <code>after</code></li>
2134 <li>Guess when they run!</li>
2135 </ul>
2136</div>
2137
2138<div class="slide">
2139 <h1>Uses for <code>before</code></h1>
2140
2141 <ul>
2142 <li>As a pre-call check</li>
2143 </ul>
2144
2145 <pre><code>package Person;
2146use Moose;
2147
2148before work =&gt; sub {
2149 my $self = shift;
2150 die 'I have no job!'
2151 unless $self-&gt;has_title;
2152};</code></pre>
2153</div>
2154
2155<div class="slide">
2156 <h1>Uses for <code>before</code></h1>
2157
2158 <ul>
2159 <li>Logging/Debugging</li>
2160 </ul>
2161
2162 <pre><code>package Person;
2163use Moose;
2164
2165before work =&gt; sub {
2166 my $self = shift;
2167 return unless $DEBUG;
2168
2169 warn "Called work on ", $self->full_name,
2170 "with the arguments: [@_]\n";
2171};</code></pre>
2172</div>
2173
2174<div class="slide">
2175 <h1>Uses for <code>after</code></h1>
2176
2177 <ul>
2178 <li>Also works for logging/debugging</li>
2179 <li>Post-X side-effects (recording audit info)</li>
2180 </ul>
2181
2182 <pre><code>package Person;
2183use Moose;
2184
2185after work =&gt; sub {
2186 my $self = shift;
2187 $self-&gt;work_count(
2188 $self-&gt;work_count + 1 );
2189};</code></pre>
2190</div>
2191
2192<div class="slide">
2193 <h1>Other Uses</h1>
2194
2195 <ul>
2196 <li>Modifiers are useful for adding behavior to generated methods</li>
2197 </ul>
2198</div>
2199
2200<div class="slide">
2201 <h1>Other Uses Example</h1>
2202
2203 <pre><code>has password =&gt; (
2204 is =&gt; 'rw',
2205 clearer =&gt; 'clear_password',
2206);
2207
2208has hashed_password =&gt; (
2209 is =&gt; 'ro',
2210 builder =&gt; '_build_hashed_password',
2211 clearer =&gt; '_clear_hashed_password',
2212);
2213
2214after clear_password =&gt; sub {
2215 my $self = shift;
2216 $self-&gt;_clear_hashed_password;
2217};</code></pre>
2218</div>
2219
2220<div class="slide">
2221 <h1><code>before</code> and <code>after</code> Limitations</h1>
2222
2223 <ul>
2224 <li>Cannot alter method parameters</li>
2225 <li>Cannot alter return value</li>
2226 <li>But <strong>can</strong> throw an exception</li>
2227 </ul>
2228</div>
2229
2230<div class="slide">
2231 <h1>The <code>around</code> Modifier</h1>
2232
2233 <ul>
2234 <li>The big gun</li>
2235 <li>Can alter parameters <strong>and/or</strong> return values</li>
2236 <li>Can skip calling the wrapped method entirely</li>
2237 </ul>
2238</div>
2239
2240<div class="slide">
2241 <h1>The power of <code>around</code></h1>
2242
2243 <pre><code>around insert =&gt; sub {
2244 my $orig = shift;
2245 my $self = shift;
2246
2247 $self-&gt;_validate_insert(@_);
2248
2249 my $new_user =
2250 $self-&gt;$orig(
2251 $self-&gt;_munge_insert(@_) );
2252
2253 $new_user->_assign_uri;
2254
2255 return $new_user;
2256};</code></pre>
2257</div>
2258
2259<div class="slide">
2260 <h1>Modifier Order</h1>
2261
2262 <ul>
2263 <li>Before runs order from last to first</li>
2264 <li>After runs in order from first to last</li>
2265 <li>Around runs in order from last to first</li>
2266 </ul>
2267</div>
2268
2269<div class="slide">
2270 <h1>Modifier Order Illustrated</h1>
2271
2272<pre>
2273<span class="current incremental">before 2
2274 before 1</span>
2275 <span class="incremental">around 2
2276 around 1</span>
2277 <span class="incremental">wrapped method</span>
2278 <span class="incremental">around 1
2279 around 2</span>
2280 <span class="incremental">after 1
2281after 2</span>
2282</pre>
2283</div>
2284
2285<div class="slide">
2286 <h1>Modifiers in Roles</h1>
2287
2288 <ul>
2289 <li>Roles can use these modifiers</li>
2290 <li>Very powerful!</li>
2291 </ul>
2292</div>
2293
2294<div class="slide">
2295 <h1>Modifiers in Roles</h1>
2296
2297 <pre><code>package IsUnreliable;
2298use Moose::Role;
2299
2300<span class="highlight">requires 'run';
2301
2302around run</span> =&gt; sub {
2303 my $orig = shift;
2304 my $self = shift;
2305
2306 return if rand(1) &lt; 0.5;
2307
2308 return $self-&gt;$orig(@_);
2309};</code></pre>
2310</div>
2311
2312<div class="slide">
2313 <h1>Augment and Inner</h1>
2314
2315 <ul>
2316 <li>Inverted <code>super</code></li>
2317 <li>From least- to most-specific</li>
2318 <li>Grandparent to parent to child</li>
2319 <li>Not allowed in roles</li>
2320 </ul>
2321</div>
2322
2323<div class="slide">
2324 <h1>Augment and Inner</h1>
2325
2326 <pre><code>package Document;
2327
2328sub xml { '&lt;doc&gt;' . <span class="highlight">inner()</span> . '&lt;/doc&gt;' }
2329
2330package Report;
2331extends 'Document';
2332
2333<span class="highlight">augment xml</span> =&gt; { title() . <span class="highlight">inner()</span> . summary() };
2334
2335package TPSReport;
2336extends 'Report';
2337
2338<span class="highlight">augment xml</span> =&gt; { tps_xml() . <span class="highlight">inner()</span> };</code></pre>
2339</div>
2340
2341<div class="slide">
2342 <h1>Augment and Inner</h1>
2343
2344 <ul>
2345 <li>When we call <code>$tps-&gt;xml</code> ...
2346 <ul>
2347 <li><code>Document-&gt;xml</code></li>
2348 <li><code>Report-&gt;xml</code></li>
2349 <li><code>TPSReport-&gt;xml</code></li>
2350 </ul>
2351 </li>
2352 </ul>
2353</div>
2354
2355<div class="slide">
2356 <h1>Augment and Inner Usage</h1>
2357
2358 <ul>
2359 <li>Call <code>inner()</code> to "fill in the blank"</li>
2360 <li>Requires designing for subclassing</li>
2361 <li>Call <code>inner()</code> in the terminal class, just in case</li>
2362 </ul>
2363</div>
2364
2365<div class="slide">
5d572684 2366 <h1>Method Modifiers Summary</h1>
2367
2368 <ul>
2369 <li>Use <code>before</code> and <code>after</code> for ...
2370 <ul>
2371 <li>logging</li>
2372 <li>pre- or post-validation</li>
2373 <li>to add behavior to generated methods</li>
2374 </ul>
2375 </li>
2376 <li>These two modifiers cannot change parameters or return values</li>
2377 </ul>
2378</div>
2379
2380<div class="slide">
2381 <h1>Method Modifiers Summary</h1>
2382
2383 <ul>
2384 <li>Use <code>around</code> to ...
2385 <ul>
2386 <li>alter parameters passed to the original method</li>
2387 <li>alter the return value of the original method</li>
2388 <li>not call the original method at all (or call a <em>different</em> method)</li>
2389 </ul>
2390 </li>
2391 </ul>
2392</div>
2393
2394<div class="slide">
2395 <h1>Method Modifiers Summary</h1>
2396
2397 <ul>
2398 <li>When using modifiers in a role, require the modified method</li>
2399 <li>Use <code>augment</code> and <code>inner</code> to invert the normal subclassing flow ...
2400 <ul>
2401 <li>Least- to most-specific (parents to children)</li>
2402 <li>Build in "insertability" (stick more stuff in the "middle")</li>
2403 </ul>
2404 </li>
2405 <li>Always call <code>inner</code> in the most specific subclass to allow for future extension</li>
2406 </ul>
2407</div>
2408
2409<div class="slide">
26164c8d 2410 <h1>Questions?</h1>
2411</div>
2412
2413<div class="slide">
2414 <h1>Exercises</h1>
2415
2416 <pre># cd exercises
2417# perl bin/prove -lv t/04-method-modifiers.t
2418
2419Iterate til this passes all its tests</pre>
2420</div>
2421
5d572684 2422<div class="slide fake-slide0">
2423 <h1>Part 5: Types</h1>
2424</div>
2425
2426<div class="slide fake-slide0">
2427 <h1>Part 6: Advanced Attributes</h1>
2428</div>
2429
2430<div class="slide">
2431 <h1>Weak References</h1>
2432
2433 <ul>
2434 <li>A weak reference lets you avoid circular references</li>
2435 <li>Weak references do not increase the reference count</li>
2436 </ul>
2437</div>
2438
2439<div class="slide">
2440 <h1>Circular Reference Illustrated</h1>
2441
2442 <pre><code>my $foo = {};
2443my $bar = { foo =&gt; $foo };
2444$foo-&gt;{bar} = $bar;</code></pre>
2445
2446 <ul>
2447 <li>Neither <code>$foo</code> nor <code>$bar</code> go out of scope<br />
2448 (until the program exits)</li>
2449 </ul>
2450</div>
2451
2452<div class="slide">
2453 <h1>Weakening Circular References</h1>
2454
2455 <pre><code>use Scalar::Util qw( weaken );
2456
2457my $foo = {};
2458my $bar = { foo =&gt; $foo };
2459$foo-&gt;{bar} = $bar;
2460weaken $foo-&gt;{bar}</code></pre>
2461
2462 <ul>
2463 <li>When <code>$bar</code> goes out of scope, <code>$foo-&gt;{bar}</code> becomes <code>undef</code></li>
2464 </ul>
2465</div>
2466
2467<div class="slide">
2468 <h1>Circular References in Attributes</h1>
2469
2470 <pre><code>package Person;
2471use Moose;
2472
2473has name =&gt; ( is =&gt; 'ro' );
2474has friend =&gt; ( is =&gt; 'rw' );
2475
2476my $alice = Person-&gt;new( name =&gt; 'Alice' );
2477my $bob = Person-&gt;new( name =&gt; 'Bob' );
2478$bob-&gt;friend($alice);
2479$alice-&gt;friend($bob);</code></pre>
2480</div>
2481
2482<div class="slide">
2483 <h1>The Fix</h1>
2484
2485 <pre><code>package Person;
2486use Moose;
2487
2488has name =&gt; ( is =&gt; 'ro' );
2489has friend =&gt; ( is =&gt; 'rw', <span class="highlight">weak_ref =&gt; 1</span> );
2490
2491my $alice = Person-&gt;new( name =&gt; 'Alice' );
2492my $bob = Person-&gt;new( name =&gt; 'Bob' );
2493$bob-&gt;friend($alice);
2494$alice-&gt;friend($bob);</code></pre>
2495</div>
2496
2497<div class="slide">
2498 <h1>Under the Hood</h1>
2499
2500 <ul>
2501 <li>A <code>weak_ref</code> attribute calls <code>weaken</code> ...
2502 <ul>
2503 <li>during object construction</li>
2504 <li>when the attribute is set via a writer</li>
2505 </ul>
2506 </li>
2507 </ul>
2508</div>
2509
2510<div class="slide">
2511 <h1>Triggers</h1>
2512
2513 <ul>
2514 <li>A code reference run after an attribute is <em>set</em></li>
2515 <li>Like an <code>after</code> modifier, but makes intentions clearer</li>
2516 </ul>
2517
2518 <h2 class="wrong">Gross</h2>
2519
2520 <pre><code>after salary_level =&gt; {
2521 my $self = shift;
2522 return unless @_;
2523 $self-&gt;clear_salary;
2524};</code></pre>
2525</div>
2526
2527<div class="slide">
2528 <h1>Use a Trigger Instead</h1>
2529
2530 <h2 class="right">Cleaner</h2>
2531
2532 <pre><code>has salary_level =&gt; (
2533 is =&gt; 'rw',
2534 trigger =&gt; sub { $_[0]-&gt;clear_salary },
2535);</code></pre>
2536</div>
2537
2538<div class="slide">
2539 <h1>Delegation</h1>
2540
2541 <ul>
2542 <li>Attributes can be objects</li>
2543 <li>Delegation transparently calls methods on those objects</li>
2544 </ul>
2545</div>
2546
2547<div class="slide">
2548 <h1>Delegation Examples</h1>
2549
2550 <pre><code>package Person;
2551
2552has lungs =&gt; (
2553 is =&gt; 'ro',
2554 isa => 'Lungs',
2555 <span class="highlight">handles =&gt; [ 'inhale', 'exhale' ],</span>
2556);</code></pre>
2557
2558 <ul>
2559 <li>Creates <code>$person-&gt;inhale</code> and <code>-&gt;exhale</code> methods</li>
2560 <li>Internally calls <code>$person-&gt;lungs-&gt;inhale</code></li>
2561 </ul>
2562</div>
2563
2564<div class="slide">
2565 <h1>Why Delegation?</h1>
2566
2567 <ul>
2568 <li>Reduce the number of classes exposed</li>
2569 <li>Re-arrange class internals -<br />
2570 turn a method into an attribute with delegation</li>
2571 <li>Provide convenenience methods</li>
2572 </ul>
2573</div>
2574
2575<div class="slide">
2576 <h1>Moose's <code>handles</code> Parameter</h1>
2577
2578 <ul>
2579 <li>Accepts many arguments ...
2580 <ul>
2581 <li>Array reference - list of methods to delegate as-is</li>
2582 <li>Hash reference - map of method names</li>
2583 <li>Regex - delegates all matching methods</li>
2584 <li>Role name - delegates all methods in the role</li>
2585 <li>Sub reference - does something complicated ;)</li>
2586 </ul>
2587 </li>
2588 </ul>
2589</div>
2590
2591<div class="slide">
2592 <h1>Array Reference</h1>
2593
2594 <ul>
2595 <li>Takes each method name and creates a simple delegation from the delegating class to the delegatee attribute</li>
2596 </ul>
2597</div>
2598
2599<div class="slide">
2600 <h1>Hash Reference</h1>
2601
2602 <ul>
2603 <li>Mapping of names in the delegating class to the delegatee class</li>
2604 </ul>
2605
2606 <pre><code>package Person;
2607use Moose;
2608
2609has account =&gt; (
2610 is =&gt; 'ro',
2611 isa =&gt; 'BankAccount',
2612 <span class="highlight">handles =&gt; {
2613 receive_money =&gt; 'deposit',
2614 give_money =&gt; 'withdraw',
2615 },</span>
2616);</code></pre>
2617</div>
2618
2619<div class="slide">
2620 <h1>Hash Reference Detailed</h1>
2621
2622 <pre><code> handles =&gt; {
2623 receive_money =&gt; 'deposit',
2624 give_money =&gt; 'withdraw',
2625 },</code></pre>
2626
2627 <ul>
2628 <li><code>$person-&gt;receive_money</code> = <code>$person-&gt;account-&gt;deposit</code></li>
2629 <li><code>$person-&gt;give_money</code> = <code>$person-&gt;account-&gt;withdraw</code></li>
2630 </ul>
2631</div>
2632
2633<div class="slide">
2634 <h1>Regex</h1>
2635
2636 <pre><code>package Person;
2637use Moose;
2638
2639has name =&gt; (
2640 is =&gt; 'ro',
2641 isa =&gt; 'Name',
2642 handles =&gt; qr/.*/,
2643);</code></pre>
2644
2645 <ul>
2646 <li>Creates a delegation for every method in the Name class</li>
2647 <li>Excludes <code>meta</code> and methods inherited from <code>Moose::Object</code></li>
2648 </ul>
2649</div>
2650
2651<div class="slide">
2652 <h1>Role Name</h1>
2653
2654 <pre><code>package Auditor;
2655use Moose::Role;
2656
2657sub record_change { ... }
2658sub change_history { ... }
2659
2660package Account;
2661use Moose;
2662
2663has history =&gt; (
2664 is =&gt; 'ro',
2665 does =&gt; 'Auditor',
2666 <span class="highlight">handles =&gt; 'Auditor',</span>
2667);</code></pre>
2668</div>
2669
2670<div class="slide">
2671 <h1>Role Name Detailed</h1>
2672
2673 <ul>
2674 <li>Account gets delegate methods for each method in the <code>Auditor</code> role
2675 <ul>
2676 <li>record_history</li>
2677 <li>change_history</li>
2678 </ul>
2679 </li>
2680 </ul>
2681</div>
2682
2683<div class="slide">
2684 <h1>Traits and Metaclasses</h1>
2685
2686 <ul>
2687 <li>The ultimate in customization</li>
2688 <li>Per attribute metaclasses</li>
2689 <li>Per attribute roles applied to the attribute metaclass</li>
2690 <li>Change the meta-level behavior</li>
2691 </ul>
2692</div>
2693
2694<div class="slide">
2695 <h1>Traits and Metaclasses</h1>
2696
2697 <ul>
2698 <li>The default metaclass is <code>Moose::Meta::Attribute</code></li>
2699 <li>Controls accessor generation, defaults, delegation, etc.</li>
2700 <li>Adding a role to this metaclass (or replacing it) allows for infinite customization</li>
2701 </ul>
2702</div>
2703
2704<div class="slide">
2705 <h1>Traits and Metaclasses</h1>
2706
2707 <ul>
2708 <li>Can add/alter/remove attribute parameter (from <code>has</code>)</li>
2709 <li>Can change behavior of created attribute</li>
2710 </ul>
2711</div>
2712
2713<div class="slide">
2714 <h1>Simple Trait Example</h1>
2715
2716 <pre><code>package Person;
2717use Moose;
2718use MooseX::LabeledAttributes;
2719
2720has ssn =&gt; (
2721 <span class="highlight">traits =&gt; [ 'Labeled' ],</span>
2722 is =&gt; 'ro',
2723 isa =&gt; 'Str',
2724 <span class="highlight">label =&gt; 'Social Security Number',</span>
2725);
2726
2727print <span class="highlight">Person-&gt;meta
2728 -&gt;get_attribute('ssn')-&gt;label;</span></code></pre>
2729</div>
2730
2731<div class="slide">
2732 <h1>Simple Metaclass Example</h1>
2733
2734 <pre><code>package Person;
2735use Moose;
2736use MooseX::LabeledAttributes;
2737
2738has ssn =&gt; (
2739 <span class="highlight">metaclass =&gt;
2740 'MooseX::Meta::Attribute::Labeled',</span>
2741 is =&gt; 'ro',
2742 isa =&gt; 'Str',
2743 <span class="highlight">label =&gt; 'Social Security Number',</span>
2744);
2745
2746print <span class="highlight">Person-&gt;meta
2747 -&gt;get_attribute('ssn')-&gt;label;</span></code></pre>
2748</div>
2749
2750<div class="slide">
2751 <h1>Traits vs Metaclass</h1>
2752
2753 <ul>
2754 <li>Can apply any mix of traits to an attribute</li>
2755 <li>But just one metaclass</li>
2756 <li>Traits (aka roles) can cooperate</li>
2757 <li>Metaclasses require you to pick just one</li>
2758 </ul>
2759</div>
2760
2761<div class="slide">
2762 <h1>Advanced Attributes Summary</h1>
2763
2764 <ul>
2765 <li>Use <code>weak_ref</code> to avoid circular references</li>
2766 <li>Use trigger to do an action post-attribute write</li>
2767 <li>Use delegations to hide "internal" objects</li>
2768 <li>Traits and metaclasses let you extend Moose's core attribute features</li>
2769 </ul>
2770</div>
2771
9186987b 2772<div class="slide">
2773 <h1>Questions?</h1>
2774</div>
2775
2776<div class="slide">
2777 <h1>Exercises</h1>
2778
2779 <pre># cd exercises
2780# perl bin/prove -lv t/06-advanced-attributes.t
2781
2782Iterate til this passes all its tests</pre>
2783</div>
2784
2785<div class="slide fake-slide0">
2786 <h1>Part 7: Introspection</h1>
2787</div>
2788
2789<div class="slide fake-slide0">
2790 <h1>Part 8: A Tour of MooseX</h1>
2791</div>
2792
2793<div class="slide fake-slide0">
2794 <h1>Part 9: Writing Moose Extensions</h1>
2795</div>
2796
55906a14 2797</div>
b751d33f 2798</body>
2799</html>
55906a14 2800
2801<!--
2802
2803Copyright 2009 David Rolsky. All Rights Reserved.
2804
2805This work is licensed under a Creative Commons Attribution-Share Alike
28063.0 United States License See
2807http://creativecommons.org/licenses/by-sa/3.0/us/ for details.
2808
2809-->