1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4 <html xmlns="http://www.w3.org/1999/xhtml">
7 <title>Introduction to Moose</title>
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;}
26 img#me01 {top: 0; left: 0;}
27 img#me02 {left: 23px;}
29 img#me05 {top: 43px;left: 36px;}
32 <script src="ui/default/slides.js" type="text/javascript"></script>
33 <link rel="stylesheet" href="ui/custom.css" type="text/css" />
38 <div id="controls"><!-- DO NOT EDIT --></div>
39 <div id="currentSlide"><!-- DO NOT EDIT --></div>
40 <div id="header"></div>
42 <h2>Introduction to Moose</h2>
46 <div class="presentation">
49 <h1>Introduction to Moose</h1>
54 <h1>Moose Summed Up</h1>
57 <li><strong>Declarative</strong> OO sugar</li>
58 <li>Introspectable</li>
63 <div class="slide fake-slide0">
64 <h1>Part 0: Moose Concepts</h1>
68 <h1>Moose background</h1>
71 <li>Moose builds on Perl 5's native OO</li>
72 <li>Borrows ideas from other languages, notably Perl 6</li>
73 <li>Provides semantics for common operations</li>
87 <li>Method modifiers</li>
88 <li>Constructor and destructor</li>
89 <li>One metaclass object</li>
92 <li>Classes do roles</li>
97 <h1>Class Example</h1>
99 <pre><code>package Person;
100 <span class="highlight">use Moose;</span></code></pre>
103 <li>Poof, a Moose-based class!</li>
111 <li>Aka property, slot, field, member variable</li>
112 <li>A piece of data owned by an object</li>
123 <li>Access-control (read-only vs read-write)</li>
124 <li>An optional type</li>
125 <li>Accessor methods</li>
126 <li>Delegation methods</li>
127 <li>Optional default value</li>
128 <li>Many more features</li>
131 <li>Stored in the object, but don't worry about that</li>
136 <h1>Attribute Example</h1>
138 <pre><code>package Person;
141 <span class="highlight">has 'first_name' => ( is => 'rw' );</span></code></pre>
149 <li>Nothing fancy here, just Perl subroutines</li>
152 <pre><code>package Person;
155 <span class="highlight">sub greet { ... }</span></code></pre>
162 <li>Classes <strong>do</strong> (or consume) roles</li>
163 <li>Similar to mixins and Java interfaces</li>
171 <li>Like classes, can have attributes, methods, do roles</li>
172 <li>Roles can require methods</li>
173 <li>Roles are composed (flattened) into classes</li>
178 <h1>Role Example</h1>
180 <pre><code>package HasPermissions;
181 <span class="highlight">use Moose::Role;</span>
183 has is_admin => ( is => 'rw' );</code></pre>
187 <h1>Role Example</h1>
193 <pre><code>package Person;
196 <span class="highlight">with 'HasPermissions';</span></code></pre>
200 <h1>Method Modifiers</h1>
204 <li>"<strong>Before</strong> foo(), do this first"</li>
205 <li>"Do this <strong>after</strong> foo()</li>
206 <li>"Put this code <strong>around</strong> foo()"</li>
211 <h1>Before & After</h1>
213 <pre><code>before 'foo'
214 => sub { warn 'About to call foo()' };
217 => sub { warn 'Leaving foo()' };</code></pre>
224 <pre><code>around 'foo' => sub {
225 my $real_foo = shift;
228 warn 'Just before foo()';
230 $self->$real_foo( @_, bar => 42 );
232 return ( @return, 'modify return values' );
237 <h1>Type Constraints</h1>
240 <li>NOT A FULL-BLOWN TYPE SYSTEM!</li>
241 <li>But still darn useful</li>
242 <li>Constrain attribute values</li>
243 <li>Coerce from other types</li>
248 <h1>Type Constraint Example</h1>
250 <pre><code>package Person;
253 has 'weight' => ( is => 'ro', <span class="highlight">isa => 'Int'</span> );
256 Person->new( weight => 'fat' );</code></pre>
263 <li>Attributes can define delegations</li>
264 <li>Lets you hide some implementation details</li>
265 <li>Fewer objects to chase around</li>
272 <pre><code>package Person;
275 has 'blog_uri' => (
278 <span class="highlight">handles => { 'blog_hostname' => 'host' },</span>
281 <span class="highlight">$person->blog_hostname;</span>
282 # really calls $person->blog_uri->host
286 <h1>Constructors</h1>
289 <li>Moose creates <code>new()</code> for you</li>
290 <li>Provide an optional <code>BUILDARGS()</code> and <code>BUILD()</code></li>
298 <li>Provide an optional <code>DEMOLISH()</code></li>
303 <h1>Moose Meta-API</h1>
306 <li>Answers questions like ...
308 <li>What methods does this class have?</li>
309 <li>What are its parents?</li>
310 <li>What attributes does it have (including inherited attributes)?</li>
311 <li>What roles does it do?</li>
312 <li>Much, much, more</li>
319 <h1>Moose Meta-API</h1>
322 <li>Not just for introspection ...
324 <li>Add methods, attributes, roles, etc</li>
325 <li>Extend and alter core features</li>
335 <li>A quick bit of propoganda ...</li>
342 <pre><code>package Person;
345 has last_name => (
352 <h1>Without Moose</h1>
354 <pre class="small"><code>package Person;
364 if (exists $args{last_name}) {
365 confess "Attribute (last_name) does not pass the type constraint because: "
366 . "Validation failed for 'Str' with value $args{last_name}"
367 if ref($args{last_name});
368 $self->{last_nane} = $args{last_name};
371 return bless $self, $class;
379 confess "Attribute (last_name) does not pass the type constraint because: "
380 . "Validation failed for 'Str' with value $value"
382 $self->{last_name} = $value;
385 return $self->{last_name};
391 <h1>Side by side</h1>
393 <table class="side-by-side">
396 <pre><code>package Person;
399 has last_name => (
405 <pre class="small"><code>package Person;
415 if (exists $args{last_name}) {
416 confess "Attribute (last_name) does not pass the type constraint because: "
417 . "Validation failed for 'Str' with value $args{last_name}"
418 if ref($args{last_name});
419 $self->{last_nane} = $args{last_name};
422 return bless $self, $class;
430 confess "Attribute (last_name) does not pass the type constraint because: "
431 . "Validation failed for 'Str' with value $value"
433 $self->{last_name} = $value;
436 return $self->{last_name};
445 <h1>Side by side</h1>
447 <table class="side-by-side">
450 <pre><code><span class="match-moose">package Person;</span>
453 has last_name => (
459 <pre class="small"><code><span class="match-unsweet">package Person;</span>
469 if (exists $args{last_name}) {
470 confess "Attribute (last_name) does not pass the type constraint because: "
471 . "Validation failed for 'Str' with value $args{last_name}"
472 if ref($args{last_name});
473 $self->{last_nane} = $args{last_name};
476 return bless $self, $class;
484 confess "Attribute (last_name) does not pass the type constraint because: "
485 . "Validation failed for 'Str' with value $value"
487 $self->{last_name} = $value;
490 return $self->{last_name};
498 <h1>Side by side</h1>
500 <table class="side-by-side">
503 <pre><code>package Person;
504 <span class="match-moose">use Moose;</span>
506 has last_name => (
512 <pre class="small"><code>package Person;
513 <span class="match-unsweet">use strict;
520 my $self = {};</span>
522 if (exists $args{last_name}) {
523 confess "Attribute (last_name) does not pass the type constraint because: "
524 . "Validation failed for 'Str' with value $args{last_name}"
525 if ref($args{last_name});
526 $self->{last_nane} = $args{last_name};
529 <span class="match-unsweet">return bless $self, $class;
537 confess "Attribute (last_name) does not pass the type constraint because: "
538 . "Validation failed for 'Str' with value $value"
540 $self->{last_name} = $value;
543 return $self->{last_name};
551 <h1>Side by side</h1>
553 <table class="side-by-side">
556 <pre><code>package Person;
559 <span class="match-moose">has last_name => (</span>
562 <span class="match-moose">);</span></code></pre>
565 <pre class="small"><code>package Person;
575 <span class="match-unsweet">if (exists $args{last_name}) {</span>
576 confess "Attribute (last_name) does not pass the type constraint because: "
577 . "Validation failed for 'Str' with value $args{last_name}"
578 if ref($args{last_name});
579 <span class="match-unsweet">$self->{last_nane} = $args{last_name};
582 return bless $self, $class;
590 confess "Attribute (last_name) does not pass the type constraint because: "
591 . "Validation failed for 'Str' with value $value"
593 $self->{last_name} = $value;
596 return $self->{last_name};
604 <h1>Side by side</h1>
606 <table class="side-by-side">
609 <pre><code>package Person;
612 has last_name => (
613 <span class="match-moose">is => 'rw',</span>
618 <pre class="small"><code>package Person;
628 if (exists $args{last_name}) {
629 confess "Attribute (last_name) does not pass the type constraint because: "
630 . "Validation failed for 'Str' with value $args{last_name}"
631 if ref($args{last_name});
632 $self->{last_nane} = $args{last_name};
635 return bless $self, $class;
638 <span class="match-unsweet">sub last_name {
642 my $value = shift;</span>
643 confess "Attribute (last_name) does not pass the type constraint because: "
644 . "Validation failed for 'Str' with value $value"
646 <span class="match-unsweet">$self->{last_name} = $value;
649 return $self->{last_name};
650 }</span></code></pre>
657 <h1>Side by side</h1>
659 <table class="side-by-side">
662 <pre><code>package Person;
665 has last_name => (
667 <span class="match-moose">isa => 'Str',</span>
671 <pre class="small"><code>package Person;
681 if (exists $args{last_name}) {
682 <span class="match-unsweet">confess "Attribute (last_name) does not pass the type constraint because: "
683 . "Validation failed for 'Str' with value $args{last_name}"
684 if ref($args{last_name});</span>
685 $self->{last_nane} = $args{last_name};
688 return bless $self, $class;
696 <span class="match-unsweet">confess "Attribute (last_name) does not pass the type constraint because: "
697 . "Validation failed for 'Str' with value $value"
698 if ref($value);</span>
699 $self->{last_name} = $value;
702 return $self->{last_name};
710 <h1>Side by side</h1>
712 <table class="side-by-side">
713 <tr class="incremental">
717 <tr class="incremental">
718 <td>92 characters</td>
719 <td>741 characters</td>
723 <pre><code>package Person;
726 has last_name => (
732 <pre class="small"><code>package Person;
742 if (exists $args{last_name}) {
743 confess "Attribute (last_name) does not pass the type constraint because: "
744 . "Validation failed for 'Str' with value $args{last_name}"
745 if ref($args{last_name});
746 $self->{last_nane} = $args{last_name};
749 return bless $self, $class;
757 confess "Attribute (last_name) does not pass the type constraint because: "
758 . "Validation failed for 'Str' with value $value"
760 $self->{last_name} = $value;
763 return $self->{last_name};
773 <pre class="small"><code>sub new {
778 if (exists $args{last_name}) {
779 confess "Attribute (last_name) does not pass the type constraint because: "
780 . "Validation failed for 'Str' with value $args{last_name}"
781 if ref($args{last_name});
782 $self->{last_nane} = $args{last_name};
785 return bless $self, $class;
792 <pre class="small"><code>if (exists $args{last_name}) {
793 confess "Attribute (last_name) does not pass the type constraint because: "
794 . "Validation failed for 'Str' with value $args{last_name}"
795 if ref($args{last_name});
796 $self->{last_nane} = $args{last_name};
803 <code>$self->{last_nane} = $args{last_name};</code>
808 <code>$self->{last_na<span class="highlight">n</span>e}</code>
814 <pre><code>package Person;
817 has last_name => (
823 <div class="slide fake-slide0">
824 <h1>Part 1: Moose Classes</h1>
828 <h1>Moose Classes</h1>
831 <li>Moose classes are Perl packages which <code>use Moose</code></li>
836 <h1>Moose.pm and Your Class</h1>
838 <pre><code>package Person;
839 use Moose;</code></pre>
842 <li><code>Moose.pm</code> provides declarative sugar</li>
843 <li>Turns on <code>strict</code> and <code>warnings</code></li>
844 <li>Creates metaclasses for your class: <code>Person->meta</code></li>
845 <li>Moose classes automatically inherit from <code>Moose::Object</code></li>
850 <h1>What <code>Moose::Object</code> Provides</h1>
853 <li>Constructor - <code>new()</code></li>
854 <li>Calls your <code>BUILDARGS()</code> and/or <code>BUILD()</code></li>
855 <li>Calls your <code>DEMOLISH</code> during object destruction</li>
863 <li><code>extends</code> is sugar for declaring parent classes</li>
866 <pre><code>package Employee;
868 <span class="highlight">extends 'Person';</span></code></pre>
875 <li>Each call to <code>extends</code> <strong>resets</strong> your parents</li>
878 <h2 class="wrong">WRONG</h2>
880 <pre><code>package EvilEmployee;
883 extends 'Thief';</pre></code>
885 <h2 class="right">RIGHT</h2>
887 <pre><code>package EvilEmployee;
889 extends 'Person', 'Thief';</pre></code>
893 <h1>Extending un-Moose-y Parents</h1>
895 <pre><code>package My::LWP;
897 extends 'LWP';</pre></code>
900 <li>No <code>Moose::Object</code>, so ...
902 <li>No attribute-handling <code>new()</code></li>
903 <li>No <code>BUILDARGS()</code> or <code>BUILD()</code></li>
904 <li>No <code>DEMOLISH()</code></li>
907 <li>But see <code>MooseX::NonMoose</code> for a workaround</li>
912 <h1><code>overrides</code> and <code>super</code></h1>
915 <li><code>overrides</code> is another method modifier</li>
916 <li>An alternative to Perl's <code>SUPER::</code></li>
921 <h1><code>overrides</code> and <code>super</code></h1>
923 <pre><code>package Employee;
926 <span class="incremental current">extends 'Person';</span>
928 <span class="incremental">overrides</span> work => sub {
931 die "Pay me first" unless $self->got_paid;
932 <span class="incremental">super();</span>
933 }<span class="incremental">;</span></code></pre>
936 <h1>Caveat <code>super</code></h1>
939 <li>Mostly like <code>$self->SUPER::work(@_)</code></li>
940 <li><strong>But</strong> cannot change <code>@_</code>!</li>
941 <li>Binds the parent's method at compile time</li>
946 <h1>Attributes (Part 1)</h1>
949 <li><code>has 'foo'</code></li>
950 <li>Use <code>is => 'ro'</code> or <code>is => 'rw'</code></li>
951 <li>Attributes without "is" have no accessors</li>
956 <h1>Read-write attributes</h1>
958 <pre><code>package Person;
961 has 'first_name' => ( <span class="highlight">is => 'rw'</span> );
964 Person->new( first_name => 'Dave' );
966 $person->first_name('Stevan');
967 print $person->first_name; # Stevan</code></pre>
972 <h1>Read-only attributes</h1>
974 <pre><code>package Person;
977 has 'first_name' => ( <span class="highlight">is => 'ro'</span> );
980 Person->new( first_name => 'Dave' );
982 $person->first_name('Stevan');
983 print $person->first_name; # Dave</code></pre>
988 <h1>There is More to Come</h1>
991 <li>Attributes have a <em>lot</em> of features</li>
996 <h1>Cleaning Up Moose Droppings</h1>
998 <pre><code>package Person;
1002 Person->can('extends');</code></pre>
1005 <li>Not very hygienic</li>
1010 <h1>Cleaning Up Moose Droppings</h1>
1012 <pre><code>package Person;
1020 Person->can('extends');</code></pre>
1027 <li><code>no Moose</code> at the end of a package is a best practice</li>
1033 <h1>Immutability</h1>
1036 <li><span style="font-family: URW Chancery L; font-size: 140%">Stevan's Incantation of Fleet-Footedness</span></li>
1039 <pre><code>package Person;
1042 <span class="highlight">__PACKAGE__->meta->make_immutable;</span></code></pre>
1046 <h1>What <code>make_immutable</code> does</h1>
1050 <li>Uses <code>eval</code> to "inline" a constructor</li>
1051 <li>Memoizes a lot of meta-information</li>
1052 <li>Makes loading your class slower</li>
1053 <li>Makes object creation <em>much</em> faster</li>
1058 <h1>When to Immutabilize?</h1>
1061 <li><em>Almost</em> always</li>
1062 <li>Startup time vs execution time</li>
1070 $ perl bin/prove -lv t/00-prereq.t
1072 Missing anything? Install it. (see tarballs/)
1074 # perl bin/prove -lv t/01-classes.t
1076 Iterate til this passes all its tests