Be more explicit about BUILDARGS munging new's @_
[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">
debc93f8 43 <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/"><img alt="Creative Commons License" style="border-width:0" src="ui/creative-commons.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>
659a35cd 55 <h2>Dave Rolsky</a>
b751d33f 56</div>
57
58<div class="slide">
ba3e6f3b 59 <h1>Introduce Yourselves</h1>
60
61 <ul>
62 <li>Your name</li>
63 <li>What you do with Perl</li>
64 <li>Why you're here today (optional)</li>
65 </ul>
66</div>
67
68<div class="slide">
b751d33f 69 <h1>Moose Summed Up</h1>
70
71 <ul>
72 <li><strong>Declarative</strong> OO sugar</li>
73 <li>Introspectable</li>
c31b1dea 74 <li>Extensible (177 MooseX::* on CPAN)</li>
75 <li>Community approved (1222 downstream dependents on CPAN)</li>
b751d33f 76 </ul>
77</div>
78
79<div class="slide">
55906a14 80 <h1>Moose Background</h1>
b751d33f 81
82 <ul>
55906a14 83 <li>Created by Stevan Little, first released in 2006</li>
b751d33f 84 <li>Moose builds on Perl 5's native OO</li>
85 <li>Borrows ideas from other languages, notably Perl 6</li>
86 <li>Provides semantics for common operations</li>
87 </ul>
88</div>
89
55906a14 90<div class="slide fake-slide0">
91 <h1>Part 0: Moose Concepts</h1>
92</div>
93
b751d33f 94<div class="slide">
95 <h1>Classes</h1>
96
97 <ul>
98 <li>
99 Classes have ...
100 <ul>
101 <li>Attributes</li>
102 <li>Methods</li>
103 <li>Superclasses</li>
104 <li>Method modifiers</li>
105 <li>Constructor and destructor</li>
106 <li>One metaclass object</li>
107 </ul>
108 </li>
109 <li>Classes do roles</li>
110 </ul>
111</div>
112
113<div class="slide">
114 <h1>Class Example</h1>
115
116 <pre><code>package Person;
117<span class="highlight">use Moose;</span></code></pre>
118
119 <ul>
120 <li>Poof, a Moose-based class!</li>
121 </ul>
122</div>
123
124<div class="slide">
125 <h1>Attributes</h1>
126
127 <ul>
128 <li>Aka property, slot, field, member variable</li>
129 <li>A piece of data owned by an object</li>
130 </ul>
131</div>
132
133<div class="slide">
134 <h1>Attributes</h1>
135
136 <ul>
137 <li>
138 Attributes have ...
139 <ul>
362c7c75 140 <li>Mutability (read-only vs read-write)</li>
b751d33f 141 <li>An optional type</li>
142 <li>Accessor methods</li>
143 <li>Delegation methods</li>
144 <li>Optional default value</li>
145 <li>Many more features</li>
146 </ul>
147 </li>
148 <li>Stored in the object, but don't worry about that</li>
149 </ul>
150</div>
151
152<div class="slide">
153 <h1>Attribute Example</h1>
154
155 <pre><code>package Person;
156use Moose;
157
55906a14 158<span class="highlight">has first_name =&gt; ( is =&gt; 'rw' );</span></code></pre>
b751d33f 159
160</div>
161
162<div class="slide">
163 <h1>Methods</h1>
164
165 <ul>
166 <li>Nothing fancy here, just Perl subroutines</li>
167 </ul>
168
169 <pre><code>package Person;
170use Moose;
171
172<span class="highlight">sub greet { ... }</span></code></pre>
173</div>
174
175<div class="slide">
176 <h1>Roles</h1>
177
178 <ul>
179 <li>Classes <strong>do</strong> (or consume) roles</li>
180 <li>Similar to mixins and Java interfaces</li>
181 </ul>
182</div>
183
184<div class="slide">
185 <h1>Roles</h1>
186
187 <ul>
188 <li>Like classes, can have attributes, methods, do roles</li>
189 <li>Roles can require methods</li>
190 <li>Roles are composed (flattened) into classes</li>
191 </ul>
192</div>
193
194<div class="slide">
195 <h1>Role Example</h1>
196
197<pre><code>package HasPermissions;
198<span class="highlight">use Moose::Role;</span>
199
200has is_admin =&gt; ( is =&gt; 'rw' );</code></pre>
201</div>
202
203<div class="slide">
204 <h1>Role Example</h1>
205
206 <p>
207 And then ...
208 </p>
209
210<pre><code>package Person;
211use Moose;
212
213<span class="highlight">with 'HasPermissions';</span></code></pre>
214</div>
215
216<div class="slide">
217 <h1>Method Modifiers</h1>
218
219 <ul>
220 <li>AKA advice</li>
221 <li>&quot;<strong>Before</strong> foo(), do this first&quot;</li>
801bde7c 222 <li>&quot;Do this <strong>after</strong> foo()&quot;</li>
b751d33f 223 <li>&quot;Put this code <strong>around</strong> foo()&quot;</li>
224 </ul>
225</div>
226
227<div class="slide">
26164c8d 228 <h1>Before and After</h1>
b751d33f 229
230<pre><code>before 'foo'
231 =&gt; sub { warn 'About to call foo()' };
232
233after 'foo'
234 =&gt; sub { warn 'Leaving foo()' };</code></pre>
235
236</div>
237
238<div class="slide">
239 <h1>Around</h1>
240
241<pre><code>around 'foo' =&gt; sub {
242 my $real_foo = shift;
243 my $self = shift;
244
245 warn 'Just before foo()';
246 my @return =
247 $self-&gt;$real_foo( @_, bar =&gt; 42 );
248
debc93f8 249 return (
250 @return,
251 'modify return values'
252 );
b751d33f 253};</code></pre>
254</div>
255
256<div class="slide">
257 <h1>Type Constraints</h1>
258
259 <ul>
260 <li>NOT A FULL-BLOWN TYPE SYSTEM!</li>
261 <li>But still darn useful</li>
262 <li>Constrain attribute values</li>
263 <li>Coerce from other types</li>
264 </ul>
265</div>
266
267<div class="slide">
268 <h1>Type Constraint Example</h1>
269
270<pre><code>package Person;
271use Moose;
272
55906a14 273has weight =&gt; (
274 is =&gt; 'ro',
275 <span class="highlight">isa =&gt; 'Int'</span>,
276);
b751d33f 277
278# kaboom
2ab00dc1 279Person-&gt;new( weight =&gt; 'heavy' );</code></pre>
b751d33f 280</div>
281
282<div class="slide">
283 <h1>Delegation</h1>
284
285 <ul>
286 <li>Attributes can define delegations</li>
287 <li>Lets you hide some implementation details</li>
288 <li>Fewer objects to chase around</li>
289 </ul>
290</div>
291
292<div class="slide">
293 <h1>Delegation</h1>
294
295<pre><code>package Person;
296use Moose;
297
55906a14 298has blog_uri =&gt; (
b751d33f 299 is =&gt; 'rw',
300 isa =&gt; 'URI',
debc93f8 301 <span class="highlight">handles =&gt; { 'blog_host' =&gt; 'host' },</span>
b751d33f 302);
303
203ca9ec 304<span class="highlight">$person-&gt;blog_host;</span>
305# really calls $person-&gt;blog_uri-&gt;host</code></pre>
b751d33f 306</div>
307
308<div class="slide">
309 <h1>Constructors</h1>
310
311 <ul>
312 <li>Moose creates <code>new()</code> for you</li>
93faddd6 313 <li>Provide an optional <code>BUILDARGS()</code> and <code>BUILD()</code></li>
b751d33f 314 </ul>
315</div>
316
317<div class="slide">
318 <h1>Destructors</h1>
319
320 <ul>
321 <li>Provide an optional <code>DEMOLISH()</code></li>
322 </ul>
323</div>
324
325<div class="slide">
326 <h1>Moose Meta-API</h1>
327
328 <ul>
329 <li>Answers questions like ...
330 <ul>
331 <li>What methods does this class have?</li>
332 <li>What are its parents?</li>
333 <li>What attributes does it have (including inherited attributes)?</li>
334 <li>What roles does it do?</li>
335 <li>Much, much, more</li>
336 </ul>
337 </li>
338 </ul>
339</div>
340
341<div class="slide">
342 <h1>Moose Meta-API</h1>
343
344 <ul>
345 <li>Not just for introspection ...
346 <ul>
347 <li>Add methods, attributes, roles, etc</li>
348 <li>Extend and alter core features</li>
349 </ul>
350 </li>
351 </ul>
352</div>
353
354<div class="slide">
355 <h1>Why Moose?</h1>
356
357 <ul>
811952b2 358 <li>A quick bit of propaganda ...</li>
b751d33f 359 </ul>
360</div>
361
362<div class="slide">
363 <h1>With Moose</h1>
364
365 <pre><code>package Person;
366use Moose;
367
368has last_name =&gt; (
369 is =&gt; 'rw',
370 isa =&gt; 'Str',
371);</code></pre>
372</div>
373
374<div class="slide">
375 <h1>Without Moose</h1>
376
377 <pre class="small"><code>package Person;
378use strict;
379use warnings;
380use Carp 'confess';
381
382sub new {
383 my $class = shift;
384 my %args = @_;
385 my $self = {};
386
387 if (exists $args{last_name}) {
388 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
389 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
390 if ref($args{last_name});
391 $self-&gt;{last_nane} = $args{last_name};
392 }
393
394 return bless $self, $class;
395}
396
397sub last_name {
398 my $self = shift;
399
400 if (@_) {
401 my $value = shift;
402 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
403 . &quot;Validation failed for 'Str' with value $value&quot;
404 if ref($value);
405 $self-&gt;{last_name} = $value;
406 }
407
408 return $self-&gt;{last_name};
409}</code></pre>
410
411</div>
412
413<div class="slide">
414 <h1>Side by side</h1>
415
416 <table class="side-by-side">
417 <tr>
418 <td>
419 <pre><code>package Person;
420use Moose;
421
422has last_name =&gt; (
423 is =&gt; 'rw',
424 isa =&gt; 'Str',
425);</code></pre>
426 </td>
427 <td>
428 <pre class="small"><code>package Person;
429use strict;
430use warnings;
431use Carp 'confess';
432
433sub new {
434 my $class = shift;
435 my %args = @_;
436 my $self = {};
437
438 if (exists $args{last_name}) {
439 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
440 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
441 if ref($args{last_name});
442 $self-&gt;{last_nane} = $args{last_name};
443 }
444
445 return bless $self, $class;
446}
447
448sub last_name {
449 my $self = shift;
450
451 if (@_) {
452 my $value = shift;
453 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
454 . &quot;Validation failed for 'Str' with value $value&quot;
455 if ref($value);
456 $self-&gt;{last_name} = $value;
457 }
458
459 return $self-&gt;{last_name};
460}</code></pre>
461 </td>
462 </tr>
463 </table>
464
465</div>
466
467<div class="slide">
468 <h1>Side by side</h1>
469
470 <table class="side-by-side">
471 <tr>
472 <td>
473 <pre><code><span class="match-moose">package Person;</span>
474use Moose;
475
476has last_name =&gt; (
477 is =&gt; 'rw',
478 isa =&gt; 'Str',
479);</code></pre>
480 </td>
481 <td>
482 <pre class="small"><code><span class="match-unsweet">package Person;</span>
483use strict;
484use warnings;
485use Carp 'confess';
486
487sub new {
488 my $class = shift;
489 my %args = @_;
490 my $self = {};
491
492 if (exists $args{last_name}) {
493 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
494 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
495 if ref($args{last_name});
496 $self-&gt;{last_nane} = $args{last_name};
497 }
498
499 return bless $self, $class;
500}
501
502sub last_name {
503 my $self = shift;
504
505 if (@_) {
506 my $value = shift;
507 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
508 . &quot;Validation failed for 'Str' with value $value&quot;
509 if ref($value);
510 $self-&gt;{last_name} = $value;
511 }
512
513 return $self-&gt;{last_name};
514}</code></pre>
515 </td>
516 </tr>
517 </table>
518</div>
519
520<div class="slide">
521 <h1>Side by side</h1>
522
523 <table class="side-by-side">
524 <tr>
525 <td>
526 <pre><code>package Person;
527<span class="match-moose">use Moose;</span>
528
529has last_name =&gt; (
530 is =&gt; 'rw',
531 isa =&gt; 'Str',
532);</code></pre>
533 </td>
534 <td>
535 <pre class="small"><code>package Person;
536<span class="match-unsweet">use strict;
537use warnings;
538use Carp 'confess';
539
540sub new {
541 my $class = shift;
542 my %args = @_;
543 my $self = {};</span>
544
545 if (exists $args{last_name}) {
546 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
547 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
548 if ref($args{last_name});
549 $self-&gt;{last_nane} = $args{last_name};
550 }
551
552 <span class="match-unsweet">return bless $self, $class;
553}</span>
554
555sub last_name {
556 my $self = shift;
557
558 if (@_) {
559 my $value = shift;
560 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
561 . &quot;Validation failed for 'Str' with value $value&quot;
562 if ref($value);
563 $self-&gt;{last_name} = $value;
564 }
565
566 return $self-&gt;{last_name};
567}</code></pre>
568 </td>
569 </tr>
570 </table>
571</div>
572
573<div class="slide">
574 <h1>Side by side</h1>
575
576 <table class="side-by-side">
577 <tr>
578 <td>
579 <pre><code>package Person;
580use Moose;
581
582<span class="match-moose">has last_name =&gt; (</span>
583 is =&gt; 'rw',
584 isa =&gt; 'Str',
585<span class="match-moose">);</span></code></pre>
586 </td>
587 <td>
588 <pre class="small"><code>package Person;
589use strict;
590use warnings;
591use Carp 'confess';
592
593sub new {
594 my $class = shift;
595 my %args = @_;
596 my $self = {};
597
598 <span class="match-unsweet">if (exists $args{last_name}) {</span>
599 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
600 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
601 if ref($args{last_name});
602 <span class="match-unsweet">$self-&gt;{last_nane} = $args{last_name};
603 }</span>
604
605 return bless $self, $class;
606}
607
608sub last_name {
609 my $self = shift;
610
611 if (@_) {
612 my $value = shift;
613 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
614 . &quot;Validation failed for 'Str' with value $value&quot;
615 if ref($value);
616 $self-&gt;{last_name} = $value;
617 }
618
619 return $self-&gt;{last_name};
620}</code></pre>
621 </td>
622 </tr>
623 </table>
624</div>
625
626<div class="slide">
627 <h1>Side by side</h1>
628
629 <table class="side-by-side">
630 <tr>
631 <td>
632 <pre><code>package Person;
633use Moose;
634
635has last_name =&gt; (
636 <span class="match-moose">is =&gt; 'rw',</span>
637 isa =&gt; 'Str',
638);</code></pre>
639 </td>
640 <td>
641 <pre class="small"><code>package Person;
642use strict;
643use warnings;
644use Carp 'confess';
645
646sub new {
647 my $class = shift;
648 my %args = @_;
649 my $self = {};
650
651 if (exists $args{last_name}) {
652 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
653 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
654 if ref($args{last_name});
655 $self-&gt;{last_nane} = $args{last_name};
656 }
657
658 return bless $self, $class;
659}
660
661<span class="match-unsweet">sub last_name {
662 my $self = shift;
663
664 if (@_) {
665 my $value = shift;</span>
666 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
667 . &quot;Validation failed for 'Str' with value $value&quot;
668 if ref($value);
669 <span class="match-unsweet">$self-&gt;{last_name} = $value;
670 }
671
672 return $self-&gt;{last_name};
673}</span></code></pre>
674 </td>
675 </tr>
676 </table>
677</div>
678
679<div class="slide">
680 <h1>Side by side</h1>
681
682 <table class="side-by-side">
683 <tr>
684 <td>
685 <pre><code>package Person;
686use Moose;
687
688has last_name =&gt; (
689 is =&gt; 'rw',
690 <span class="match-moose">isa =&gt; 'Str',</span>
691);</code></pre>
692 </td>
693 <td>
694 <pre class="small"><code>package Person;
695use strict;
696use warnings;
697use Carp 'confess';
698
699sub new {
700 my $class = shift;
701 my %args = @_;
702 my $self = {};
703
704 if (exists $args{last_name}) {
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 $args{last_name}&quot;
707 if ref($args{last_name});</span>
708 $self-&gt;{last_nane} = $args{last_name};
709 }
710
711 return bless $self, $class;
712}
713
714sub last_name {
715 my $self = shift;
716
717 if (@_) {
718 my $value = shift;
719 <span class="match-unsweet">confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
720 . &quot;Validation failed for 'Str' with value $value&quot;
721 if ref($value);</span>
722 $self-&gt;{last_name} = $value;
723 }
724
725 return $self-&gt;{last_name};
726}</code></pre>
727 </td>
728 </tr>
729 </table>
730</div>
731
732<div class="slide">
733 <h1>Side by side</h1>
734
735 <table class="side-by-side">
736 <tr class="incremental">
737 <td>5 lines</td>
738 <td>21 lines</td>
739 </tr>
740 <tr class="incremental">
741 <td>92 characters</td>
742 <td>741 characters</td>
743 </tr>
744 <tr>
745 <td>
746 <pre><code>package Person;
747use Moose;
748
749has last_name =&gt; (
750 is =&gt; 'rw',
751 isa =&gt; 'Str',
752);</code></pre>
753 </td>
754 <td>
755 <pre class="small"><code>package Person;
756use strict;
757use warnings;
758use Carp 'confess';
759
760sub new {
761 my $class = shift;
762 my %args = @_;
763 my $self = {};
764
765 if (exists $args{last_name}) {
766 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
767 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
768 if ref($args{last_name});
769 $self-&gt;{last_nane} = $args{last_name};
770 }
771
772 return bless $self, $class;
773}
774
775sub last_name {
776 my $self = shift;
777
778 if (@_) {
779 my $value = shift;
780 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
781 . &quot;Validation failed for 'Str' with value $value&quot;
782 if ref($value);
783 $self-&gt;{last_name} = $value;
784 }
785
786 return $self-&gt;{last_name};
787}</code></pre>
788 </td>
789 </tr>
790 </table>
791</div>
792
793<div class="slide">
794 <h1>Typo?</h1>
795
796 <pre class="small"><code>sub new {
797 my $class = shift;
798 my %args = @_;
799 my $self = {};
800
801 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 }
807
808 return bless $self, $class;
809}</code></pre>
810</div>
811
812<div class="slide">
813 <h1>Typo?</h1>
814
815 <pre class="small"><code>if (exists $args{last_name}) {
816 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
817 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
818 if ref($args{last_name});
819 $self-&gt;{last_nane} = $args{last_name};
820}</code></pre>
821</div>
822
823<div class="slide">
824 <h1>Typo?</h1>
825
826 <code>$self-&gt;{last_nane} = $args{last_name};</code>
827</div>
828
829<div class="slide">
830 <h1>Typo?</h1>
8d1ce1d7 831 <code>$self-&gt;{last_na<span class="wrong">n</span>e}</code>
b751d33f 832</div>
833
834<div class="slide">
835 <h1>Why Moose?</h1>
836
837 <pre><code>package Person;
838use Moose;
839
840has last_name =&gt; (
841 is =&gt; 'rw',
842 isa =&gt; 'Str',
843);</code></pre>
844</div>
845
9b0c7222 846<div class="slide">
847 <h1>More Why Moose?</h1>
848
849 <ul>
850 <li>Less code == fewer bugs</li>
851 <li>Moose is well-tested, test your own code, not Moose</li>
852 <li>Focus on <strong>what</strong>, not <strong>how</strong></li>
853 </ul>
854</div>
855
b751d33f 856<div class="slide fake-slide0">
ba1c9923 857 <h1>Part 1: Moose Classes</h1>
b751d33f 858</div>
859
860<div class="slide">
861 <h1>Moose Classes</h1>
862
863 <ul>
864 <li>Moose classes are Perl packages which <code>use Moose</code></li>
865 </ul>
866</div>
867
868<div class="slide">
869 <h1>Moose.pm and Your Class</h1>
870
871 <pre><code>package Person;
872use Moose;</code></pre>
873
874 <ul>
875 <li><code>Moose.pm</code> provides declarative sugar</li>
9b195048 876 <li>Turns on <code>strict</code> and <code>warnings</code></li>
b751d33f 877 <li>Creates metaclasses for your class: <code>Person-&gt;meta</code></li>
878 <li>Moose classes automatically inherit from <code>Moose::Object</code></li>
879 </ul>
880</div>
881
882<div class="slide">
883 <h1>What <code>Moose::Object</code> Provides</h1>
884
885 <ul>
886 <li>Constructor - <code>new()</code></li>
887 <li>Calls your <code>BUILDARGS()</code> and/or <code>BUILD()</code></li>
888 <li>Calls your <code>DEMOLISH</code> during object destruction</li>
889 </ul>
890</div>
891
892<div class="slide">
d6c8786d 893 <h1>BUILDARGS</h1>
894
895 <ul>
b8e08963 896 <li>Processes <code>new</code>'s <code>@_</code>, returns a hash reference of attribute name/value pairs</li>
d6c8786d 897 <li>Accepts a hash or hashref; throws otherwise</li>
898 <li>Provide your own for other cases</li>
899 <li><strong>Always</strong> call <code>$class-&gt;SUPER::BUILDARGS(@_)</code> as a fallback!</li>
900 </ul>
901</div>
902
903<div class="slide">
904 <h1>BUILDARGS Example</h1>
905
906 <pre><code>package Person;
907use Moose;
908
909sub BUILDARGS {
910 my $class = shift;
911
5e2eb691 912 if ( @_ == 1 &amp;&amp; ! ref $_[0] ) {
d6c8786d 913 <span class="highlight">return { ssn =&gt; $_[0] };</span>
914 }
d6c8786d 915 <span class="highlight">return $class-&gt;SUPER::BUILDARGS(@_)</span>;
916}
917
918<span class="highlight">Person-&gt;new('123-45-6789')</span></code></pre>
919</div>
920
921<div class="slide">
922 <h1>BUILD</h1>
923
924 <ul>
925 <li>Called after object is created, before <code>new</code> returns</li>
926 <li>Chance to do more complex validation, set complex attributes</li>
927 <li>Called in reverse inheritance order, parents to children</li>
928 <li>Return value is ignored</li>
929 </ul>
930</div>
931
932<div class="slide">
933 <h1>BUILD Example</h1>
934
935 <pre><code>package Person;
936use Moose;
937
938sub BUILD {
939 my $self = shift;
940
941 if ( $self-&gt;country_of_residence
942 eq 'USA' ) {
943 die 'All US residents'
944 . ' must have an SSN'
945 unless $self-&gt;has_ssn;
946 }
947}</code></pre>
948</div>
949
950<div class="slide">
7205c6ef 951 <h1>Object Construction a la Moose</h1>
952
953 <pre><code>Person-&gt;new(@_)</code></pre>
954
86178e0f 955 <ol style="margin-top: 0">
7205c6ef 956 <li>Calls <code>Person-&gt;BUILDARGS(@_)</code> to turn <code>@_</code> into a hashref</li>
957 <li>Blesses a reference</li>
958 <li>Populates attributes based on the hashref from #1</li>
203ca9ec 959 <li>Calls <code>$new_object-&gt;BUILDALL($constructor_args)</code>
7205c6ef 960 <br />... which calls all <code>BUILD</code> methods</li>
961 <li>Returns the object</li>
962 </ol>
963</div>
964
965<div class="slide">
17d7a564 966 <h1>The Object is Opaque</h1>
7205c6ef 967
968 <ul>
969 <li>Technically it's a hash reference</li>
970 <li><span class="wrong">If you <em>ever</em> treat it as one <strong>you are doing it wrong!</strong></span></li>
971 </ul>
972</div>
973
974<div class="slide">
d6c8786d 975 <h1>DEMOLISH</h1>
976
977 <ul>
978 <li>Like <code>DESTROY</code>, but Moose makes sure all <code>DEMOLISH</code> methods in a hierarchy are called</li>
979 <li>Called in normal inheritance order, children to parents</li>
5763b46d 980 <li><em>Never</em> called by you, only by Perl itself</li>
d6c8786d 981 </ul>
982</div>
983
984<div class="slide">
b751d33f 985 <h1>extends</h1>
986
987 <ul>
988 <li><code>extends</code> is sugar for declaring parent classes</li>
1847dd9e 989 <li>Also ensures metaclass compatibility between parent and child</li>
990 <li>Do not <code>use base</code></li>
b751d33f 991 </ul>
992
993 <pre><code>package Employee;
994use Moose;
995<span class="highlight">extends 'Person';</span></code></pre>
996</div>
997
998<div class="slide">
999 <h1>extends</h1>
1000
1001 <ul>
1002 <li>Each call to <code>extends</code> <strong>resets</strong> your parents</li>
1003 </ul>
1004
5d572684 1005 <h2 class="wrong">Wrong</h2>
b751d33f 1006
9b195048 1007 <pre><code>package EvilEmployee;
b751d33f 1008use Moose;
1009extends 'Person';
55906a14 1010extends 'Thief';</code></pre>
b751d33f 1011
5d572684 1012 <h2 class="right">Right</h2>
b751d33f 1013
9b195048 1014 <pre><code>package EvilEmployee;
b751d33f 1015use Moose;
55906a14 1016extends 'Person', 'Thief';</code></pre>
b751d33f 1017</div>
1018
1019<div class="slide">
1020 <h1>Extending un-Moose-y Parents</h1>
1021
1022 <pre><code>package My::LWP;
1023use Moose;
55906a14 1024extends 'LWP';</code></pre>
b751d33f 1025
1026 <ul>
1027 <li>No <code>Moose::Object</code>, so ...
1028 <ul>
1029 <li>No attribute-handling <code>new()</code></li>
1030 <li>No <code>BUILDARGS()</code> or <code>BUILD()</code></li>
1031 <li>No <code>DEMOLISH()</code></li>
1032 </ul>
1033 </li>
1034 <li>But see <code>MooseX::NonMoose</code> for a workaround</li>
1035 </ul>
1036</div>
1037
1038<div class="slide">
9fa24ee2 1039 <h1><code>override</code> and <code>super</code></h1>
9b195048 1040
1041 <ul>
9fa24ee2 1042 <li><code>override</code> is another method modifier</li>
9b195048 1043 <li>An alternative to Perl's <code>SUPER::</code></li>
f1273f9c 1044 <li><em>Declares</em> your intent to override a method</li>
9b195048 1045 </ul>
1046</div>
1047
1048<div class="slide">
9fa24ee2 1049 <h1><code>override</code> and <code>super</code></h1>
9b195048 1050
1051 <pre><code>package Employee;
1052use Moose;
1053
26164c8d 1054<span class="current incremental">extends 'Person';</span>
9b195048 1055
9fa24ee2 1056<span class="incremental">override</span> work =&gt; sub {
9b195048 1057 my $self = shift;
1058
debc93f8 1059 die "Pay me first"
1060 unless $self-&gt;got_paid;
9b195048 1061 <span class="incremental">super();</span>
1062}<span class="incremental">;</span></code></pre>
55906a14 1063</div>
9b195048 1064
1065<div class="slide">
1066 <h1>Caveat <code>super</code></h1>
1067
1068 <ul>
1069 <li>Mostly like <code>$self-&gt;SUPER::work(@_)</code></li>
1070 <li><strong>But</strong> cannot change <code>@_</code>!</li>
1071 <li>Binds the parent's method at compile time</li>
16efce7a 1072 <li>Parent determined by checking <code>Child-&gt;meta()-&gt;superclasses()</code></li>
9b195048 1073 </ul>
1074</div>
1075
1076<div class="slide">
e43c4c2a 1077 <h1>Minimal Attributes</h1>
9b195048 1078
1079 <ul>
1080 <li><code>has 'foo'</code></li>
1081 <li>Use <code>is =&gt; 'ro'</code> or <code>is =&gt; 'rw'</code></li>
1082 <li>Attributes without "is" have no accessors</li>
1083 </ul>
1084</div>
1085
1086<div class="slide">
1087 <h1>Read-write attributes</h1>
1088
1089 <pre><code>package Person;
1090use Moose;
1091
55906a14 1092has first_name =&gt; ( <span class="highlight">is =&gt; 'rw'</span> );
9b195048 1093
1094my $person =
1095 Person-&gt;new( first_name =&gt; 'Dave' );
1096
1097$person-&gt;first_name('Stevan');
1098print $person-&gt;first_name; # Stevan</code></pre>
1099
1100</div>
1101
1102<div class="slide">
1103 <h1>Read-only attributes</h1>
1104
1105 <pre><code>package Person;
1106use Moose;
1107
55906a14 1108has first_name =&gt; ( <span class="highlight">is =&gt; 'ro'</span> );
9b195048 1109
1110my $person =
1111 Person-&gt;new( first_name =&gt; 'Dave' );
1112
cda9a369 1113$person-&gt;first_name('Stevan'); # dies</code></pre>
9b195048 1114
1115</div>
1116
1117<div class="slide">
1118 <h1>There is More to Come</h1>
1119
1120 <ul>
1121 <li>Attributes have a <em>lot</em> of features</li>
1122 </ul>
1123</div>
1124
1125<div class="slide">
b751d33f 1126 <h1>Cleaning Up Moose Droppings</h1>
1127
1128 <pre><code>package Person;
1129use Moose;
1130
1131# true
203ca9ec 1132Person-&gt;can('extends');</code></pre>
b751d33f 1133
1134 <ul>
1135 <li>Not very hygienic</li>
1136 </ul>
1137</div>
1138
1139<div class="slide">
1140 <h1>Cleaning Up Moose Droppings</h1>
1141
1142 <pre><code>package Person;
1143use Moose;
1144
1145...
1146
511c9234 1147<span class="highlight">no Moose;</span>
1148
1149# false
203ca9ec 1150Person-&gt;can('extends');</code></pre>
511c9234 1151</div>
1152
1153<div class="slide">
1154 <h1>Cleaning Up Moose Droppings</h1>
1155
1156 <pre><code>package Person;
1157<span class="highlight">use namespace::autoclean;</span>
1158use Moose;
1159
1160...
b751d33f 1161
1162# false
203ca9ec 1163Person-&gt;can('extends');</code></pre>
b751d33f 1164</div>
1165
1166<div class="slide">
1167 <h1>No Moose</h1>
1168
1169 <ul>
78c5b76a 1170 <li>Cleaning up is a best practice</li>
1171 <li>Say <code>no Moose</code> at the end of a package</li>
debc93f8 1172 <li>Or <code>use namespace::autoclean</code> at the top</li>
b751d33f 1173 <li>Just do it</li>
1174 </ul>
1175</div>
1176
1177<div class="slide">
1178 <h1>Immutability</h1>
1179
1180 <ul>
511c9234 1181 <li><span style="font-family: URW Chancery L; font-size: 120%">Stevan's Incantation of Fleet-Footedness</span></li>
b751d33f 1182 </ul>
1183
1184 <pre><code>package Person;
1185use Moose;
1186
203ca9ec 1187<span class="highlight">__PACKAGE__-&gt;meta-&gt;make_immutable;</span></code></pre>
b751d33f 1188</div>
1189
9b195048 1190<div class="slide">
1191 <h1>What <code>make_immutable</code> does</h1>
1192
1193 <ul>
1194 <li>Magic</li>
1195 <li>Uses <code>eval</code> to "inline" a constructor</li>
1196 <li>Memoizes a lot of meta-information</li>
1197 <li>Makes loading your class slower</li>
1198 <li>Makes object creation <em>much</em> faster</li>
1199 </ul>
1200</div>
1201
1202<div class="slide">
1203 <h1>When to Immutabilize?</h1>
1204
1205 <ul>
1206 <li><em>Almost</em> always</li>
1207 <li>Startup time vs execution time</li>
1208 </ul>
1209</div>
1210
ddd87d75 1211<div class="slide">
55906a14 1212 <h1>Classes Summary</h1>
1213
1214 <ul>
1215 <li><code>use Moose</code></li>
1216 <li><code>Class-&gt;meta</code></li>
1217 <li><code>Moose::Object</code> base class</li>
9fa24ee2 1218 <li><code>extends</code>, <code>override</code>, and <code>super</code></li>
55906a14 1219 <li>Simple attributes: <code>has</code>, <code>is&nbsp;=&gt;&nbsp;'ro'</code>, &amp; <code>is&nbsp;=&gt;&nbsp;'rw'</code></li>
1220 <li><code>no Moose</code></li>
1221 <li><code>__PACKAGE__-&gt;meta-&gt;make_immutable</code></li>
1222 </ul>
1223</div>
1224
1225<div class="slide">
26164c8d 1226 <h1>Questions?</h1>
1227</div>
1228
1229<div class="slide">
ba1c9923 1230 <h1>Exercises</h1>
ddd87d75 1231
8d1ce1d7 1232 <pre># cd exercises
bcbafd14 1233
4a2daaa5 1234# perl bin/prove -lv t/00-prereq.t
ddd87d75 1235
bcbafd14 1236# perl install-moose (if needed)
ddd87d75 1237
ba1c9923 1238# perl bin/prove -lv t/01-classes.t
1239
ff112bdd 1240# edit lib/Person.pm and lib/Employee.pm
1241
55906a14 1242Iterate til this passes all its tests</pre>
1243</div>
1244
1245<div class="slide fake-slide0">
1246 <h1>Part 2: Roles</h1>
1247</div>
1248
1249<div class="slide">
1250 <h1>Just What Is a Role?</h1>
1251
1252 <ul>
1253 <li>Mixin? Interface? Trait?</li>
1254 <li>Yes ... and more!</li>
1255 </ul>
1256</div>
1257
1258<div class="slide">
debc93f8 1259 <h1>Roles - State <strong>and</strong> Behavior</h1>
55906a14 1260
1261 <pre><code>package HasPermissions;
1262use Moose::Role;
26164c8d 1263<span class="current incremental"># state
55906a14 1264has access_level =&gt; ( is =&gt; 'rw' );</span>
1265
1266<span class="incremental"># behavior
1267sub can_access {
1268 my $self = shift;
1269 my $required = shift;
1270
debc93f8 1271 return $self-&gt;access_level
1272 &gt;= $required;
55906a14 1273}</span></code></pre>
1274
1275</div>
1276
1277<div class="slide">
1278 <h1>Roles Can Define Interfaces</h1>
1279
1280 <pre><code>package Printable;
1281use Moose::Role;
1282
1283requires 'as_string';</code></pre>
1284</div>
1285
1286<div class="slide">
1287 <h1>Roles Can Do All Three</h1>
1288
1289 <pre><code>package Printable;
1290use Moose::Role;
1291
1292requires 'as_string';
1293
1294has has_been_printed =&gt; ( is =&gt; 'rw' );
1295
1296sub print {
1297 my $self = shift;
1298 print $self-&gt;as_string;
1299 $self-&gt;has_been_printed(1);
1300}</code></pre>
1301</div>
1302
1303<div class="slide">
1304 <h1>Classes Consume Roles</h1>
1305
1306 <pre><code>package Person;
1307use Moose;
1308
1309with 'HasPermissions';</code></pre>
1310</div>
1311
1312<div class="slide">
1313 <h1>Classes Consume Roles</h1>
1314
1315<pre><code>my $person = Person-&gt;new(
debc93f8 1316 first_name =&gt; 'Kenichi',
1317 last_name =&gt; 'Asai',
55906a14 1318 access_level =&gt; 42,
1319);
1320
1321print $person-&gt;full_name
1322 . ' has '
1323 . $person-&gt;can_access(42)
1324 ? 'great power'
1325 : 'little power';</code></pre>
1326</div>
1327
1328<div class="slide">
1329 <h1>Roles in Practice</h1>
1330
1331 <ul>
1332 <li>Consuming a role =~ inlining the role</li>
1333 </ul>
1334</div>
1335
1336<div class="slide">
1337 <h1>In Other Words ...</h1>
1338
1339<pre><code>package Person;
1340use Moose;
1341
1342<span class="highlight">with 'Printable';</span></code></pre>
1343</div>
1344
1345<div class="slide">
1346 <h1>In Other Words ...</h1>
1347
1348<pre><code>package Person;
1349use Moose;
1350
1351<span class="delete">with 'Printable';</span>
1352
23d5de74 1353<span class="highlight">has has_been_printed =&gt; ( is =&gt; 'rw' );
55906a14 1354
1355sub print {
1356 my $self = shift;
1357 print $self-&gt;as_string;
1358 $self-&gt;has_been_printed(1);
1359}</span></code></pre>
1360</div>
1361
1362<div class="slide">
1363 <h1>Except</h1>
1364
1365 <ul>
1366 <li>Role consumption is introspectable</li>
1367 </ul>
1368
1369 <pre><code>if ( Person-&gt;does('Printable') ) { ... }
1370
1371# or ...
1372
401d7961 1373Person-&gt;meta-&gt;does_role('Printable')</code></pre>
55906a14 1374
1375</div>
1376
1377<div class="slide">
1378 <h1>These Names Are the Same</h1>
1379
1380 <ul>
1381 <li>What if a role and class define the same method?</li>
1382 <li>A class's <em>local</em> methods win over the role's</li>
1383 <li>The role's methods win over the class's <em>inherited</em> methods</li>
1384 </ul>
1385</div>
1386
1387<div class="slide">
1388 <h1>Conflicts Between Roles</h1>
1389
1390 <ul>
1391 <li>Two roles with a method of the same name</li>
1392 <li>Generates a compile-time error when consumed by a class</li>
1393 </ul>
1394</div>
1395
1396<div class="slide">
1397 <h1>Conflict Example</h1>
1398
1399 <pre><code>package IsFragile;
1400use Moose::Role;
1401
1402sub break { ... }
1403
1404package CanBreakdance;
1405use Moose::Role;
1406
1407sub break { ... }</code></pre>
1408</div>
1409
1410<div class="slide">
1411 <h1>Conflict Example</h1>
1412
1413 <pre><code>package FragileDancer;
1414use Moose;
1415
1416<span class="highlight">with 'IsFragile', 'CanBreakdance';</span></code></pre>
1417
1418 <ul>
1419 <li>Only one <code>with</code>!</li>
1420 </ul>
1421</div>
1422
1423<div class="slide">
1424 <h1>Conflict Resolution</h1>
1425
1426 <ul>
0412f089 1427 <li>The consuming class must resolve the conflict by implementing the method</li>
55906a14 1428 <li>Can use some combination of method exclusion and aliasing</li>
1429 </ul>
1430</div>
1431
1432<div class="slide">
726473c6 1433 <h1>Conflicts Are a Smell</h1>
55906a14 1434
1435 <ul>
726473c6 1436 <li>Roles are about semantics!</li>
55906a14 1437 <li>Roles have a <em>meaning</em></li>
726473c6 1438 <li>Method name conflicts smell like bad design</li>
55906a14 1439 </ul>
1440</div>
1441
1442<div class="slide">
1a2103f5 1443 <h1>Roles With Roles</h1>
55906a14 1444
1445 <pre><code>package Comparable;
1446use Moose::Role;
1447
1448requires 'compare';</code></pre>
1449</div>
1450
1451<div class="slide">
1a2103f5 1452 <h1>Roles With Roles</h1>
55906a14 1453
1454 <pre><code>package TestsEquality;
1455use Moose::Role;
1456
1457with 'Comparable';
1458
1459sub is_equal {
1460 my $self = shift;
203ca9ec 1461 return $self-&gt;compare(@_) == 0;
55906a14 1462}</code></pre>
1463</div>
1464
1465<div class="slide">
1466 <h1>And then ...</h1>
1467
1468 <pre><code>package Integer;
1469use Moose;
1470
1471with 'TestsEquality';
1472
1473# Satisfies the Comparable role
1474sub compare { ... }
1475
203ca9ec 1476Integer-&gt;does('TestsEquality'); # true
1477Integer-&gt;does('Comparable'); # also true!</code></pre>
55906a14 1478</div>
1479
1480<div class="slide">
1481 <h1>Name Conflicts Between Roles</h1>
1482
1483 <pre><code>package HasSubProcess;
1484use Moose::Role;
1485
1486<span class="highlight">sub execute { ... }</span>
1487
1488package Killer;
1489use Moose::Role;
1490
1491with 'HasSubProcess';
1492
1493<span class="highlight">sub execute { ... }</span></code></pre>
1494</div>
1495
1496<div class="slide">
1497 <h1>Delayed Conflict</h1>
1498
9b515ca4 1499 <pre><code>package SysadminAssassin;
55906a14 1500with 'Killer';</code></pre>
1501
1502 <ul>
9b515ca4 1503 <li><code>SysadminAssassin</code> must implement its own <code>execute</code></li>
55906a14 1504 <li>But loading the <code>Killer</code> role by itself does not cause an error</li>
1505 </ul>
1506</div>
1507
1508<div class="slide">
1509 <h1>Roles as Interfaces</h1>
1510
1511 <ul>
1512 <li>Roles can <code>require</code> methods of their consumers</li>
1513 <li>Compile-time checks</li>
1514 <li>Method must exist when the role is consumed</li>
1515 </ul>
1516</div>
1517
1518<div class="slide">
1519 <h1>The Attribute Gotcha</h1>
1520
1521<pre><code>package HasSize;
1522use Moose::Role;
1523
26164c8d 1524<span class="current incremental">requires 'size';</span>
55906a14 1525
1526package Shirt;
1527use Moose;
1528
1529<span class="incremental">with 'HasSize';
1530
d7deb8a9 1531has size =&gt; ( is =&gt; 'ro' );</span></code></pre>
55906a14 1532</div>
1533
1534<div class="slide">
1535 <h1>The Attribute Gotcha Workaround</h1>
1536
1537 <pre><code>package HasSize;
1538use Moose::Role;
1539
1540requires 'size';
1541
1542package Shirt;
1543use Moose;
1544
d7deb8a9 1545has size =&gt; ( is =&gt; 'ro' );
55906a14 1546
1547with 'HasSize';</code></pre>
1548</div>
1549
1550<div class="slide">
1551 <h1>Compile-time Is a Lie</h1>
1552
1553 <ul>
1554 <li>Really, it's <em>package load</em> time</li>
1555 <li>That's run-time, but before the "real" run-time</li>
1556 <li>Moose does not rewire Perl, it's just sugar!</li>
1557 <li>(but <code>MooseX::Declare</code> <em>does</em> rewire Perl)</li>
1558 </ul>
1559</div>
1560
1561<div class="slide">
1562 <h1>Enforcing Roles</h1>
1563
1564 <pre><code>package Comparison;
1565use Moose;
1566
d7deb8a9 1567has [ 'left', 'right' ] =&gt; (
1568 is =&gt; 'ro',
1569 <span class="highlight">does =&gt; 'Comparable',</span>
55906a14 1570);
1571</code></pre>
1572
1573 <ul>
1574 <li>A sneak peek at type constraints</li>
1575 </ul>
1576</div>
1577
1578
1579<div class="slide">
1580 <h1>Roles Can Be Applied to Objects</h1>
1581
1582 <pre><code>use Moose::Util qw( apply_all_roles );
1583
203ca9ec 1584my $fragile_person = Person-&gt;new( ... );
debc93f8 1585apply_all_roles( $fragile_person,
1586 'IsFragile' );</code></pre>
55906a14 1587
1588 <ul>
1589 <li>Does not change the <code>Person</code> class</li>
1590 <li>Works with non-Moose classes, great for monkey-patching!</li>
1591 </ul>
1592</div>
1593
1594<div class="slide">
1595 <h1>Roles Are Dirty Too</h1>
1596
1597 <ul>
1598 <li>Once again, clean up those Moose droppings</li>
1599 </ul>
1600
1601 <pre><code>package Comparable;
1602use Moose::Role;
1603
1604requires 'compare';
1605
1606<span class="highlight">no Moose::Role;</span></code></pre>
1607
1608 <ul>
1609 <li>But roles cannot be made immutable</li>
1610 </ul>
1611</div>
1612
1613<div class="slide">
1614 <h1>The Zen of Roles</h1>
1615
1616 <ul>
1617 <li>Roles represent discrete units of ...
1618 <ul>
1619 <li>state</li>
1620 <li>behavior</li>
1621 <li>interface</li>
1622 </ul>
1623 </li>
1624 <li>Roles are shareable between unrelated classes</li>
1625 <li>Roles are what a class <em>does</em>, not what it <em>is</em></li>
1626 <li>Roles <em>add</em> functionality, inheritance <em>specializes</em></li>
1627 </ul>
1628</div>
1629
1630<div class="slide">
1631 <h1>Abstract Examples</h1>
1632
1633 <ul>
1634 <li>Human <em>@ISA</em> Animal</li>
1635 <li>Human <em>does</em> Toolmaker (as <em>does</em> Chimpanzee)</li>
1636 <li>Car <em>@ISA</em> Vehicle</li>
1637 <li>Car <em>does</em> HasEngine</li>
1638 </ul>
1639</div>
1640
1641<div class="slide">
1642 <h1>Real Examples</h1>
1643
1644 <ul>
1645 <li>Objects representing SQL database components and queries
1646 <ul>
1647 <li>Schema, Table, Column, ColumnAlias</li>
1648 <li>Select, Insert, Update, Delete</li>
1649 </ul>
1650 </li>
1651 </ul>
1652</div>
1653
1654<div class="slide">
1655 <h1>Real Examples</h1>
1656
1657 <ul>
1658 <li>Column and ColumnAlias both <em>do</em> ColumnLike</li>
1659 <li>ColumnLike things can be used in certain parts of queries</li>
1660 <li>All queries <em>do</em> HasWhereClause</li>
1661 <li>Select <em>does</em> Comparable and Selectable (for subselects)</li>
1662 <li>A where clause requires its components to <em>do</em> Comparable</li>
1663 </ul>
1664</div>
1665
1666<div class="slide">
26164c8d 1667 <h1>Roles Summary</h1>
1668
1669 <ul>
1670 <li>Roles can define an interface with <code>requires</code></li>
1671 <li>Roles can have state (attributes) and behavior (methods)</li>
1672 <li>Roles can mix interface, state, &amp; behavior</li>
1673 <li>Roles are composed (flattened) into classes</li>
1674 <li>Roles can do other roles</li>
1675 <li>Roles can be used as a type in APIs (must do Comparable)</li>
1676 </ul>
1677</div>
1678
1679<div class="slide">
1680 <h1>Questions?</h1>
1681</div>
1682
1683<div class="slide">
55906a14 1684 <h1>Exercises</h1>
1685
8d1ce1d7 1686 <pre># cd exercises
55906a14 1687# perl bin/prove -lv t/02-roles.t
1688
1689Iterate til this passes all its tests</pre>
1690</div>
1691
8d1ce1d7 1692<div class="slide fake-slide0">
1693 <h1>Part 3: Basic Attributes</h1>
1694</div>
1695
1696<div class="slide">
1697 <h1>Attributes Are Huge</h1>
1698
1699 <ul>
1700 <li>Moose's biggest feature</li>
1701 <li>The target of <em>many</em> MooseX modules</li>
1702 </ul>
1703</div>
1704
1705<div class="slide">
1706 <h1>Quick Review</h1>
1707
1708 <ul>
1709 <li>Declared with <code>has</code></li>
1710 <li>Read-only or read-write</li>
1711 </ul>
1712
1713 <pre><code>package Shirt;
1714use Moose;
1715
1716has 'color' =&gt; ( is =&gt; 'ro' );
1717has 'is_ripped' =&gt; ( is =&gt; 'rw' );</code></pre>
1718</div>
1719
1720<div class="slide">
1721 <h1>Required-ness</h1>
1722
1723 <ul>
1724 <li>Required means "must be passed to the constructor"</li>
1725 <li>But can be <code>undef</code></li>
1726 </ul>
1727</div>
1728
1729<div class="slide">
1730 <h1>Required-ness</h1>
1731
1732 <pre><code>package Person;
1733use Moose;
1734
1735has first_name =&gt; (
1736 is =&gt; 'ro',
26164c8d 1737 <span class="current incremental">required =&gt; 1,</span>
8d1ce1d7 1738);
1739
203ca9ec 1740<span class="incremental">Person-&gt;new( first_name =&gt; undef ); # ok
1741Person-&gt;new(); # kaboom</span></code></pre>
8d1ce1d7 1742</div>
1743
1744<div class="slide">
1745 <h1>Default and Builder</h1>
1746
1747 <ul>
1748 <li>Attributes can have defaults</li>
7504f80b 1749 <li>Simple non-reference scalars (number, string)</li>
8d1ce1d7 1750 <li>Subroutine reference</li>
1751 <li>A builder method</li>
1752 </ul>
1753</div>
1754
1755<div class="slide">
1756 <h1>Default</h1>
1757
1758 <ul>
1759 <li>Can be a non-reference scalar (including <code>undef</code>)</li>
1760 </ul>
1761
1762 <pre><code>package Person;
1763use Moose;
1764
1765has bank =&gt; (
1766 is =&gt; 'rw',
1767 default =&gt; 'Spire FCU',
1768);</code></pre>
1769</div>
1770
1771<div class="slide">
1772 <h1>Default</h1>
1773
1774 <ul>
1775 <li>Can be a subroutine reference</li>
1776 </ul>
1777
1778 <pre><code>package Person;
1779use Moose;
1780
1781has bank =&gt; (
1782 is =&gt; 'rw',
1783 default =&gt;
1784 sub { Bank-&gt;new(
1785 name =&gt; 'Spire FCU' ) },
1786);</code></pre>
1787</div>
1788
1789<div class="slide">
debc93f8 1790 <h1>Subroutine Reference Default</h1>
8d1ce1d7 1791
1792 <ul>
1793 <li>Called as a method on the object</li>
1794 <li>Called anew for each object</li>
1795 </ul>
1796</div>
1797
1798<div class="slide">
1799 <h1>Why No Other Reference Types?</h1>
1800
1801 <pre><code>package Person;
1802use Moose;
1803
1804has bank =&gt; (
1805 is =&gt; 'rw',
1806 <span class="wrong">default =&gt; Bank-&gt;new(
1807 name =&gt; 'Spire FCU' ),</span>
1808);</code></pre>
1809
1810 <ul>
1811 <li>Now <strong>every</strong> person shares the <strong>same</strong> Bank object!</li>
1812 </ul>
1813</div>
1814
1815<div class="slide">
1816 <h1>Defaulting to an Empty Reference</h1>
1817
1818 <pre><code>package Person;
1819use Moose;
1820
1821has packages =&gt; (
1822 is =&gt; 'rw',
1823 default =&gt; <span class="highlight">sub { [] }</span>,
1824);</code></pre>
1825</div>
1826
1827<div class="slide">
1828 <h1>What if I Want to Share?</h1>
1829
1830 <pre><code>package Person;
1831use Moose;
1832
1833my $highlander_bank =
78c5b76a 1834 Bank-&gt;new(
1835 name =&gt; 'Clan MacLeod Trust' );
8d1ce1d7 1836
1837has bank =&gt; (
1838 is =&gt; 'rw',
1839 default =&gt; sub { $highlander_bank },
1840);</code></pre>
1841</div>
1842
1843<div class="slide">
1844 <h1>Builder</h1>
1845
1846 <ul>
78c5b76a 1847 <li>A method <em>name</em></li>
6960f4e1 1848 <li>When called, this method returns the default value</li>
8d1ce1d7 1849 </ul>
1850</div>
1851
1852<div class="slide">
1853 <h1>Builder</h1>
1854
1855 <pre><code>package Person;
1856use Moose;
1857
1858has bank =&gt; (
1859 is =&gt; 'rw',
1860 builder =&gt; '_build_bank',
1861);
1862
1863sub _build_bank {
1864 my $self = shift;
debc93f8 1865 return Bank-&gt;new(
d7deb8a9 1866 name =&gt; 'Spire FCU' );
8d1ce1d7 1867}</code></pre>
1868</div>
1869
1870<div class="slide">
1871 <h1>Default vs Builder</h1>
1872
1873 <ul>
1874 <li>Use default for simple scalars</li>
1875 <li>Use default to return empty references</li>
1876 <li>Use default for <em>very</em> trivial subroutine references</li>
1877 <li>Use builder for everything else</li>
1878 </ul>
1879</div>
1880
1881<div class="slide">
1882 <h1>Builder Bonuses</h1>
1883
1884 <ul>
1885 <li>Can be overridden and method modified, because it's called by <em>name</em></li>
1886 <li>Roles can require a builder</li>
1887 </ul>
1888</div>
1889
1890<div class="slide">
1891 <h1>Role Requires Builder</h1>
1892
1893 <pre><code>package HasBank;
1894use Moose::Role;
1895
1896requires '_build_bank';
1897
1898has bank =&gt; (
1899 is =&gt; 'ro',
1900 builder =&gt; '_build_bank',
1901);</code></pre>
1902</div>
1903
1904<div class="slide">
debc93f8 1905 <h1>Lazy, Good for Nothin' Attributes</h1>
8d1ce1d7 1906
1907 <ul>
1908 <li>Normally, defaults are generated during object construction</li>
1909 <li>This can be expensive</li>
1910 <li>We want to default to <code>$self-&gt;size * 2</code>, but attribute initialization order is unpredictable</li>
1911 <li>Use lazy attributes!</li>
1912 </ul>
1913</div>
1914
1915<div class="slide">
1916 <h1>The Power of Dynamic Defaults</h1>
1917
1918 <pre><code>package Person;
1919use Moose;
1920
1921has shoe_size =&gt; (
6960f4e1 1922 is =&gt; 'ro',
b24924cc 1923 required =&gt; 1,
8d1ce1d7 1924);</code></pre>
1925</div>
1926
1927<div class="slide">
1928 <h1>The Power of Dynamic Defaults</h1>
1929
1930 <pre><code>has shoes =&gt; (
1931 is =&gt; 'ro',
1932 <span class="highlight">lazy =&gt; 1,</span>
d7deb8a9 1933 builder =&gt; '_build_shoes',
8d1ce1d7 1934);
1935
1936sub _build_shoes {
1937 my $self = shift;
1938
1939 return Shoes-&gt;new(
13cb03c7 1940 size =&gt; <span class="highlight">$self-&gt;shoe_size</span> );
8d1ce1d7 1941}</code></pre>
1942</div>
1943
1944<div class="slide">
1945 <h1>Lazy is Good</h1>
1946
1947 <ul>
1948 <li>Lazy defaults are executed when the attribute is read</li>
1949 <li>Can see other object attributes</li>
1950 <li>Still need to watch out for circular laziness</li>
1951 </ul>
1952</div>
1953
1954<div class="slide">
1955 <h1>Clearer and Predicate</h1>
1956
1957 <ul>
1958 <li>Attributes can have a value, including <code>undef</code>, or not</li>
1959 <li>Can clear the value with a clearer method</li>
1960 <li>Can check for the existence of a value with a predicate method</li>
1961 <li>By default, these methods are not created</li>
1962 </ul>
1963</div>
1964
1965<div class="slide">
1966 <h1>Clearer and Predicate</h1>
1967
1968 <pre><code>package Person;
1969use Moose;
1970
1971has account =&gt; (
1972 is =&gt; 'ro',
1973 lazy =&gt; 1,
1974 builder =&gt; '_build_account',
1975 <span class="highlight">clearer =&gt; '_clear_account',
1976 predicate =&gt; 'has_account',</span>
1977);</code></pre>
1978</div>
1979
1980<div class="slide">
1981 <h1>Clearer and Lazy Defaults</h1>
1982
1983 <ul>
1984 <li>Lazy defaults are good for computed attributes</li>
1985 <li>Clear the attribute when the source data changes</li>
1986 <li>Recalculated at next access</li>
1987 </ul>
1988</div>
1989
1990<div class="slide">
1991 <h1>Renaming constructor arguments</h1>
1992
1993 <ul>
1994 <li>By default, constructor names = attribute names</li>
1995 <li>Use <code>init_arg</code> to change this</li>
1996 <li>Set <code>init_arg =&gt; undef</code> to make it unconstructable</li>
1997 </ul>
1998</div>
1999
2000<div class="slide">
2001 <h1>Some <code>init_arg</code> examples</h1>
2002
2003 <pre><code>package Person;
2004use Moose;
2005
d7deb8a9 2006has shoe_size =&gt; (
8d1ce1d7 2007 is =&gt; 'ro',
2008 <span class="highlight">init_arg =&gt; 'foot_size',</span>
2009);
2010
203ca9ec 2011Person-&gt;new( <span class="wrong">shoe_size =&gt; 13</span> );
8d1ce1d7 2012
2013my $person =
203ca9ec 2014 Person-&gt;new( <span class="right">foot_size =&gt; 13</span> );
2015print $person-&gt;shoe_size;</code></pre>
8d1ce1d7 2016</div>
2017
2018<div class="slide">
2019 <h1>Some <code>init_arg</code> examples</h1>
2020
2021<pre><code>package Person;
2022use Moose;
2023
d7deb8a9 2024has shoes =&gt; (
8d1ce1d7 2025 is =&gt; 'ro',
2026 <span class="highlight">init_arg =&gt; undef,</span>
2027);
2028
203ca9ec 2029Person-&gt;new( <span class="wrong">shoes =&gt; Shoes-&gt;new</span> );</code></pre>
8d1ce1d7 2030</div>
2031
2032<div class="slide">
2033 <h1>Why Set <code>init_arg =&gt; undef</code>?</h1>
2034
2035 <ul>
2036 <li>Use this with a lazy default for attributes-as-cache</li>
2037 <li>Compute the value as needed</li>
2038 <li>Ensure that it is always generated correctly (not set by constructor)</li>
2039 <li>Use triggers or method modifiers (coming soon) to clear the value</li>
2040 </ul>
2041</div>
2042
2043<div class="slide">
2044 <h1>Attribute Inheritance</h1>
2045
2046 <ul>
2047 <li>By default, subclasses inherit attribute as-is</li>
2048 <li>Can change some attribute parameters in subclasses
2049 <ul>
2050 <li>default</li>
2051 <li>builder</li>
2052 <li>required</li>
2053 <li>lazy</li>
2054 <li>others we've not yet covered</li>
2055 </ul>
2056 </li>
2057 </ul>
2058</div>
2059
2060<div class="slide">
2061 <h1>Attribute Inheritance Example</h1>
2062
2063 <pre><code>package Employee;
2064use Moose;
2065
2066extends 'Person';
2067
2068has '<span class="highlight">+first_name</span>' =&gt; (
2069 default =&gt; 'Joe',
2070);</code></pre>
2071</div>
2072
2073<div class="slide">
2074 <h1>Attribute Inheritance Warning</h1>
2075
2076 <ul>
2077 <li>An attribute is a contract about a class's API</li>
2078 <li>Don't break that contract in a subclass</li>
2079 <li>Especially important in the context of types</li>
2080 </ul>
2081</div>
2082
2083<div class="slide">
2084 <h1>Changing Accessor Names</h1>
2085
2086 <pre><code>package Person;
2087use Moose;
2088
2089has first_name =&gt; (
bd857054 2090 <span class="highlight">accessor</span> =&gt; 'first_name',
8d1ce1d7 2091);</code></pre>
2092
2093 <ul>
2094 <li>The long-hand version of <code>is =&gt; 'rw'</code></li>
2095 </ul>
2096</div>
2097
2098<div class="slide">
2099 <h1>Changing Accessor Names</h1>
2100
2101 <pre><code>package Person;
2102use Moose;
2103
2104has first_name =&gt; (
2105 <span class="highlight">reader</span> =&gt; 'first_name',
2106 <span class="highlight">writer</span> =&gt; undef,
2107);</code></pre>
2108
2109 <ul>
2110 <li>The long-hand version of <code>is =&gt; 'ro'</code></li>
2111 </ul>
2112</div>
2113
2114
2115<div class="slide">
2116 <h1>Changing Accessor Names</h1>
2117
2118 <pre><code>package Person;
2119use Moose;
2120
2121has first_name =&gt; (
2122 <span class="highlight">reader</span> =&gt; 'get_first_name',
de668480 2123 <span class="highlight">writer</span> =&gt; 'set_first_name',
8d1ce1d7 2124);</code></pre>
2125</div>
2126
2127<div class="slide">
2128 <h1>Changing Accessor Names</h1>
2129
2130 <pre><code>package Person;
2131use Moose;
2132
2133has first_name =&gt; (
2134 <span class="highlight">is</span> =&gt; 'rw',
2135 <span class="highlight">writer</span> =&gt; '_first_name',
2136);</code></pre>
2137
2138 <ul>
be6689d2 2139 <li>Can also mix-and-match <code>is</code> and explicit names</li>
8d1ce1d7 2140 </ul>
2141</div>
2142
2143<div class="slide">
2144 <h1>ETOOMUCHTYPING</h1>
2145
2146 <ul>
2147 <li><code>MooseX::FollowPBP</code><br /><code>get_foo</code> and <code>set_foo</code></li>
2148 <li><code>MooseX::SemiAffordanceAccessor</code><br /><code>foo</code> and <code>set_foo</code></li>
2149 </ul>
2150</div>
2151
2152<div class="slide">
2153 <h1>ETOOMUCHTYPING</h1>
2154
2155 <pre><code>package Person;
2156use Moose;
2157<span class="highlight">use MooseX::SemiAffordanceAccessor;</span>
2158
2159has first_name =&gt; (
2160 is =&gt; 'rw',
2161);</code></pre>
2162
2163 <ul>
2164 <li>Creates <code>first_name</code> and <code>set_first_name</code></li>
2165 </ul>
2166</div>
2167
2168<div class="slide">
26164c8d 2169 <h1>Basic Attributes Summary</h1>
2170
2171 <ul>
2172 <li>Attributes can be <code>required</code></li>
2173 <li>Attributes can have a <code>default</code> or <code>builder</code></li>
2174 <li>Attributes with a default or builder can be <code>lazy</code></li>
2175 <li>Attributes can have a <code>clearer</code> and/or <code>predicate</code></li>
78c5b76a 2176 </ul>
2177</div>
2178
2179<div class="slide">
2180 <h1>Basic Attributes Summary</h1>
2181
2182 <ul>
26164c8d 2183 <li>An attribute's constructor name can be changed with <code>init_arg</code></li>
2184 <li>A subclass can alter its parents' attributes</li>
2185 <li>Attribute accessor names can be changed</li>
2186 </ul>
2187</div>
2188
2189<div class="slide">
2190 <h1>Questions?</h1>
2191</div>
2192
2193<div class="slide">
8d1ce1d7 2194 <h1>Exercises</h1>
2195
2196 <pre># cd exercises
debc93f8 2197# perl bin/prove -lv \
2198 t/03-basic-attributes.t
8d1ce1d7 2199
2200Iterate til this passes all its tests</pre>
2201</div>
2202
26164c8d 2203<div class="slide fake-slide0">
2204 <h1>Part 4: Method Modifiers</h1>
2205</div>
2206
2207<div class="slide">
2208 <h1>What is a Method Modifier</h1>
2209
2210 <ul>
2211 <li>Apply to an existing method</li>
78c5b76a 2212 <li>... that comes from a parent class, the current class, or a role</li>
26164c8d 2213 <li>Roles can provide modifiers that are applied at composition time</li>
2214 </ul>
2215</div>
2216
2217<div class="slide">
78c5b76a 2218 <h1>What Are Method Modifiers For?</h1>
26164c8d 2219
2220 <ul>
0a0c7e7c 2221 <li>"Inject" behavior</li>
26164c8d 2222 <li>Add behavior to generated methods (accessors, delegations)</li>
78c5b76a 2223 <li>Added from a role, can modify existing behavior</li>
26164c8d 2224 </ul>
2225</div>
2226
2227<div class="slide">
2228 <h1>Before and After</h1>
2229
2230 <ul>
2231 <li>Simplest modifiers - <code>before</code> and <code>after</code></li>
2232 <li>Guess when they run!</li>
2233 </ul>
2234</div>
2235
2236<div class="slide">
2237 <h1>Uses for <code>before</code></h1>
2238
2239 <ul>
2240 <li>As a pre-call check</li>
2241 </ul>
2242
2243 <pre><code>package Person;
2244use Moose;
2245
2246before work =&gt; sub {
2247 my $self = shift;
2248 die 'I have no job!'
2249 unless $self-&gt;has_title;
2250};</code></pre>
2251</div>
2252
2253<div class="slide">
2254 <h1>Uses for <code>before</code></h1>
2255
2256 <ul>
2257 <li>Logging/Debugging</li>
2258 </ul>
2259
2260 <pre><code>package Person;
2261use Moose;
2262
2263before work =&gt; sub {
2264 my $self = shift;
2265 return unless $DEBUG;
2266
debc93f8 2267 warn "Called work on ",
2268 $self-&gt;full_name,
26164c8d 2269 "with the arguments: [@_]\n";
2270};</code></pre>
2271</div>
2272
2273<div class="slide">
2274 <h1>Uses for <code>after</code></h1>
2275
2276 <ul>
2277 <li>Also works for logging/debugging</li>
2278 <li>Post-X side-effects (recording audit info)</li>
2279 </ul>
2280
2281 <pre><code>package Person;
2282use Moose;
2283
2284after work =&gt; sub {
2285 my $self = shift;
2286 $self-&gt;work_count(
2287 $self-&gt;work_count + 1 );
2288};</code></pre>
2289</div>
2290
2291<div class="slide">
2292 <h1>Other Uses</h1>
2293
2294 <ul>
2295 <li>Modifiers are useful for adding behavior to generated methods</li>
2296 </ul>
2297</div>
2298
2299<div class="slide">
debc93f8 2300 <h1>More Modifier Examples</h1>
26164c8d 2301
2302 <pre><code>has password =&gt; (
2303 is =&gt; 'rw',
2304 clearer =&gt; 'clear_password',
2305);
26164c8d 2306has hashed_password =&gt; (
2307 is =&gt; 'ro',
2308 builder =&gt; '_build_hashed_password',
2309 clearer =&gt; '_clear_hashed_password',
2310);
26164c8d 2311after clear_password =&gt; sub {
2312 my $self = shift;
2313 $self-&gt;_clear_hashed_password;
2314};</code></pre>
2315</div>
2316
2317<div class="slide">
2318 <h1><code>before</code> and <code>after</code> Limitations</h1>
2319
2320 <ul>
2321 <li>Cannot alter method parameters</li>
2322 <li>Cannot alter return value</li>
2323 <li>But <strong>can</strong> throw an exception</li>
2324 </ul>
2325</div>
2326
2327<div class="slide">
2328 <h1>The <code>around</code> Modifier</h1>
2329
2330 <ul>
2331 <li>The big gun</li>
2332 <li>Can alter parameters <strong>and/or</strong> return values</li>
2333 <li>Can skip calling the wrapped method entirely</li>
2334 </ul>
2335</div>
2336
2337<div class="slide">
2338 <h1>The power of <code>around</code></h1>
2339
2340 <pre><code>around insert =&gt; sub {
2341 my $orig = shift;
2342 my $self = shift;
2343
2344 $self-&gt;_validate_insert(@_);
2345
2346 my $new_user =
2347 $self-&gt;$orig(
2348 $self-&gt;_munge_insert(@_) );
2349
203ca9ec 2350 $new_user-&gt;_assign_uri;
26164c8d 2351 return $new_user;
2352};</code></pre>
2353</div>
2354
2355<div class="slide">
2356 <h1>Modifier Order</h1>
2357
2358 <ul>
e5792e20 2359 <li>Before runs in order from last to first</li>
26164c8d 2360 <li>After runs in order from first to last</li>
2361 <li>Around runs in order from last to first</li>
2362 </ul>
2363</div>
2364
2365<div class="slide">
2366 <h1>Modifier Order Illustrated</h1>
2367
2368<pre>
2369<span class="current incremental">before 2
2370 before 1</span>
2371 <span class="incremental">around 2
2372 around 1</span>
2373 <span class="incremental">wrapped method</span>
2374 <span class="incremental">around 1
2375 around 2</span>
2376 <span class="incremental">after 1
2377after 2</span>
2378</pre>
2379</div>
2380
2381<div class="slide">
2382 <h1>Modifiers in Roles</h1>
2383
2384 <ul>
2385 <li>Roles can use these modifiers</li>
2386 <li>Very powerful!</li>
2387 </ul>
2388</div>
2389
2390<div class="slide">
2391 <h1>Modifiers in Roles</h1>
2392
2393 <pre><code>package IsUnreliable;
2394use Moose::Role;
2395
2396<span class="highlight">requires 'run';
2397
2398around run</span> =&gt; sub {
2399 my $orig = shift;
2400 my $self = shift;
2401
2402 return if rand(1) &lt; 0.5;
2403
2404 return $self-&gt;$orig(@_);
2405};</code></pre>
2406</div>
2407
2408<div class="slide">
2409 <h1>Augment and Inner</h1>
2410
2411 <ul>
2412 <li>Inverted <code>super</code></li>
2413 <li>From least- to most-specific</li>
78c5b76a 2414 <li>Like Mason's autohandler feature</li>
26164c8d 2415 <li>Grandparent to parent to child</li>
2416 <li>Not allowed in roles</li>
2417 </ul>
2418</div>
2419
2420<div class="slide">
2421 <h1>Augment and Inner</h1>
2422
62e6bee0 2423 <pre class="medium"><code>package Document;
26164c8d 2424
2425sub xml { '&lt;doc&gt;' . <span class="highlight">inner()</span> . '&lt;/doc&gt;' }
2426
2427package Report;
2428extends 'Document';
c3ccfa10 2429<span class="highlight">augment xml</span> =&gt;
62e6bee0 2430 sub { my $self = shift;
2431 $self-&gt;title() . <span class="highlight">inner()</span> . $self-&gt;summary() };
26164c8d 2432
2433package TPSReport;
2434extends 'Report';
c3ccfa10 2435<span class="highlight">augment xml</span> =&gt;
62e6bee0 2436 sub { my $self = shift;
2437 $self-&gt;tps_xml() . <span class="highlight">inner()</span> };</code></pre>
26164c8d 2438</div>
2439
2440<div class="slide">
2441 <h1>Augment and Inner</h1>
2442
2443 <ul>
2444 <li>When we call <code>$tps-&gt;xml</code> ...
2445 <ul>
2446 <li><code>Document-&gt;xml</code></li>
2447 <li><code>Report-&gt;xml</code></li>
2448 <li><code>TPSReport-&gt;xml</code></li>
2449 </ul>
2450 </li>
2451 </ul>
2452</div>
2453
2454<div class="slide">
2455 <h1>Augment and Inner Usage</h1>
2456
2457 <ul>
2458 <li>Call <code>inner()</code> to "fill in the blank"</li>
2459 <li>Requires designing for subclassing</li>
2460 <li>Call <code>inner()</code> in the terminal class, just in case</li>
2461 </ul>
2462</div>
2463
2464<div class="slide">
5d572684 2465 <h1>Method Modifiers Summary</h1>
2466
2467 <ul>
2468 <li>Use <code>before</code> and <code>after</code> for ...
2469 <ul>
2470 <li>logging</li>
2471 <li>pre- or post-validation</li>
2472 <li>to add behavior to generated methods</li>
2473 </ul>
2474 </li>
2475 <li>These two modifiers cannot change parameters or return values</li>
2476 </ul>
2477</div>
2478
2479<div class="slide">
2480 <h1>Method Modifiers Summary</h1>
2481
2482 <ul>
2483 <li>Use <code>around</code> to ...
2484 <ul>
2485 <li>alter parameters passed to the original method</li>
2486 <li>alter the return value of the original method</li>
2487 <li>not call the original method at all (or call a <em>different</em> method)</li>
2488 </ul>
2489 </li>
2490 </ul>
2491</div>
2492
2493<div class="slide">
2494 <h1>Method Modifiers Summary</h1>
2495
2496 <ul>
2497 <li>When using modifiers in a role, require the modified method</li>
2498 <li>Use <code>augment</code> and <code>inner</code> to invert the normal subclassing flow ...
2499 <ul>
2500 <li>Least- to most-specific (parents to children)</li>
2501 <li>Build in "insertability" (stick more stuff in the "middle")</li>
2502 </ul>
2503 </li>
2504 <li>Always call <code>inner</code> in the most specific subclass to allow for future extension</li>
2505 </ul>
2506</div>
2507
2508<div class="slide">
26164c8d 2509 <h1>Questions?</h1>
2510</div>
2511
2512<div class="slide">
2513 <h1>Exercises</h1>
2514
2515 <pre># cd exercises
debc93f8 2516# perl bin/prove -lv \
2517 t/04-method-modifiers.t
26164c8d 2518
2519Iterate til this passes all its tests</pre>
2520</div>
2521
5d572684 2522<div class="slide fake-slide0">
2523 <h1>Part 5: Types</h1>
2524</div>
2525
636ceec1 2526<div class="slide">
2527 <h1>A Type System for Perl</h1>
2528
2529 <ul>
2530 <li>Sort of ...</li>
2531 <li><em>Variables</em> are not typed</li>
2532 <li>Attributes can have types</li>
2533 <li>MooseX modules let you define method signatures</li>
2534 </ul>
2535</div>
2536
2537<div class="slide">
2538 <h1>Components of a Moose Type</h1>
2539
2540 <ul>
2541 <li>A type is a name and a constraint</li>
2542 <li>Types have a hierarchy</li>
2543 <li>Constraints are cumulative from parents</li>
2544 <li>Types can have associated coercions</li>
2545 </ul>
2546</div>
2547
2548<div class="slide">
2549 <h1>Built-in Type Hierarchy</h1>
2550
2551 <pre>
2552Any
2553Item
2554 Bool
2555 Maybe[`a]
2556 Undef
2557 Defined
2558 Value
78c5b76a 2559 Str
2560 Num
2561 Int
2562 ClassName
913a61d3 2563 RoleName
636ceec1 2564</pre>
2565</div>
2566
2567<div class="slide">
2568 <h1>Built-in Type Hierarchy</h1>
2569
2570<pre>
2571(Item)
2572 (Defined)
b9a2a53f 2573 (Value)
636ceec1 2574 Ref
2575 ScalarRef
2576 ArrayRef[`a]
2577 HashRef[`a]
2578 CodeRef
2579 RegexpRef
2580 GlobRef
78c5b76a 2581 FileHandle
636ceec1 2582 Object
2583</pre>
2584</div>
2585
2586<div class="slide">
2587 <h1>Bool</h1>
2588
2589 <h2>True</h2>
2590 <pre><code>1
2591924.1
2592'true'
2593{}</code></pre>
2594
2595 <h2>False</h2>
2596 <pre><code>0
25970.0
2598'0'
2599undef</code></pre>
2600
2601 <ul>
2602 <li>Like Perl's <code>if ($foo)</code></li>
2603 </ul>
2604</div>
2605
2606<div class="slide">
2607 <h1>Value (and subtypes)</h1>
2608
2609 <ul>
b59551bc 2610 <li><code>Value</code> is true when <code>! ref $thing</code></li>
2611 <li><code>Value</code> and <code>Str</code> are effectively the same, but <code>Str</code> is more expressive</li>
84326b8a 2612 <li><code>Num</code> is true when a <code>$scalar</code> looks like a number</li>
636ceec1 2613 <li>An overloaded object which numifies does not pass the <code>Num</code> constraint!</li>
2614 <li>Perl 5's overloading is hopelessly broken</li>
2615 </ul>
2616</div>
2617
2618<div class="slide">
2619 <h1>ClassName and RoleName</h1>
2620
2621 <ul>
2622 <li>A string with a package name</li>
2623 <li>The package <strong>must already be loaded</strong></li>
2624 </ul>
2625</div>
2626
2627<div class="slide">
2628 <h1>Parameterizable Types</h1>
2629
2630 <ul>
2631 <li>What does <code>ArrayRef[`a]</code> mean?</li>
2632 <li><code>s/`a/Int/</code> (or <code>Str</code> or ...)</li>
2633 <li>When you use it you can write ...
2634 <ul>
2635 <li><code>ArrayRef</code> (== <code>ArrayRef[Item]</code>)</li>
2636 <li><code>ArrayRef[Str]</code></li>
2637 <li><code>ArrayRef[MyTypeName]</code></li>
2638 <li><code>ArrayRef[HashRef[Maybe[Int]]]</code></li>
2639 </ul>
2640 </li>
2641 </ul>
2642</div>
2643
2644<div class="slide">
2645 <h1>Maybe[`a]</h1>
2646
2647 <ul>
2648 <li>Maybe means either the named type or <code>undef</code></li>
2649 <li><code>Maybe[Int]</code> accepts integers or <code>undef</code></li>
2650 </ul>
2651</div>
2652
2653<div class="slide">
b59551bc 2654 <h1>Type Union</h1>
636ceec1 2655
2656 <ul>
2657 <li>This or that (or that or ...)</li>
2658 <li><code>Int | ArrayRef[Int]</code></li>
2659 <li>But use a coercion instead when possible</li>
b59551bc 2660 <li>Or use a <code>role_type</code>, <code>duck_type</code>, or anything not a union</li>
2661 <li>A union is often a code smell</li>
636ceec1 2662 </ul>
2663</div>
2664
2665<div class="slide">
2666 <h1>Making Your Own Types</h1>
2667
2668 <pre><code>use Moose::Util::TypeConstraints;
2669
2670<span class="incremental current">subtype 'PositiveInt',</span>
2671 <span class="incremental">as 'Int',</span>
2672 <span class="incremental">where { $_ &gt; 0 },</span>
debc93f8 2673 <span class="incremental">message
2674 { "The value you provided ($_)"
2675 . " was not a positive int." };</span>
636ceec1 2676
2677has size =&gt; (
2678 is =&gt; 'ro',
2679 <span class="incremental">isa =&gt; 'PositiveInt',</span>
2680);</code></pre>
2681</div>
2682
2683<div class="slide">
2684 <h1>Automatic Types</h1>
2685
2686 <ul>
2687 <li>Moose creates a type for every Moose class and role</li>
2688 <li>Unknown names are assumed to be classes</li>
2689 </ul>
2690</div>
2691
2692<div class="slide">
2693 <h1>Automatic Types</h1>
2694
2695 <pre><code>package Employee;
2696use Moose;
2697
2698has manager =&gt; (
2699 is =&gt; 'rw',
2700 <span class="highlight">isa =&gt; 'Employee',</span>
2701);
2702
2703has start_date =&gt; (
2704 is =&gt; 'ro',
2705 <span class="highlight">isa =&gt; 'DateTime',</span>
2706);</code></pre>
2707</div>
2708
2709<div class="slide">
2710 <h1>Subtype Shortcuts - <code>class_type</code></h1>
2711
2712 <pre><code>use Moose::Util::TypeConstraints;
78c5b76a 2713class_type 'DateTime';</code></pre>
2714
2715<hr />
636ceec1 2716
6b241000 2717<pre><code>subtype 'DateTime',
636ceec1 2718 as 'Object',
2719 where { $_-&gt;isa('DateTime') },
2720 message { ... };</code></pre>
2721</div>
2722
2723<div class="slide">
2724 <h1>Subtype Shortcuts - <code>role_type</code></h1>
2725
2726 <pre><code>use Moose::Util::TypeConstraints;
78c5b76a 2727role_type 'Printable';</coe></pre>
636ceec1 2728
78c5b76a 2729<hr />
2730
2731<pre><code>subtype 'Printable',
6b241000 2732 as 'Object',
636ceec1 2733 where
2734 { Moose::Util::does_role(
2735 $_, 'Printable' ) },
2736 message { ... };</code></pre>
2737</div>
2738
2739<div class="slide">
2740 <h1>Subtype Shortcuts - <code>duck_type</code></h1>
2741
2742 <pre><code>use Moose::Util::TypeConstraints;
78c5b76a 2743duck_type Car =&gt; qw( run break_down );</code></pre>
2744
2745<hr />
636ceec1 2746
78c5b76a 2747<pre><code>subtype 'Car',
636ceec1 2748 as 'Object',
2749 where { all { $_-&gt;can($_) }
2750 qw( run break_down ) },
2751 message { ... };</code></pre>
2752</div>
2753
2754<div class="slide">
2755 <h1>Subtype Shortcuts - <code>enum</code></h1>
2756
2757 <pre><code>use Moose::Util::TypeConstraints;
f5cc2f3e 2758enum Color =&gt; qw( red blue green );</code></pre>
78c5b76a 2759
2760<hr />
636ceec1 2761
78c5b76a 2762<pre><code>my %ok = map { $_ =&gt; 1 }
debc93f8 2763 qw( red blue green );
2764
6b241000 2765subtype 'Color'
636ceec1 2766 as 'Str',
2767 where { $ok{$_} },
2768 message { ... };</code></pre>
2769</div>
2770
2771<div class="slide">
2772 <h1>Anonymous Subtypes</h1>
2773
2774 <pre><code>package Person;
2775
2776<span class="highlight">my $posint =
2777 subtype as 'Int', where { $_ &gt; 0 };</span>
2778
2779has size =&gt; (
2780 is =&gt; 'ro',
2781 <span class="highlight">isa =&gt; $posint,</span>
2782);</code></pre>
2783
2784 <ul>
2785 <li>Shortcuts have anonymous forms as well</li>
2786 </ul>
2787</div>
2788
2789<div class="slide">
2790 <h1>Coercions</h1>
2791
2792 <pre><code>use Moose::Util::TypeConstraints;
2793
2794subtype 'UCStr',
2795 as 'Str',
debc93f8 2796 where { ! /[a-z]/ };</code></pre>
2797</div>
2798
2799<div class="slide">
2800 <h1>Coercions</h1>
636ceec1 2801
debc93f8 2802 <pre><code><span class="incremental current">coerce 'UCStr',</span>
636ceec1 2803 <span class="incremental">from 'Str',</span>
2804 <span class="incremental">via { uc };</span>
2805
2806has shouty_name =&gt; (
2807 is =&gt; 'ro',
2808 isa =&gt; 'UCStr',
2809 <span class="incremental">coerce =&gt; 1,</span>
2810);</code></pre>
2811</div>
2812
2813<div class="slide">
b59551bc 2814 <h1>Coercion Examples</h1>
2815
2816 <pre><code>subtype 'My::DateTime',
2817 as class_type 'DateTime';
2818
2819coerce 'My::DateTime',
2820 from 'HashRef',
2821 via { DateTime-&gt;new( %{$_} ) };
2822
2823coerce 'My::DateTime',
2824 from 'Int',
2825 via { DateTime-&gt;from_epoch(
2826 epoch =&gt; $_ ) };</code></pre>
2827
2828 <ul>
2829 <li>Use coercion to inflate a value</li>
2830 </ul>
2831</div>
2832
2833<div class="slide">
2834 <h1>Coercion Examples</h1>
2835
2836 <pre><code>coerce 'ArrayRef[Int]',
2837 from 'Int',
2838 via { [ $_ ] };</code></pre>
2839
2840 <ul>
4bb8a45d 2841 <li>Instead of union - <code style="white-space: nowrap">Int | ArrayRef[Int]</code></li>
b59551bc 2842 </ul>
2843</div>
2844
b59551bc 2845<div class="slide">
2846 <h1>Using Types with Attributes</h1>
2847
2848 <pre><code>package Person;
2849
b59551bc 2850has height =&gt; (
2851 is =&gt; 'rw',
2852 <span class="highlight">isa =&gt; 'Num',</span>
2853);
2854
2855has favorite_numbers =&gt; (
2856 is =&gt; 'rw',
2857 <span class="highlight">isa =&gt; 'ArrayRef[Int]',
2858 coerce =&gt; 1,</span>
2859);</code></pre>
2860</div>
2861
2862<div class="slide">
ee2e815e 2863 <h1>More Droppings</h1>
2864
2865 <ul>
0f55e69e 2866 <li><code>Moose::Util::TypeConstraints</code> also needs cleanup</li>
ee2e815e 2867 </ul>
2868
2869 <pre><code>package Person;
2870
2871use Moose;
2872use Moose::Util::TypeConstraints;
2873
2874subtype ...;
2875
2876no Moose;
2877<span class="highlight">no Moose::Util::TypeConstraints;</span></code></pre>
2878</div>
2879
2880<div class="slide">
5bc2184a 2881 <h1>Questions So Far?</h1>
2882</div>
2883
2884<div class="slide">
2885 <h1>Exercises</h1>
2886
2887 <pre># cd exercises
2888# perl bin/prove -lv t/05-types.t
2889
2890Iterate til this passes all its tests</pre>
2891</div>
2892
2893<div class="slide">
b59551bc 2894 <h1>Typed Methods (Low-tech)</h1>
2895
2896 <pre class="medium"><code>package Person;
2897<span class="highlight">use MooseX::Params::Validate qw( validated_list );</span>
2898
2899sub work {
2900 my $self = shift;
2901 <span class="highlight">my ( $tasks, $can_rest ) =
2902 validated_list(
2903 \@_,
2904 tasks =&gt;
2905 { isa =&gt; 'ArrayRef[Task]',
64864ac0 2906 coerce =&gt; 1 },
b59551bc 2907 can_rest =&gt;
2908 { isa =&gt; 'Bool',
2909 default =&gt; 0 },
2910 );</span>
b59551bc 2911 ...
2912}</code></pre>
68af922f 2913</div>
b59551bc 2914
2915<div class="slide">
2916 <h1>Typed Methods (High-tech)</h1>
2917
2918 <pre class="medium"><code>package Person;
2919
2920<span class="highlight">use MooseX::Method::Signatures;</span>
2921
2922<span class="highlight">method work ( ArrayRef[Task] :$tasks,
2923 Bool :$can_rest = 0 )</span> {
2924 my $self = shift;
2925
2926 ...
2927}</code></pre>
68af922f 2928</div>
b59551bc 2929
2930<div class="slide">
636ceec1 2931 <h1>Digression: The Type Registry</h1>
2932
2933 <ul>
0f55e69e 2934 <li>Types are actually <code>Moose::Meta::TypeConstraints</code> <em>objects</em></li>
636ceec1 2935 <li>Stored in an interpreter-global registry mapping names to objects</li>
2936 </ul>
2937</div>
2938
2939<div class="slide">
2940 <h1>Danger!</h1>
2941
2942 <ul>
2943 <li>Coercions are attached to type objects</li>
2944 <li>Therefore also global</li>
2945 <li>Name conflicts between modules!</li>
2946 <li>Coercion conflicts between modules!</li>
2947 </ul>
2948</div>
2949
2950<div class="slide">
b59551bc 2951 <h1>Namespace Fix</h1>
636ceec1 2952
2953 <ul>
2954 <li>Use some sort of pseudo-namespacing scheme</li>
2955 <li>Never coerce directly to a class name, or <em>to</em> built-in types</li>
2956 </ul>
2957</div>
2958
2959<div class="slide">
2960 <h1>Namespace Fix</h1>
2961
2962 <pre><code>use Moose::Util::TypeConstraints;
636ceec1 2963subtype <span class="highlight">'MyApp::Type::DateTime',</span>
2964 as 'DateTime';
2965
2966<span class="highlight">coerce 'MyApp::Type::DateTime',</span>
2967 from 'HashRef',
2968 via { DateTime-&gt;new( %{$_} ) }
2969
2970has creation_date =&gt; (
2971 is =&gt; 'ro',
2972 <span class="highlight">isa =&gt; 'MyApp::Type::DateTime',</span>
2973 coerce =&gt; 1,
2974);</code></pre>
2975</div>
2976
2977<div class="slide">
2978 <h1>Namespace Fix</h1>
2979
2980 <pre><code>subtype 'MyApp::Type::ArrayOfInt',
2981 as 'ArrayRef[Int]';
2982
2983coerce 'MyApp::Type::ArrayOfInt',
2984 from 'Int',
2985 via { [ $_ ] };</code></pre>
2986</div>
636ceec1 2987
2988<div class="slide">
b59551bc 2989 <h1>Namespace Fix Pros and Cons</h1>
636ceec1 2990
b59551bc 2991 <ul>
2992 <li><span class="right">Relatively simple</span></li>
2993 <li><span class="right">Already built into Moose</span></li>
2994 <li><span class="wrong">Conflates type and module namespaces</span></li>
2995 <li><span class="wrong">Type names are strings, so typos are easy to make and may be hard to find</span></li>
2996 </ul>
2997</div>
636ceec1 2998
b59551bc 2999<div class="slide">
3000 <h1>MooseX::Types</h1>
636ceec1 3001
b59551bc 3002 <pre><code>package MyApp::Types;
3003
3004use MooseX::Types
3005 <span class="highlight">-declare =&gt; [ qw( ArrayOfInt ) ]</span>;
3006use MooseX::Types::Moose
3007 qw( ArrayRef Int );
3008
3009subtype <span class="highlight">ArrayOfInt</span>,
3010 as ArrayRef[Int];
3011
3012coerce <span class="highlight">ArrayOfInt</span>
3013 from Int,
3014 via { [ $_ ] };</code></pre>
3015</div>
3016
3017<div class="slide">
3018 <h1>MooseX::Types</h1>
3019
3020 <pre><code>package MyApp::Account;
3021
3022use MyApp::Types qw( ArrayOfInt );
3023
d7deb8a9 3024has transaction_history =&gt; (
3025 is =&gt; 'rw',
3026 isa =&gt; ArrayOfInt,
b59551bc 3027);</code></pre>
68af922f 3028</div>
b59551bc 3029
3030<div class="slide">
3031 <h1>MooseX::Types</h1>
636ceec1 3032
3033 <ul>
b59551bc 3034 <li>Type names are exported functions, catches typos early</li>
3035 <li>Types must be pre-declared</li>
78c5b76a 3036 <li>Types are stored with namespaces internally, but you use short names</li>
b59551bc 3037 <li>Import existing Moose types as functions from <code>MooseX::Types::Moose</code></li>
3038 <li>Still need string names for things like <code>ArrayRef['Email::Address']</code></li>
636ceec1 3039 </ul>
3040</div>
3041
3042<div class="slide">
b59551bc 3043 <h1>MooseX::Types Pros and Cons</h1>
636ceec1 3044
b59551bc 3045 <ul>
3046 <li><span class="right">Catches typos at compile time</span></li>
3047 <li><span class="right">Automatic namespacing</span></li>
3048 <li><span class="wrong">One more thing to install and learn</span></li>
78c5b76a 3049 <li><span class="wrong">Every name is typed twice (declared and then defined)</span></li>
b59551bc 3050 <li><span class="wrong">Still stuck with strings when referring to class or role names</span></li>
68af922f 3051 <li><span class="wrong">Coercion gotcha from earlier still applies to types exported from <code>MooseX::Types::Moose</code></span></li>
b59551bc 3052 </ul>
3053</div>
3054
3055<div class="slide">
3056 <h1>Recommendation</h1>
636ceec1 3057
3058 <ul>
b59551bc 3059 <li>Use <code>MooseX::Types</code></li>
3060 <li>Compile time error catching and automatic namespacing are huge wins</li>
3061 <li>Docs from <code>Moose::Util::TypeConstraints</code> are 98% compatible with <code>MooseX::Types</code> anyway</li>
3062 <li>A function exported by a type library works wherever a type name would</li>
636ceec1 3063 </ul>
3064</div>
3065
3066<div class="slide">
3067 <h1>Questions?</h1>
3068</div>
3069
5d572684 3070<div class="slide fake-slide0">
3071 <h1>Part 6: Advanced Attributes</h1>
3072</div>
3073
3074<div class="slide">
3075 <h1>Weak References</h1>
3076
3077 <ul>
3078 <li>A weak reference lets you avoid circular references</li>
3079 <li>Weak references do not increase the reference count</li>
3080 </ul>
3081</div>
3082
3083<div class="slide">
3084 <h1>Circular Reference Illustrated</h1>
3085
3086 <pre><code>my $foo = {};
3087my $bar = { foo =&gt; $foo };
3088$foo-&gt;{bar} = $bar;</code></pre>
3089
3090 <ul>
3091 <li>Neither <code>$foo</code> nor <code>$bar</code> go out of scope<br />
3092 (until the program exits)</li>
3093 </ul>
3094</div>
3095
3096<div class="slide">
3097 <h1>Weakening Circular References</h1>
3098
3099 <pre><code>use Scalar::Util qw( weaken );
3100
3101my $foo = {};
3102my $bar = { foo =&gt; $foo };
3103$foo-&gt;{bar} = $bar;
3104weaken $foo-&gt;{bar}</code></pre>
3105
3106 <ul>
3107 <li>When <code>$bar</code> goes out of scope, <code>$foo-&gt;{bar}</code> becomes <code>undef</code></li>
3108 </ul>
3109</div>
3110
3111<div class="slide">
3112 <h1>Circular References in Attributes</h1>
3113
3114 <pre><code>package Person;
3115use Moose;
3116
3117has name =&gt; ( is =&gt; 'ro' );
3118has friend =&gt; ( is =&gt; 'rw' );
3119
3120my $alice = Person-&gt;new( name =&gt; 'Alice' );
3121my $bob = Person-&gt;new( name =&gt; 'Bob' );
3122$bob-&gt;friend($alice);
3123$alice-&gt;friend($bob);</code></pre>
3124</div>
3125
3126<div class="slide">
3127 <h1>The Fix</h1>
3128
3129 <pre><code>package Person;
3130use Moose;
3131
3132has name =&gt; ( is =&gt; 'ro' );
debc93f8 3133has friend =&gt; ( is =&gt; 'rw',
3134 <span class="highlight">weak_ref =&gt; 1</span> );
5d572684 3135
3136my $alice = Person-&gt;new( name =&gt; 'Alice' );
3137my $bob = Person-&gt;new( name =&gt; 'Bob' );
3138$bob-&gt;friend($alice);
3139$alice-&gt;friend($bob);</code></pre>
3140</div>
3141
3142<div class="slide">
3143 <h1>Under the Hood</h1>
3144
3145 <ul>
3146 <li>A <code>weak_ref</code> attribute calls <code>weaken</code> ...
3147 <ul>
3148 <li>during object construction</li>
3149 <li>when the attribute is set via a writer</li>
3150 </ul>
3151 </li>
3152 </ul>
3153</div>
3154
3155<div class="slide">
3156 <h1>Triggers</h1>
3157
3158 <ul>
3159 <li>A code reference run after an attribute is <em>set</em></li>
3160 <li>Like an <code>after</code> modifier, but makes intentions clearer</li>
3161 </ul>
3162
3163 <h2 class="wrong">Gross</h2>
3164
3165 <pre><code>after salary_level =&gt; {
3166 my $self = shift;
78c5b76a 3167 <span class="highlight">return unless @_;</span>
5d572684 3168 $self-&gt;clear_salary;
3169};</code></pre>
3170</div>
3171
3172<div class="slide">
3173 <h1>Use a Trigger Instead</h1>
3174
3175 <h2 class="right">Cleaner</h2>
3176
3177 <pre><code>has salary_level =&gt; (
3178 is =&gt; 'rw',
78c5b76a 3179 trigger =&gt;
3180 sub { $_[0]-&gt;clear_salary },
5d572684 3181);</code></pre>
3182</div>
3183
3184<div class="slide">
fc274492 3185 <h1>Trigger Arguments</h1>
3186
3187 <ul>
3188 <li><code>$self</code></li>
3189 <li><code>$new_value</code></li>
3190 <li><code>$old_value</code> - if one exists</li>
3191 </ul>
3192</div>
3193
3194<div class="slide">
5d572684 3195 <h1>Delegation</h1>
3196
3197 <ul>
3198 <li>Attributes can be objects</li>
3199 <li>Delegation transparently calls methods on those objects</li>
3200 </ul>
3201</div>
3202
3203<div class="slide">
3204 <h1>Delegation Examples</h1>
3205
3206 <pre><code>package Person;
3207
3208has lungs =&gt; (
3209 is =&gt; 'ro',
d7deb8a9 3210 isa =&gt; 'Lungs',
5d572684 3211 <span class="highlight">handles =&gt; [ 'inhale', 'exhale' ],</span>
3212);</code></pre>
3213
3214 <ul>
3215 <li>Creates <code>$person-&gt;inhale</code> and <code>-&gt;exhale</code> methods</li>
3216 <li>Internally calls <code>$person-&gt;lungs-&gt;inhale</code></li>
3217 </ul>
3218</div>
3219
3220<div class="slide">
3221 <h1>Why Delegation?</h1>
3222
3223 <ul>
3224 <li>Reduce the number of classes exposed</li>
3225 <li>Re-arrange class internals -<br />
3226 turn a method into an attribute with delegation</li>
3227 <li>Provide convenenience methods</li>
3228 </ul>
3229</div>
3230
3231<div class="slide">
3232 <h1>Moose's <code>handles</code> Parameter</h1>
3233
3234 <ul>
3235 <li>Accepts many arguments ...
3236 <ul>
3237 <li>Array reference - list of methods to delegate as-is</li>
3238 <li>Hash reference - map of method names</li>
3239 <li>Regex - delegates all matching methods</li>
3240 <li>Role name - delegates all methods in the role</li>
3241 <li>Sub reference - does something complicated ;)</li>
3242 </ul>
3243 </li>
3244 </ul>
3245</div>
3246
3247<div class="slide">
3248 <h1>Array Reference</h1>
3249
3250 <ul>
78c5b76a 3251 <li>1-to-1 mapping</li>
5d572684 3252 <li>Takes each method name and creates a simple delegation from the delegating class to the delegatee attribute</li>
3253 </ul>
3254</div>
3255
3256<div class="slide">
3257 <h1>Hash Reference</h1>
3258
3259 <ul>
3260 <li>Mapping of names in the delegating class to the delegatee class</li>
3261 </ul>
3262
3263 <pre><code>package Person;
3264use Moose;
5d572684 3265has account =&gt; (
3266 is =&gt; 'ro',
3267 isa =&gt; 'BankAccount',
3268 <span class="highlight">handles =&gt; {
3269 receive_money =&gt; 'deposit',
3270 give_money =&gt; 'withdraw',
3271 },</span>
3272);</code></pre>
3273</div>
3274
3275<div class="slide">
3276 <h1>Hash Reference Detailed</h1>
3277
3278 <pre><code> handles =&gt; {
3279 receive_money =&gt; 'deposit',
3280 give_money =&gt; 'withdraw',
3281 },</code></pre>
3282
3283 <ul>
3284 <li><code>$person-&gt;receive_money</code> = <code>$person-&gt;account-&gt;deposit</code></li>
3285 <li><code>$person-&gt;give_money</code> = <code>$person-&gt;account-&gt;withdraw</code></li>
3286 </ul>
3287</div>
3288
3289<div class="slide">
3290 <h1>Regex</h1>
3291
3292 <pre><code>package Person;
3293use Moose;
3294
3295has name =&gt; (
3296 is =&gt; 'ro',
3297 isa =&gt; 'Name',
3298 handles =&gt; qr/.*/,
3299);</code></pre>
3300
3301 <ul>
3302 <li>Creates a delegation for every method in the Name class</li>
3303 <li>Excludes <code>meta</code> and methods inherited from <code>Moose::Object</code></li>
3304 </ul>
3305</div>
3306
3307<div class="slide">
3308 <h1>Role Name</h1>
3309
3310 <pre><code>package Auditor;
3311use Moose::Role;
5d572684 3312sub record_change { ... }
3313sub change_history { ... }
3314
3315package Account;
3316use Moose;
3317
3318has history =&gt; (
3319 is =&gt; 'ro',
3320 does =&gt; 'Auditor',
3321 <span class="highlight">handles =&gt; 'Auditor',</span>
3322);</code></pre>
3323</div>
3324
3325<div class="slide">
3326 <h1>Role Name Detailed</h1>
3327
3328 <ul>
3329 <li>Account gets delegate methods for each method in the <code>Auditor</code> role
3330 <ul>
3331 <li>record_history</li>
3332 <li>change_history</li>
3333 </ul>
3334 </li>
3335 </ul>
3336</div>
3337
3338<div class="slide">
1c32806a 3339 <h1>Native Delegation</h1>
3340
3341 <ul>
3342 <li>Delegate to <em>unblessed</em> Perl types</li>
3343 <li>Scalar, array or hash ref, etc</li>
ba3e6f3b 3344 <li>Treat Perl types as objects</li>
3345 <li>Still uses <code>handles</code></li>
3346 <li>Pretend that native Perl types have methods</li>
1c32806a 3347 </ul>
3348</div>
3349
3350<div class="slide">
ba3e6f3b 3351 <h1>Native Delegation - Array(Ref)</h1>
3352
3353 <ul>
3354 <li>Methods include:
3355 <ul>
3356 <li><code>push</code></li>
3357 <li><code>shift</code></li>
3358 <li><code>elements</code> - returns all elements</li>
3359 <li><code>count</code></li>
3360 <li><code>is_empty</code></li>
3361 <li>quite a few more</li>
3362 </ul>
3363 </li>
3364 </ul>
c1d605db 3365</div>
ba3e6f3b 3366
3367<div class="slide">
3368 <h1>Native Delegation - Array(Ref)</h1>
1c32806a 3369
3370 <pre><code>package Person;
3371use Moose;
1c32806a 3372has _favorite_numbers =&gt; (
3373 traits =&gt; [ 'Array' ],
45218088 3374 is =&gt; 'bare',
1c32806a 3375 isa =&gt; 'ArrayRef[Int]',
3376 default =&gt; sub { [] },
3377 init_arg =&gt; undef,
3378 <span class="highlight">handles =&gt;
3379 { favorite_numbers =&gt; 'elements',
3380 add_favorite_number =&gt; 'push',
3381 },</span>
3382);</code></pre>
1c32806a 3383</div>
3384
3385<div class="slide">
ba3e6f3b 3386 <h1>Native Delegation - Array(Ref)</h1>
3387
3388 <pre><code>my $person = Person-&gt;new();
3389
3390$person-&gt;add_favorite_number(7);
3391$person-&gt;add_favorite_number(42);
3392
3393print "$_\n"
3394 for $person-&gt;favorite_numbers;
3395
3396# 7
3397# 42</code></pre>
3398</div>
3399
3400<div class="slide">
3401 <h1>Native Delegation</h1>
1c32806a 3402
ba3e6f3b 3403 <ul>
3404 <li>Native types are ...
3405 <ul>
3406 <li>Number - <code>add</code>, <code>mul</code>, ...</li>
3407 <li>String - <code>append</code>, <code>chop</code>, ...</li>
3408 <li>Counter - <code>inc</code>, <code>dec</code>, ...</li>
3409 <li>Bool - <code>set</code>, <code>toggle</code>, ...</li>
3410 <li>Hash - <code>get</code>, <code>set</code>, ...</li>
3411 <li>Array - already saw it</li>
78c5b76a 3412 <li>Code - <code>execute</code> and <code>execute_method</code></li>
ba3e6f3b 3413 </ul>
3414 </li>
3415 </ul>
3416</div>
3417
3418<div class="slide">
3419 <h1>Curried Delegation</h1>
3420
3421 <ul>
3422 <li>A delegation with some preset arguments</li>
3423 <li>Works with object or Native delegation</li>
3424 </ul>
3425</div>
3426
3427<div class="slide">
3428 <h1>Curried Delegation</h1>
3429
3430 <pre><code>package Person;
1c32806a 3431use Moose;
ba3e6f3b 3432has account =&gt; (
3433 is =&gt; 'ro',
3434 isa =&gt; 'BankAccount',
3435 handles =&gt; {
3436 receive_100 =&gt;
3437 <span class="highlight">[ 'deposit', 100 ]</span>
3438 give_100 =&gt;
3439 <span class="highlight">[ 'withdraw', 100 ]</span>
c1d605db 3440 },
1c32806a 3441);</code></pre>
3442</div>
3443
1c32806a 3444<div class="slide">
6f51d05c 3445 <h1>Curried Delegation</h1>
3446
3447 <pre><code>$person-&gt;receive_100;
3448# really is
3449$person-&gt;account-&gt;deposit(100);</code></pre>
3450</div>
3451
3452<div class="slide">
5d572684 3453 <h1>Traits and Metaclasses</h1>
3454
3455 <ul>
3456 <li>The ultimate in customization</li>
3457 <li>Per attribute metaclasses</li>
3458 <li>Per attribute roles applied to the attribute metaclass</li>
3459 <li>Change the meta-level behavior</li>
3460 </ul>
3461</div>
3462
3463<div class="slide">
3464 <h1>Traits and Metaclasses</h1>
3465
3466 <ul>
3467 <li>The default metaclass is <code>Moose::Meta::Attribute</code></li>
3468 <li>Controls accessor generation, defaults, delegation, etc.</li>
3469 <li>Adding a role to this metaclass (or replacing it) allows for infinite customization</li>
3470 </ul>
3471</div>
3472
3473<div class="slide">
3474 <h1>Traits and Metaclasses</h1>
3475
3476 <ul>
78c5b76a 3477 <li>Can add/alter/remove an attribute parameter (from <code>has</code>)</li>
5d572684 3478 <li>Can change behavior of created attribute</li>
3479 </ul>
3480</div>
3481
3482<div class="slide">
3483 <h1>Simple Trait Example</h1>
3484
3485 <pre><code>package Person;
3486use Moose;
3487use MooseX::LabeledAttributes;
3488
3489has ssn =&gt; (
3490 <span class="highlight">traits =&gt; [ 'Labeled' ],</span>
3491 is =&gt; 'ro',
3492 isa =&gt; 'Str',
3493 <span class="highlight">label =&gt; 'Social Security Number',</span>
3494);
5d572684 3495print <span class="highlight">Person-&gt;meta
3496 -&gt;get_attribute('ssn')-&gt;label;</span></code></pre>
3497</div>
3498
3499<div class="slide">
3500 <h1>Simple Metaclass Example</h1>
3501
3502 <pre><code>package Person;
3503use Moose;
3504use MooseX::LabeledAttributes;
3505
3506has ssn =&gt; (
3507 <span class="highlight">metaclass =&gt;
3508 'MooseX::Meta::Attribute::Labeled',</span>
3509 is =&gt; 'ro',
3510 isa =&gt; 'Str',
3511 <span class="highlight">label =&gt; 'Social Security Number',</span>
3512);
5d572684 3513print <span class="highlight">Person-&gt;meta
3514 -&gt;get_attribute('ssn')-&gt;label;</span></code></pre>
3515</div>
3516
3517<div class="slide">
3518 <h1>Traits vs Metaclass</h1>
3519
3520 <ul>
3521 <li>Can apply any mix of traits to an attribute</li>
3522 <li>But just one metaclass</li>
3523 <li>Traits (aka roles) can cooperate</li>
3524 <li>Metaclasses require you to pick just one</li>
3525 </ul>
3526</div>
3527
3528<div class="slide">
3529 <h1>Advanced Attributes Summary</h1>
3530
3531 <ul>
3532 <li>Use <code>weak_ref</code> to avoid circular references</li>
3533 <li>Use trigger to do an action post-attribute write</li>
3534 <li>Use delegations to hide "internal" objects</li>
8a912ad0 3535 <li>Use native delegations to treat Perl types as objects</li>
5d572684 3536 <li>Traits and metaclasses let you extend Moose's core attribute features</li>
3537 </ul>
3538</div>
3539
9186987b 3540<div class="slide">
9186987b 3541 <h1>Exercises</h1>
3542
3543 <pre># cd exercises
debc93f8 3544# perl bin/prove -lv \
3545 t/06-advanced-attributes.t
9186987b 3546
3547Iterate til this passes all its tests</pre>
3548</div>
3549
9d1b0590 3550<div class="slide">
0b337459 3551 <h1>CYOA</h1>
9d1b0590 3552
0b337459 3553 <p>
3554 If there is time, keep going ...
3555 </p>
9d1b0590 3556
0b337459 3557 <p>
3558 Otherwise, jump to slide 269 ...
3559 </p>
9d1b0590 3560</div>
3561
9186987b 3562<div class="slide fake-slide0">
9d1b0590 3563 <h1>Bonus: A Brief Tour of MooseX</h1>
9186987b 3564</div>
3565
c1d605db 3566<div class="slide">
6f51d05c 3567 <h1>Notable MX Modules on CPAN</h1>
0066613d 3568
3569 <ul>
3570 <li><strong>Not comprehensive</strong></li>
78c5b76a 3571 <li>152 MooseX distributions on CPAN as of 02/02/2010</li>
0066613d 3572 <li>Some of them are crap</li>
3573 </ul>
3574</div>
3575
3576<div class="slide">
3577 <h1>Already Mentioned Several</h1>
3578
3579 <ul>
255fe700 3580 <li><code>MooseX::NonMoose</code> - best solution for subclassing non-Moose parents</li>
3581 <li><code>MooseX::Declare</code> - <em>real</em> Perl 5 OO</li>
3582 <li><code>MooseX::FollowPBP</code> and <code>MooseX::SemiAffordanceAccessor</code></li>
3583 <li><code>MooseX::Params::Validate</code> and <code>MooseX::Method::Signatures</code></li>
3584 <li><code>MooseX::Types</code></li>
0066613d 3585 </ul>
3586</div>
3587
3588<div class="slide">
3589 <h1>MooseX::Declare</h1>
3590
3591<pre><code>use MooseX::Declare;
3592use 5.10.0; # for say
3593
3594class Person {
255fe700 3595 has greeting =&gt;
3596 ( is =&gt; 'ro', isa =&gt; 'Str' );
0066613d 3597
3598 method speak {
3599 say $self-&gt;greeting;
3600 }
3601}</code></pre>
3602</div>
3603
3604<div class="slide">
3605 <h1>MooseX::Declare</h1>
3606
3607 <ul>
3608 <li>Still experimental-ish, but seeing more and more use</li>
3609 <li><strong>Not</strong> a source filter!</li>
3610 <li>Hooks into the Perl parser rather than filtering all your code</li>
255fe700 3611 <li>But not supported by <code>PPI</code>, <code>perltidy</code>, etc.</li> (yet?)
0066613d 3612 </ul>
3613</div>
3614
3615<div class="slide">
3616 <h1>MooseX::StrictConstructor</h1>
3617
3618 <ul>
255fe700 3619 <li>By default, unknown constructor arguments are ignored</li>
0066613d 3620 <li>MX::StrictConstructor turns these into an error</li>
3621 </ul>
3622</div>
3623
3624<div class="slide">
3625 <h1>MooseX::StrictConstructor</h1>
3626
3627 <pre><code>package Person;
3628
3629use Moose;
3630<span class="highlight">use MooseX::StrictConstructor;</span>
3631
3632has name =&gt; ( is =&gt; 'ro' );
3633
3634Person-&gt;new
3635 ( na<span class="wrong">n</span>e =&gt; 'Ringo Shiina' ); # kaboom</code></pre>
3636</div>
3637
3638<div class="slide">
3639 <h1>MooseX::Traits</h1>
3640
3641 <ul>
3642 <li>Combines object construction and role application</li>
3643 <li>Makes it easy to create one-off customized objects</li>
3644 </ul>
3645</div>
3646
3647<div class="slide">
3648 <h1>MooseX::Traits</h1>
3649
3650 <pre><code>package MyApp::Thingy;
3651use Moose;
3652
3653<span class="highlight">with 'MooseX::Traits';</span>
3654
3655my $thing =
3656 MyApp::Thingy-&gt;<span class="highlight">new_with_traits</span>
3657 ( <span class="highlight">traits =&gt; [ 'Foo', 'Bar' ],</span>
3658 size =&gt; 42 );</code></pre>
3659</div>
3660
3661<div class="slide">
3662 <h1>MooseX::Getopt</h1>
3663
3664 <ul>
3665 <li>Makes command-line interface programs easy!</li>
3666 <li>Construct an object from CLI arguments</li>
3667 </ul>
3668</div>
3669
3670<div class="slide">
3671 <h1>MooseX::Getopt</h1>
3672
3673 <pre><code>package App::CLI;
3674use Moose;
3675
3676<span class="highlight">with 'MooseX::Getopt';</span>
3677
3678has file =&gt;
3679 ( is =&gt; 'ro', required =&gt; 1 );
3680has filters =&gt;
78c5b76a 3681 ( is =&gt; 'ro', isa =&gt; 'ArrayRef[Str]' );
0066613d 3682
3683sub run { ... }</code></pre>
3684</div>
3685
3686<div class="slide">
3687 <h1>MooseX::Getopt</h1>
3688
3689 <ul>
3690 <li>Then call it like this:</li>
3691 </ul>
3692
3693<pre><code>#!/usr/bin/perl
3694
3695use App::CLI;
3696
203ca9ec 3697<span class="highlight">App::CLI-&gt;new_with_options()</span>-&gt;run();</code></pre>
0066613d 3698
3699<pre>$ myapp-cli \
3700 --file foo \
3701 --filters compress \
3702 --filters sanitize</pre>
3703</div>
3704
3705<div class="slide">
3706 <h1>MooseX::Clone</h1>
3707
3708 <pre><code>package Person;
3709
3710use Moose;
3711<span class="highlight">with 'MooseX::Clone';</span>
3712
3713my $person = Person-&gt;new;
3714my $clone = <span class="highlight">$person-&gt;clone;</span></code></pre>
3715</div>
3716
3717<div class="slide">
3718 <h1>MooseX::NonMoose</h1>
3719
3720 <ul>
3721 <li>Highly recommended for subclassing non-Moose parents</li>
3722 <li>Gets all the little annoying details right</li>
3723 </ul>
3724</div>
3725
3726<div class="slide">
3727 <h1>MooseX::Role::Parameterized</h1>
3728
3729 <pre><code>package HasCollection;
6f51d05c 3730<span class="current incremental">use MooseX::Role::Parameterized;</span>
3731<span class="incremental">parameter type =&gt; ( isa =&gt; 'Str',
3732 default =&gt; 'Item' );</span>
3733<span class="incremental">role {
0066613d 3734 my $p = shift;
3735
6f51d05c 3736 my $type =
3737 'ArrayRef[' . $p-&gt;type() . ']';
0066613d 3738 has collection =&gt;
3739 ( is =&gt; 'ro',
3740 isa =&gt; $type );
6f51d05c 3741};</span></code></pre>
0066613d 3742</div>
3743
3744<div class="slide">
3745 <h1>MooseX::Role::Parameterized</h1>
3746
3747 <pre><code>package Person;
3748
3749use Moose;
3750with HasCollection =&gt; { type =&gt; 'Int' };</code></pre>
3751</div>
3752
0b337459 3753<div class="slide">
3754 <h1>Questions?</h1>
3755</div>
3756
3757<div class="slide">
3758 <h1>Moose-using Modules</h1>
3759
3760 <p>
3761 For further reading, a few modules which use Moose ...
3762 </p>
3763
3764 <ul>
3765 <li><a href="http://search.cpan.org/dist/Catalyst-Runtime">Catalyst</a></li>
3766 <li><a href="http://search.cpan.org/dist/CHI">CHI</a></li>
3767 <li><a href="http://search.cpan.org/dist/Devel-REPL">Devel::REPL</a></li>
3768 <li><a href="http://search.cpan.org/dist/Email-Sender">Email::Sender</a></li>
3769 <li><a href="http://search.cpan.org/dist/Fey">Fey</a></li>
3770 <li><a href="http://search.cpan.org/dist/Net-Twitter">Net::Twitter</a></li>
3771 </ul>
8a719516 3772</div>
3773
1c6a4565 3774<div class="slide">
3775 <h1>More Information</h1>
3776
3777 <ul>
3778 <li><a href="http://moose.perl.org/">http://moose.perl.org/</a></li>
3779 <li><a href="http://search.cpan.org/dist/Moose/lib/Moose/Manual.pod">Moose::Manual</a> and <a href="http://search.cpan.org/dist/Moose/lib/Moose/Cookbook.pod">Moose::Cookbook</a></li>
3780 <li><a href="irc://irc.perl.org/#moose">irc://irc.perl.org/#moose</a></li>
3781 <li>mailing list - <a href="mailto:moose@perl.org">moose@perl.org</a></li>
3782 <li>Slides and exercises are in Moose's git repo:
3783 <br />
3784 <span style="font-size:80%; white-space: nowrap">git://jules.scsys.co.uk/gitmo/moose-presentations</span></li>
3785 </ul>
3786</div>
3787
0b337459 3788<div class="slide fake-slide0">
3789 <h1>The End</h1>
3790</div>
3791
55906a14 3792</div>
b751d33f 3793</body>
3794</html>
55906a14 3795
3796<!--
3797
3798Copyright 2009 David Rolsky. All Rights Reserved.
3799
3800This work is licensed under a Creative Commons Attribution-Share Alike
38013.0 United States License See
3802http://creativecommons.org/licenses/by-sa/3.0/us/ for details.
3803
3804-->