Fix validation errors
[gitmo/moose-presentations.git] / moose-class / slides / index.html
CommitLineData
232c184d 1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
b751d33f 2
3<html xmlns="http://www.w3.org/1999/xhtml">
4
5<head>
6<title>Introduction to Moose</title>
55906a14 7<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
b751d33f 8<!-- metadata -->
9<meta name="generator" content="S5" />
10<meta name="version" content="S5 1.2a2" />
11<meta name="author" content="Eric A. Meyer" />
12<meta name="company" content="Complex Spiral Consulting" />
13<!-- configuration parameters -->
14<meta name="defaultView" content="slideshow" />
15<meta name="controlVis" content="hidden" />
16<!-- style sheet links -->
17<link rel="stylesheet" href="ui/default/slides.css" type="text/css" media="projection" id="slideProj" />
18<link rel="stylesheet" href="ui/default/outline.css" type="text/css" media="screen" id="outlineStyle" />
19<link rel="stylesheet" href="ui/default/print.css" type="text/css" media="print" id="slidePrint" />
20<link rel="stylesheet" href="ui/default/opera.css" type="text/css" media="projection" id="operaFix" />
21<!-- embedded styles -->
22<style type="text/css" media="all">
23.imgcon {width: 525px; margin: 0 auto; padding: 0; text-align: center;}
24#anim {width: 270px; height: 320px; position: relative; margin-top: 0.5em;}
25#anim img {position: absolute; top: 42px; left: 24px;}
26img#me01 {top: 0; left: 0;}
27img#me02 {left: 23px;}
28img#me04 {top: 44px;}
29img#me05 {top: 43px;left: 36px;}
30</style>
31<!-- S5 JS -->
32<script src="ui/default/slides.js" type="text/javascript"></script>
33<link rel="stylesheet" href="ui/custom.css" type="text/css" />
34</head>
35<body>
36
37<div class="layout">
38<div id="controls"><!-- DO NOT EDIT --></div>
39<div id="currentSlide"><!-- DO NOT EDIT --></div>
40<div id="header"></div>
41<div id="footer">
55906a14 42 <div id="license">
43 <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/us/88x31.png" /></a>
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">Intro to Moose Class</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>.
45 </div>
46
b751d33f 47 <h2>Introduction to Moose</h2>
48</div>
49</div>
50
51<div class="presentation">
52
53<div class="slide">
54 <h1>Introduction to Moose</h1>
55 <h2>YAPC 2009</h2>
56</div>
57
58<div class="slide">
59 <h1>Moose Summed Up</h1>
60
61 <ul>
62 <li><strong>Declarative</strong> OO sugar</li>
63 <li>Introspectable</li>
64 <li>Extensible</li>
65 </ul>
66</div>
67
68<div class="slide">
55906a14 69 <h1>Moose Background</h1>
b751d33f 70
71 <ul>
55906a14 72 <li>Created by Stevan Little, first released in 2006</li>
b751d33f 73 <li>Moose builds on Perl 5's native OO</li>
74 <li>Borrows ideas from other languages, notably Perl 6</li>
75 <li>Provides semantics for common operations</li>
76 </ul>
77</div>
78
55906a14 79<div class="slide fake-slide0">
80 <h1>Part 0: Moose Concepts</h1>
81</div>
82
b751d33f 83<div class="slide">
84 <h1>Classes</h1>
85
86 <ul>
87 <li>
88 Classes have ...
89 <ul>
90 <li>Attributes</li>
91 <li>Methods</li>
92 <li>Superclasses</li>
93 <li>Method modifiers</li>
94 <li>Constructor and destructor</li>
95 <li>One metaclass object</li>
96 </ul>
97 </li>
98 <li>Classes do roles</li>
99 </ul>
100</div>
101
102<div class="slide">
103 <h1>Class Example</h1>
104
105 <pre><code>package Person;
106<span class="highlight">use Moose;</span></code></pre>
107
108 <ul>
109 <li>Poof, a Moose-based class!</li>
110 </ul>
111</div>
112
113<div class="slide">
114 <h1>Attributes</h1>
115
116 <ul>
117 <li>Aka property, slot, field, member variable</li>
118 <li>A piece of data owned by an object</li>
119 </ul>
120</div>
121
122<div class="slide">
123 <h1>Attributes</h1>
124
125 <ul>
126 <li>
127 Attributes have ...
128 <ul>
129 <li>Access-control (read-only vs read-write)</li>
130 <li>An optional type</li>
131 <li>Accessor methods</li>
132 <li>Delegation methods</li>
133 <li>Optional default value</li>
134 <li>Many more features</li>
135 </ul>
136 </li>
137 <li>Stored in the object, but don't worry about that</li>
138 </ul>
139</div>
140
141<div class="slide">
142 <h1>Attribute Example</h1>
143
144 <pre><code>package Person;
145use Moose;
146
55906a14 147<span class="highlight">has first_name =&gt; ( is =&gt; 'rw' );</span></code></pre>
b751d33f 148
149</div>
150
151<div class="slide">
152 <h1>Methods</h1>
153
154 <ul>
155 <li>Nothing fancy here, just Perl subroutines</li>
156 </ul>
157
158 <pre><code>package Person;
159use Moose;
160
161<span class="highlight">sub greet { ... }</span></code></pre>
162</div>
163
164<div class="slide">
165 <h1>Roles</h1>
166
167 <ul>
168 <li>Classes <strong>do</strong> (or consume) roles</li>
169 <li>Similar to mixins and Java interfaces</li>
170 </ul>
171</div>
172
173<div class="slide">
174 <h1>Roles</h1>
175
176 <ul>
177 <li>Like classes, can have attributes, methods, do roles</li>
178 <li>Roles can require methods</li>
179 <li>Roles are composed (flattened) into classes</li>
180 </ul>
181</div>
182
183<div class="slide">
184 <h1>Role Example</h1>
185
186<pre><code>package HasPermissions;
187<span class="highlight">use Moose::Role;</span>
188
189has is_admin =&gt; ( is =&gt; 'rw' );</code></pre>
190</div>
191
192<div class="slide">
193 <h1>Role Example</h1>
194
195 <p>
196 And then ...
197 </p>
198
199<pre><code>package Person;
200use Moose;
201
202<span class="highlight">with 'HasPermissions';</span></code></pre>
203</div>
204
205<div class="slide">
206 <h1>Method Modifiers</h1>
207
208 <ul>
209 <li>AKA advice</li>
210 <li>&quot;<strong>Before</strong> foo(), do this first&quot;</li>
211 <li>&quot;Do this <strong>after</strong> foo()</li>
212 <li>&quot;Put this code <strong>around</strong> foo()&quot;</li>
213 </ul>
214</div>
215
216<div class="slide">
217 <h1>Before &amp; After</h1>
218
219<pre><code>before 'foo'
220 =&gt; sub { warn 'About to call foo()' };
221
222after 'foo'
223 =&gt; sub { warn 'Leaving foo()' };</code></pre>
224
225</div>
226
227<div class="slide">
228 <h1>Around</h1>
229
230<pre><code>around 'foo' =&gt; sub {
231 my $real_foo = shift;
232 my $self = shift;
233
234 warn 'Just before foo()';
235 my @return =
236 $self-&gt;$real_foo( @_, bar =&gt; 42 );
237
238 return ( @return, 'modify return values' );
239};</code></pre>
240</div>
241
242<div class="slide">
243 <h1>Type Constraints</h1>
244
245 <ul>
246 <li>NOT A FULL-BLOWN TYPE SYSTEM!</li>
247 <li>But still darn useful</li>
248 <li>Constrain attribute values</li>
249 <li>Coerce from other types</li>
250 </ul>
251</div>
252
253<div class="slide">
254 <h1>Type Constraint Example</h1>
255
256<pre><code>package Person;
257use Moose;
258
55906a14 259has weight =&gt; (
260 is =&gt; 'ro',
261 <span class="highlight">isa =&gt; 'Int'</span>,
262);
b751d33f 263
264# kaboom
265Person-&gt;new( weight =&gt; 'fat' );</code></pre>
266</div>
267
268<div class="slide">
269 <h1>Delegation</h1>
270
271 <ul>
272 <li>Attributes can define delegations</li>
273 <li>Lets you hide some implementation details</li>
274 <li>Fewer objects to chase around</li>
275 </ul>
276</div>
277
278<div class="slide">
279 <h1>Delegation</h1>
280
281<pre><code>package Person;
282use Moose;
283
55906a14 284has blog_uri =&gt; (
b751d33f 285 is =&gt; 'rw',
286 isa =&gt; 'URI',
287 <span class="highlight">handles =&gt; { 'blog_hostname' =&gt; 'host' },</span>
288);
289
290<span class="highlight">$person->blog_hostname;</span>
55906a14 291# really calls $person->blog_uri->host</code></pre>
b751d33f 292</div>
293
294<div class="slide">
295 <h1>Constructors</h1>
296
297 <ul>
298 <li>Moose creates <code>new()</code> for you</li>
299 <li>Provide an optional <code>BUILDARGS()</code> and <code>BUILD()</code></li>
300 </ul>
301</div>
302
303<div class="slide">
304 <h1>Destructors</h1>
305
306 <ul>
307 <li>Provide an optional <code>DEMOLISH()</code></li>
308 </ul>
309</div>
310
311<div class="slide">
312 <h1>Moose Meta-API</h1>
313
314 <ul>
315 <li>Answers questions like ...
316 <ul>
317 <li>What methods does this class have?</li>
318 <li>What are its parents?</li>
319 <li>What attributes does it have (including inherited attributes)?</li>
320 <li>What roles does it do?</li>
321 <li>Much, much, more</li>
322 </ul>
323 </li>
324 </ul>
325</div>
326
327<div class="slide">
328 <h1>Moose Meta-API</h1>
329
330 <ul>
331 <li>Not just for introspection ...
332 <ul>
333 <li>Add methods, attributes, roles, etc</li>
334 <li>Extend and alter core features</li>
335 </ul>
336 </li>
337 </ul>
338</div>
339
340<div class="slide">
341 <h1>Why Moose?</h1>
342
343 <ul>
344 <li>A quick bit of propoganda ...</li>
345 </ul>
346</div>
347
348<div class="slide">
349 <h1>With Moose</h1>
350
351 <pre><code>package Person;
352use Moose;
353
354has last_name =&gt; (
355 is =&gt; 'rw',
356 isa =&gt; 'Str',
357);</code></pre>
358</div>
359
360<div class="slide">
361 <h1>Without Moose</h1>
362
363 <pre class="small"><code>package Person;
364use strict;
365use warnings;
366use Carp 'confess';
367
368sub new {
369 my $class = shift;
370 my %args = @_;
371 my $self = {};
372
373 if (exists $args{last_name}) {
374 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
375 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
376 if ref($args{last_name});
377 $self-&gt;{last_nane} = $args{last_name};
378 }
379
380 return bless $self, $class;
381}
382
383sub last_name {
384 my $self = shift;
385
386 if (@_) {
387 my $value = shift;
388 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
389 . &quot;Validation failed for 'Str' with value $value&quot;
390 if ref($value);
391 $self-&gt;{last_name} = $value;
392 }
393
394 return $self-&gt;{last_name};
395}</code></pre>
396
397</div>
398
399<div class="slide">
400 <h1>Side by side</h1>
401
402 <table class="side-by-side">
403 <tr>
404 <td>
405 <pre><code>package Person;
406use Moose;
407
408has last_name =&gt; (
409 is =&gt; 'rw',
410 isa =&gt; 'Str',
411);</code></pre>
412 </td>
413 <td>
414 <pre class="small"><code>package Person;
415use strict;
416use warnings;
417use Carp 'confess';
418
419sub new {
420 my $class = shift;
421 my %args = @_;
422 my $self = {};
423
424 if (exists $args{last_name}) {
425 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
426 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
427 if ref($args{last_name});
428 $self-&gt;{last_nane} = $args{last_name};
429 }
430
431 return bless $self, $class;
432}
433
434sub last_name {
435 my $self = shift;
436
437 if (@_) {
438 my $value = shift;
439 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
440 . &quot;Validation failed for 'Str' with value $value&quot;
441 if ref($value);
442 $self-&gt;{last_name} = $value;
443 }
444
445 return $self-&gt;{last_name};
446}</code></pre>
447 </td>
448 </tr>
449 </table>
450
451</div>
452
453<div class="slide">
454 <h1>Side by side</h1>
455
456 <table class="side-by-side">
457 <tr>
458 <td>
459 <pre><code><span class="match-moose">package Person;</span>
460use Moose;
461
462has last_name =&gt; (
463 is =&gt; 'rw',
464 isa =&gt; 'Str',
465);</code></pre>
466 </td>
467 <td>
468 <pre class="small"><code><span class="match-unsweet">package Person;</span>
469use strict;
470use warnings;
471use Carp 'confess';
472
473sub new {
474 my $class = shift;
475 my %args = @_;
476 my $self = {};
477
478 if (exists $args{last_name}) {
479 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
480 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
481 if ref($args{last_name});
482 $self-&gt;{last_nane} = $args{last_name};
483 }
484
485 return bless $self, $class;
486}
487
488sub last_name {
489 my $self = shift;
490
491 if (@_) {
492 my $value = shift;
493 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
494 . &quot;Validation failed for 'Str' with value $value&quot;
495 if ref($value);
496 $self-&gt;{last_name} = $value;
497 }
498
499 return $self-&gt;{last_name};
500}</code></pre>
501 </td>
502 </tr>
503 </table>
504</div>
505
506<div class="slide">
507 <h1>Side by side</h1>
508
509 <table class="side-by-side">
510 <tr>
511 <td>
512 <pre><code>package Person;
513<span class="match-moose">use Moose;</span>
514
515has last_name =&gt; (
516 is =&gt; 'rw',
517 isa =&gt; 'Str',
518);</code></pre>
519 </td>
520 <td>
521 <pre class="small"><code>package Person;
522<span class="match-unsweet">use strict;
523use warnings;
524use Carp 'confess';
525
526sub new {
527 my $class = shift;
528 my %args = @_;
529 my $self = {};</span>
530
531 if (exists $args{last_name}) {
532 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
533 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
534 if ref($args{last_name});
535 $self-&gt;{last_nane} = $args{last_name};
536 }
537
538 <span class="match-unsweet">return bless $self, $class;
539}</span>
540
541sub last_name {
542 my $self = shift;
543
544 if (@_) {
545 my $value = shift;
546 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
547 . &quot;Validation failed for 'Str' with value $value&quot;
548 if ref($value);
549 $self-&gt;{last_name} = $value;
550 }
551
552 return $self-&gt;{last_name};
553}</code></pre>
554 </td>
555 </tr>
556 </table>
557</div>
558
559<div class="slide">
560 <h1>Side by side</h1>
561
562 <table class="side-by-side">
563 <tr>
564 <td>
565 <pre><code>package Person;
566use Moose;
567
568<span class="match-moose">has last_name =&gt; (</span>
569 is =&gt; 'rw',
570 isa =&gt; 'Str',
571<span class="match-moose">);</span></code></pre>
572 </td>
573 <td>
574 <pre class="small"><code>package Person;
575use strict;
576use warnings;
577use Carp 'confess';
578
579sub new {
580 my $class = shift;
581 my %args = @_;
582 my $self = {};
583
584 <span class="match-unsweet">if (exists $args{last_name}) {</span>
585 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
586 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
587 if ref($args{last_name});
588 <span class="match-unsweet">$self-&gt;{last_nane} = $args{last_name};
589 }</span>
590
591 return bless $self, $class;
592}
593
594sub last_name {
595 my $self = shift;
596
597 if (@_) {
598 my $value = shift;
599 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
600 . &quot;Validation failed for 'Str' with value $value&quot;
601 if ref($value);
602 $self-&gt;{last_name} = $value;
603 }
604
605 return $self-&gt;{last_name};
606}</code></pre>
607 </td>
608 </tr>
609 </table>
610</div>
611
612<div class="slide">
613 <h1>Side by side</h1>
614
615 <table class="side-by-side">
616 <tr>
617 <td>
618 <pre><code>package Person;
619use Moose;
620
621has last_name =&gt; (
622 <span class="match-moose">is =&gt; 'rw',</span>
623 isa =&gt; 'Str',
624);</code></pre>
625 </td>
626 <td>
627 <pre class="small"><code>package Person;
628use strict;
629use warnings;
630use Carp 'confess';
631
632sub new {
633 my $class = shift;
634 my %args = @_;
635 my $self = {};
636
637 if (exists $args{last_name}) {
638 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
639 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
640 if ref($args{last_name});
641 $self-&gt;{last_nane} = $args{last_name};
642 }
643
644 return bless $self, $class;
645}
646
647<span class="match-unsweet">sub last_name {
648 my $self = shift;
649
650 if (@_) {
651 my $value = shift;</span>
652 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
653 . &quot;Validation failed for 'Str' with value $value&quot;
654 if ref($value);
655 <span class="match-unsweet">$self-&gt;{last_name} = $value;
656 }
657
658 return $self-&gt;{last_name};
659}</span></code></pre>
660 </td>
661 </tr>
662 </table>
663</div>
664
665<div class="slide">
666 <h1>Side by side</h1>
667
668 <table class="side-by-side">
669 <tr>
670 <td>
671 <pre><code>package Person;
672use Moose;
673
674has last_name =&gt; (
675 is =&gt; 'rw',
676 <span class="match-moose">isa =&gt; 'Str',</span>
677);</code></pre>
678 </td>
679 <td>
680 <pre class="small"><code>package Person;
681use strict;
682use warnings;
683use Carp 'confess';
684
685sub new {
686 my $class = shift;
687 my %args = @_;
688 my $self = {};
689
690 if (exists $args{last_name}) {
691 <span class="match-unsweet">confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
692 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
693 if ref($args{last_name});</span>
694 $self-&gt;{last_nane} = $args{last_name};
695 }
696
697 return bless $self, $class;
698}
699
700sub last_name {
701 my $self = shift;
702
703 if (@_) {
704 my $value = shift;
705 <span class="match-unsweet">confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
706 . &quot;Validation failed for 'Str' with value $value&quot;
707 if ref($value);</span>
708 $self-&gt;{last_name} = $value;
709 }
710
711 return $self-&gt;{last_name};
712}</code></pre>
713 </td>
714 </tr>
715 </table>
716</div>
717
718<div class="slide">
719 <h1>Side by side</h1>
720
721 <table class="side-by-side">
722 <tr class="incremental">
723 <td>5 lines</td>
724 <td>21 lines</td>
725 </tr>
726 <tr class="incremental">
727 <td>92 characters</td>
728 <td>741 characters</td>
729 </tr>
730 <tr>
731 <td>
732 <pre><code>package Person;
733use Moose;
734
735has last_name =&gt; (
736 is =&gt; 'rw',
737 isa =&gt; 'Str',
738);</code></pre>
739 </td>
740 <td>
741 <pre class="small"><code>package Person;
742use strict;
743use warnings;
744use Carp 'confess';
745
746sub new {
747 my $class = shift;
748 my %args = @_;
749 my $self = {};
750
751 if (exists $args{last_name}) {
752 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
753 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
754 if ref($args{last_name});
755 $self-&gt;{last_nane} = $args{last_name};
756 }
757
758 return bless $self, $class;
759}
760
761sub last_name {
762 my $self = shift;
763
764 if (@_) {
765 my $value = shift;
766 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
767 . &quot;Validation failed for 'Str' with value $value&quot;
768 if ref($value);
769 $self-&gt;{last_name} = $value;
770 }
771
772 return $self-&gt;{last_name};
773}</code></pre>
774 </td>
775 </tr>
776 </table>
777</div>
778
779<div class="slide">
780 <h1>Typo?</h1>
781
782 <pre class="small"><code>sub new {
783 my $class = shift;
784 my %args = @_;
785 my $self = {};
786
787 if (exists $args{last_name}) {
788 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
789 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
790 if ref($args{last_name});
791 $self-&gt;{last_nane} = $args{last_name};
792 }
793
794 return bless $self, $class;
795}</code></pre>
796</div>
797
798<div class="slide">
799 <h1>Typo?</h1>
800
801 <pre class="small"><code>if (exists $args{last_name}) {
802 confess &quot;Attribute (last_name) does not pass the type constraint because: &quot;
803 . &quot;Validation failed for 'Str' with value $args{last_name}&quot;
804 if ref($args{last_name});
805 $self-&gt;{last_nane} = $args{last_name};
806}</code></pre>
807</div>
808
809<div class="slide">
810 <h1>Typo?</h1>
811
812 <code>$self-&gt;{last_nane} = $args{last_name};</code>
813</div>
814
815<div class="slide">
816 <h1>Typo?</h1>
817 <code>$self-&gt;{last_na<span class="highlight">n</span>e}</code>
818</div>
819
820<div class="slide">
821 <h1>Why Moose?</h1>
822
823 <pre><code>package Person;
824use Moose;
825
826has last_name =&gt; (
827 is =&gt; 'rw',
828 isa =&gt; 'Str',
829);</code></pre>
830</div>
831
832<div class="slide fake-slide0">
ba1c9923 833 <h1>Part 1: Moose Classes</h1>
b751d33f 834</div>
835
836<div class="slide">
837 <h1>Moose Classes</h1>
838
839 <ul>
840 <li>Moose classes are Perl packages which <code>use Moose</code></li>
841 </ul>
842</div>
843
844<div class="slide">
845 <h1>Moose.pm and Your Class</h1>
846
847 <pre><code>package Person;
848use Moose;</code></pre>
849
850 <ul>
851 <li><code>Moose.pm</code> provides declarative sugar</li>
9b195048 852 <li>Turns on <code>strict</code> and <code>warnings</code></li>
b751d33f 853 <li>Creates metaclasses for your class: <code>Person-&gt;meta</code></li>
854 <li>Moose classes automatically inherit from <code>Moose::Object</code></li>
855 </ul>
856</div>
857
858<div class="slide">
859 <h1>What <code>Moose::Object</code> Provides</h1>
860
861 <ul>
862 <li>Constructor - <code>new()</code></li>
863 <li>Calls your <code>BUILDARGS()</code> and/or <code>BUILD()</code></li>
864 <li>Calls your <code>DEMOLISH</code> during object destruction</li>
865 </ul>
866</div>
867
868<div class="slide">
869 <h1>extends</h1>
870
871 <ul>
872 <li><code>extends</code> is sugar for declaring parent classes</li>
873 </ul>
874
875 <pre><code>package Employee;
876use Moose;
877<span class="highlight">extends 'Person';</span></code></pre>
878</div>
879
880<div class="slide">
881 <h1>extends</h1>
882
883 <ul>
884 <li>Each call to <code>extends</code> <strong>resets</strong> your parents</li>
885 </ul>
886
887 <h2 class="wrong">WRONG</h2>
888
9b195048 889 <pre><code>package EvilEmployee;
b751d33f 890use Moose;
891extends 'Person';
55906a14 892extends 'Thief';</code></pre>
b751d33f 893
894 <h2 class="right">RIGHT</h2>
895
9b195048 896 <pre><code>package EvilEmployee;
b751d33f 897use Moose;
55906a14 898extends 'Person', 'Thief';</code></pre>
b751d33f 899</div>
900
901<div class="slide">
902 <h1>Extending un-Moose-y Parents</h1>
903
904 <pre><code>package My::LWP;
905use Moose;
55906a14 906extends 'LWP';</code></pre>
b751d33f 907
908 <ul>
909 <li>No <code>Moose::Object</code>, so ...
910 <ul>
911 <li>No attribute-handling <code>new()</code></li>
912 <li>No <code>BUILDARGS()</code> or <code>BUILD()</code></li>
913 <li>No <code>DEMOLISH()</code></li>
914 </ul>
915 </li>
916 <li>But see <code>MooseX::NonMoose</code> for a workaround</li>
917 </ul>
918</div>
919
920<div class="slide">
9b195048 921 <h1><code>overrides</code> and <code>super</code></h1>
922
923 <ul>
924 <li><code>overrides</code> is another method modifier</li>
925 <li>An alternative to Perl's <code>SUPER::</code></li>
926 </ul>
927</div>
928
929<div class="slide">
930 <h1><code>overrides</code> and <code>super</code></h1>
931
932 <pre><code>package Employee;
933use Moose;
934
55906a14 935<span class="current">extends 'Person';</span>
9b195048 936
937<span class="incremental">overrides</span> work =&gt; sub {
938 my $self = shift;
939
940 die "Pay me first" unless $self-&gt;got_paid;
941 <span class="incremental">super();</span>
942}<span class="incremental">;</span></code></pre>
55906a14 943</div>
9b195048 944
945<div class="slide">
946 <h1>Caveat <code>super</code></h1>
947
948 <ul>
949 <li>Mostly like <code>$self-&gt;SUPER::work(@_)</code></li>
950 <li><strong>But</strong> cannot change <code>@_</code>!</li>
951 <li>Binds the parent's method at compile time</li>
952 </ul>
953</div>
954
955<div class="slide">
956 <h1>Attributes (Part 1)</h1>
957
958 <ul>
959 <li><code>has 'foo'</code></li>
960 <li>Use <code>is =&gt; 'ro'</code> or <code>is =&gt; 'rw'</code></li>
961 <li>Attributes without "is" have no accessors</li>
962 </ul>
963</div>
964
965<div class="slide">
966 <h1>Read-write attributes</h1>
967
968 <pre><code>package Person;
969use Moose;
970
55906a14 971has first_name =&gt; ( <span class="highlight">is =&gt; 'rw'</span> );
9b195048 972
973my $person =
974 Person-&gt;new( first_name =&gt; 'Dave' );
975
976$person-&gt;first_name('Stevan');
977print $person-&gt;first_name; # Stevan</code></pre>
978
979</div>
980
981<div class="slide">
982 <h1>Read-only attributes</h1>
983
984 <pre><code>package Person;
985use Moose;
986
55906a14 987has first_name =&gt; ( <span class="highlight">is =&gt; 'ro'</span> );
9b195048 988
989my $person =
990 Person-&gt;new( first_name =&gt; 'Dave' );
991
992$person-&gt;first_name('Stevan');
993print $person-&gt;first_name; # Dave</code></pre>
994
995</div>
996
997<div class="slide">
998 <h1>There is More to Come</h1>
999
1000 <ul>
1001 <li>Attributes have a <em>lot</em> of features</li>
1002 </ul>
1003</div>
1004
1005<div class="slide">
b751d33f 1006 <h1>Cleaning Up Moose Droppings</h1>
1007
1008 <pre><code>package Person;
1009use Moose;
1010
1011# true
1012Person->can('extends');</code></pre>
1013
1014 <ul>
1015 <li>Not very hygienic</li>
1016 </ul>
1017</div>
1018
1019<div class="slide">
1020 <h1>Cleaning Up Moose Droppings</h1>
1021
1022 <pre><code>package Person;
1023use Moose;
1024
1025...
1026
1027no Moose;
1028
1029# false
1030Person->can('extends');</code></pre>
1031</div>
1032
1033<div class="slide">
1034 <h1>No Moose</h1>
1035
1036 <ul>
1037 <li><code>no Moose</code> at the end of a package is a best practice</li>
1038 <li>Just do it</li>
1039 </ul>
1040</div>
1041
1042<div class="slide">
1043 <h1>Immutability</h1>
1044
1045 <ul>
1046 <li><span style="font-family: URW Chancery L; font-size: 140%">Stevan's Incantation of Fleet-Footedness</span></li>
1047 </ul>
1048
1049 <pre><code>package Person;
1050use Moose;
1051
1052<span class="highlight">__PACKAGE__->meta->make_immutable;</span></code></pre>
1053</div>
1054
9b195048 1055<div class="slide">
1056 <h1>What <code>make_immutable</code> does</h1>
1057
1058 <ul>
1059 <li>Magic</li>
1060 <li>Uses <code>eval</code> to "inline" a constructor</li>
1061 <li>Memoizes a lot of meta-information</li>
1062 <li>Makes loading your class slower</li>
1063 <li>Makes object creation <em>much</em> faster</li>
1064 </ul>
1065</div>
1066
1067<div class="slide">
1068 <h1>When to Immutabilize?</h1>
1069
1070 <ul>
1071 <li><em>Almost</em> always</li>
1072 <li>Startup time vs execution time</li>
1073 </ul>
1074</div>
1075
ddd87d75 1076<div class="slide">
55906a14 1077 <h1>Classes Summary</h1>
1078
1079 <ul>
1080 <li><code>use Moose</code></li>
1081 <li><code>Class-&gt;meta</code></li>
1082 <li><code>Moose::Object</code> base class</li>
1083 <li><code>extends</code>, <code>overrides</code>, and <code>super</code></li>
1084 <li>Simple attributes: <code>has</code>, <code>is&nbsp;=&gt;&nbsp;'ro'</code>, &amp; <code>is&nbsp;=&gt;&nbsp;'rw'</code></li>
1085 <li><code>no Moose</code></li>
1086 <li><code>__PACKAGE__-&gt;meta-&gt;make_immutable</code></li>
1087 </ul>
1088</div>
1089
1090<div class="slide">
ba1c9923 1091 <h1>Exercises</h1>
ddd87d75 1092
1093 <pre>$ cd exercises
ba1c9923 1094$ perl bin/prove -lv t/00-prereq.t
ddd87d75 1095
1096Missing anything? Install it. (see tarballs/)
1097
ba1c9923 1098# perl bin/prove -lv t/01-classes.t
1099
55906a14 1100Iterate til this passes all its tests</pre>
1101</div>
1102
1103<div class="slide fake-slide0">
1104 <h1>Part 2: Roles</h1>
1105</div>
1106
1107<div class="slide">
1108 <h1>Just What Is a Role?</h1>
1109
1110 <ul>
1111 <li>Mixin? Interface? Trait?</li>
1112 <li>Yes ... and more!</li>
1113 </ul>
1114</div>
1115
1116<div class="slide">
1117 <h1>Roles Can Have State <strong>and</strong> Behavior</h1>
1118
1119 <pre><code>package HasPermissions;
1120use Moose::Role;
1121
1122<span class="current"># state
1123has access_level =&gt; ( is =&gt; 'rw' );</span>
1124
1125<span class="incremental"># behavior
1126sub can_access {
1127 my $self = shift;
1128 my $required = shift;
1129
1130 return $self-&gt;access_level &gt;= $required;
1131}</span></code></pre>
1132
1133</div>
1134
1135<div class="slide">
1136 <h1>Roles Can Define Interfaces</h1>
1137
1138 <pre><code>package Printable;
1139use Moose::Role;
1140
1141requires 'as_string';</code></pre>
1142</div>
1143
1144<div class="slide">
1145 <h1>Roles Can Do All Three</h1>
1146
1147 <pre><code>package Printable;
1148use Moose::Role;
1149
1150requires 'as_string';
1151
1152has has_been_printed =&gt; ( is =&gt; 'rw' );
1153
1154sub print {
1155 my $self = shift;
1156 print $self-&gt;as_string;
1157 $self-&gt;has_been_printed(1);
1158}</code></pre>
1159</div>
1160
1161<div class="slide">
1162 <h1>Classes Consume Roles</h1>
1163
1164 <pre><code>package Person;
1165use Moose;
1166
1167with 'HasPermissions';</code></pre>
1168</div>
1169
1170<div class="slide">
1171 <h1>Classes Consume Roles</h1>
1172
1173<pre><code>my $person = Person-&gt;new(
1174 first_name => 'Kenichi',
1175 last_name => 'Asai',
1176 access_level =&gt; 42,
1177);
1178
1179print $person-&gt;full_name
1180 . ' has '
1181 . $person-&gt;can_access(42)
1182 ? 'great power'
1183 : 'little power';</code></pre>
1184</div>
1185
1186<div class="slide">
1187 <h1>Roles in Practice</h1>
1188
1189 <ul>
1190 <li>Consuming a role =~ inlining the role</li>
1191 </ul>
1192</div>
1193
1194<div class="slide">
1195 <h1>In Other Words ...</h1>
1196
1197<pre><code>package Person;
1198use Moose;
1199
1200<span class="highlight">with 'Printable';</span></code></pre>
1201</div>
1202
1203<div class="slide">
1204 <h1>In Other Words ...</h1>
1205
1206<pre><code>package Person;
1207use Moose;
1208
1209<span class="delete">with 'Printable';</span>
1210
1211<span class="highlight">has has_been_printed =&gt; ( is =&gt; 'rw' );
1212
1213sub print {
1214 my $self = shift;
1215 print $self-&gt;as_string;
1216 $self-&gt;has_been_printed(1);
1217}</span></code></pre>
1218</div>
1219
1220<div class="slide">
1221 <h1>Except</h1>
1222
1223 <ul>
1224 <li>Role consumption is introspectable</li>
1225 </ul>
1226
1227 <pre><code>if ( Person-&gt;does('Printable') ) { ... }
1228
1229# or ...
1230
1231if ( Person-&gt;meta-&gt;does('Printable') ) { ... }</code></pre>
1232
1233</div>
1234
1235<div class="slide">
1236 <h1>These Names Are the Same</h1>
1237
1238 <ul>
1239 <li>What if a role and class define the same method?</li>
1240 <li>A class's <em>local</em> methods win over the role's</li>
1241 <li>The role's methods win over the class's <em>inherited</em> methods</li>
1242 </ul>
1243</div>
1244
1245<div class="slide">
1246 <h1>Conflicts Between Roles</h1>
1247
1248 <ul>
1249 <li>Two roles with a method of the same name</li>
1250 <li>Generates a compile-time error when consumed by a class</li>
1251 </ul>
1252</div>
1253
1254<div class="slide">
1255 <h1>Conflict Example</h1>
1256
1257 <pre><code>package IsFragile;
1258use Moose::Role;
1259
1260sub break { ... }
1261
1262package CanBreakdance;
1263use Moose::Role;
1264
1265sub break { ... }</code></pre>
1266</div>
1267
1268<div class="slide">
1269 <h1>Conflict Example</h1>
1270
1271 <pre><code>package FragileDancer;
1272use Moose;
1273
1274<span class="highlight">with 'IsFragile', 'CanBreakdance';</span></code></pre>
1275
1276 <ul>
1277 <li>Only one <code>with</code>!</li>
1278 </ul>
1279</div>
1280
1281<div class="slide">
1282 <h1>Conflict Resolution</h1>
1283
1284 <ul>
1285 <li>The consuming class must resolve the conflict by implementing th emethod</li>
1286 <li>Can use some combination of method exclusion and aliasing</li>
1287 </ul>
1288</div>
1289
1290<div class="slide">
1291 <h1>Method Aliasing</h1>
1292
1293 <pre><code>package FragileDancer;
1294use Moose;
1295
1296<span class="highlight">with 'IsFragile' =>
1297 { alias =>
1298 { break => 'break_bone' } },
1299 'CanBreakdance' =>
1300 { alias =>
1301 { break => 'break_it_down' } };</span></code></pre>
1302
1303 <ul>
1304 <li>Renames the roles' methods</li>
1305 <li>Still conflicts, need to <code>exclude</code> as well</li>
1306 </ul>
1307</div>
1308
1309<div class="slide">
1310 <h1>Method Exclusion</h1>
1311
1312 <pre><code>package FragileDancer;
1313use Moose;
1314
1315<span class="highlight">with 'IsFragile' =>
1316 { alias =>
1317 { break => 'break_bone' },
1318 exclude => 'break' },
1319 'CanBreakdance' =>
1320 { alias =>
1321 { break => 'break_dance' },
1322 exclude => 'break' };</span></code></pre>
1323</div>
1324
1325<div class="slide">
1326 <h1>And then ...</h1>
1327
1328 <pre><code>package FragileDancer;
1329use Moose;
ddd87d75 1330
55906a14 1331sub break {
1332 my $self = shift;
1333
1334 $self->break_dance;
232c184d 1335 if ( rand(1) &lt; 0.5 ) {
55906a14 1336 $self->break_bone;
1337 }
1338}</code></pre>
1339</div>
1340
1341<div class="slide">
1342 <h1>Still Full of Fail</h1>
1343
1344 <ul>
1345 <li>Roles are also about semantics!</li>
1346 <li>We've fulfilled the letter and lost the spirit</li>
1347 <li>Roles have a <em>meaning</em></li>
1348 <li>Think twice before blindly aliasing and excluding methods!</li>
1349 </ul>
1350</div>
1351
1352<div class="slide">
1353 <h1>Hot Role-on-Role Action</h1>
1354
1355 <pre><code>package Comparable;
1356use Moose::Role;
1357
1358requires 'compare';</code></pre>
1359</div>
1360
1361<div class="slide">
1362 <h1>Hot Role-on-Role Action</h1>
1363
1364 <pre><code>package TestsEquality;
1365use Moose::Role;
1366
1367with 'Comparable';
1368
1369sub is_equal {
1370 my $self = shift;
1371 return $self->compare(@_) == 0;
1372}</code></pre>
1373</div>
1374
1375<div class="slide">
1376 <h1>And then ...</h1>
1377
1378 <pre><code>package Integer;
1379use Moose;
1380
1381with 'TestsEquality';
1382
1383# Satisfies the Comparable role
1384sub compare { ... }
1385
1386Integer->does('TestsEquality'); # true
1387Integer->does('Comparable'); # also true!</code></pre>
1388</div>
1389
1390<div class="slide">
1391 <h1>Name Conflicts Between Roles</h1>
1392
1393 <pre><code>package HasSubProcess;
1394use Moose::Role;
1395
1396<span class="highlight">sub execute { ... }</span>
1397
1398package Killer;
1399use Moose::Role;
1400
1401with 'HasSubProcess';
1402
1403<span class="highlight">sub execute { ... }</span></code></pre>
1404</div>
1405
1406<div class="slide">
1407 <h1>Delayed Conflict</h1>
1408
1409 <pre><code>package StateOfTexas;
1410with 'Killer';</code></pre>
1411
1412 <ul>
1413 <li><code>StateOfTexas</code> must implement its own <code>execute</code></li>
1414 <li>But loading the <code>Killer</code> role by itself does not cause an error</li>
1415 </ul>
1416</div>
1417
1418<div class="slide">
1419 <h1>Roles as Interfaces</h1>
1420
1421 <ul>
1422 <li>Roles can <code>require</code> methods of their consumers</li>
1423 <li>Compile-time checks</li>
1424 <li>Method must exist when the role is consumed</li>
1425 </ul>
1426</div>
1427
1428<div class="slide">
1429 <h1>The Attribute Gotcha</h1>
1430
1431<pre><code>package HasSize;
1432use Moose::Role;
1433
1434<span class="current">requires 'size';</span>
1435
1436package Shirt;
1437use Moose;
1438
1439<span class="incremental">with 'HasSize';
1440
1441has size => ( is => 'ro' );</span></code></pre>
1442</div>
1443
1444<div class="slide">
1445 <h1>The Attribute Gotcha Workaround</h1>
1446
1447 <pre><code>package HasSize;
1448use Moose::Role;
1449
1450requires 'size';
1451
1452package Shirt;
1453use Moose;
1454
1455has size => ( is => 'ro' );
1456
1457with 'HasSize';</code></pre>
1458</div>
1459
1460<div class="slide">
1461 <h1>Compile-time Is a Lie</h1>
1462
1463 <ul>
1464 <li>Really, it's <em>package load</em> time</li>
1465 <li>That's run-time, but before the "real" run-time</li>
1466 <li>Moose does not rewire Perl, it's just sugar!</li>
1467 <li>(but <code>MooseX::Declare</code> <em>does</em> rewire Perl)</li>
1468 </ul>
1469</div>
1470
1471<div class="slide">
1472 <h1>Enforcing Roles</h1>
1473
1474 <pre><code>package Comparison;
1475use Moose;
1476
1477has [ 'left', 'right' ] => (
1478 is => 'ro',
1479 <span class="highlight">does => 'Comparable',</span>
1480);
1481</code></pre>
1482
1483 <ul>
1484 <li>A sneak peek at type constraints</li>
1485 </ul>
1486</div>
1487
1488
1489<div class="slide">
1490 <h1>Roles Can Be Applied to Objects</h1>
1491
1492 <pre><code>use Moose::Util qw( apply_all_roles );
1493
1494my $fragile_person = Person->new( ... );
1495apply_all_roles( $fragile_person, 'IsFragile' );</code></pre>
1496
1497 <ul>
1498 <li>Does not change the <code>Person</code> class</li>
1499 <li>Works with non-Moose classes, great for monkey-patching!</li>
1500 </ul>
1501</div>
1502
1503<div class="slide">
1504 <h1>Roles Are Dirty Too</h1>
1505
1506 <ul>
1507 <li>Once again, clean up those Moose droppings</li>
1508 </ul>
1509
1510 <pre><code>package Comparable;
1511use Moose::Role;
1512
1513requires 'compare';
1514
1515<span class="highlight">no Moose::Role;</span></code></pre>
1516
1517 <ul>
1518 <li>But roles cannot be made immutable</li>
1519 </ul>
1520</div>
1521
1522<div class="slide">
1523 <h1>The Zen of Roles</h1>
1524
1525 <ul>
1526 <li>Roles represent discrete units of ...
1527 <ul>
1528 <li>state</li>
1529 <li>behavior</li>
1530 <li>interface</li>
1531 </ul>
1532 </li>
1533 <li>Roles are shareable between unrelated classes</li>
1534 <li>Roles are what a class <em>does</em>, not what it <em>is</em></li>
1535 <li>Roles <em>add</em> functionality, inheritance <em>specializes</em></li>
1536 </ul>
1537</div>
1538
1539<div class="slide">
1540 <h1>Abstract Examples</h1>
1541
1542 <ul>
1543 <li>Human <em>@ISA</em> Animal</li>
1544 <li>Human <em>does</em> Toolmaker (as <em>does</em> Chimpanzee)</li>
1545 <li>Car <em>@ISA</em> Vehicle</li>
1546 <li>Car <em>does</em> HasEngine</li>
1547 </ul>
1548</div>
1549
1550<div class="slide">
1551 <h1>Real Examples</h1>
1552
1553 <ul>
1554 <li>Objects representing SQL database components and queries
1555 <ul>
1556 <li>Schema, Table, Column, ColumnAlias</li>
1557 <li>Select, Insert, Update, Delete</li>
1558 </ul>
1559 </li>
1560 </ul>
1561</div>
1562
1563<div class="slide">
1564 <h1>Real Examples</h1>
1565
1566 <ul>
1567 <li>Column and ColumnAlias both <em>do</em> ColumnLike</li>
1568 <li>ColumnLike things can be used in certain parts of queries</li>
1569 <li>All queries <em>do</em> HasWhereClause</li>
1570 <li>Select <em>does</em> Comparable and Selectable (for subselects)</li>
1571 <li>A where clause requires its components to <em>do</em> Comparable</li>
1572 </ul>
1573</div>
1574
1575<div class="slide">
1576 <h1>Exercises</h1>
1577
1578 <pre>$ cd exercises
1579# perl bin/prove -lv t/02-roles.t
1580
1581Iterate til this passes all its tests</pre>
1582</div>
1583
1584</div>
b751d33f 1585</body>
1586</html>
55906a14 1587
1588<!--
1589
1590Copyright 2009 David Rolsky. All Rights Reserved.
1591
1592This work is licensed under a Creative Commons Attribution-Share Alike
15933.0 United States License See
1594http://creativecommons.org/licenses/by-sa/3.0/us/ for details.
1595
1596-->