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>
67 <li>Moose builds on Perl 5's native OO</li>
68 <li>Borrows ideas from other languages, notably Perl 6</li>
69 <li>Provides semantics for common operations</li>
83 <li>Method modifiers</li>
84 <li>Constructor and destructor</li>
85 <li>One metaclass object</li>
88 <li>Classes do roles</li>
93 <h1>Class Example</h1>
95 <pre><code>package Person;
96 <span class="highlight">use Moose;</span></code></pre>
99 <li>Poof, a Moose-based class!</li>
107 <li>Aka property, slot, field, member variable</li>
108 <li>A piece of data owned by an object</li>
119 <li>Access-control (read-only vs read-write)</li>
120 <li>An optional type</li>
121 <li>Accessor methods</li>
122 <li>Delegation methods</li>
123 <li>Optional default value</li>
124 <li>Many more features</li>
127 <li>Stored in the object, but don't worry about that</li>
132 <h1>Attribute Example</h1>
134 <pre><code>package Person;
137 <span class="highlight">has 'first_name' => ( is => 'rw' );</span></code></pre>
145 <li>Nothing fancy here, just Perl subroutines</li>
148 <pre><code>package Person;
151 <span class="highlight">sub greet { ... }</span></code></pre>
158 <li>Classes <strong>do</strong> (or consume) roles</li>
159 <li>Similar to mixins and Java interfaces</li>
167 <li>Like classes, can have attributes, methods, do roles</li>
168 <li>Roles can require methods</li>
169 <li>Roles are composed (flattened) into classes</li>
174 <h1>Role Example</h1>
176 <pre><code>package HasPermissions;
177 <span class="highlight">use Moose::Role;</span>
179 has is_admin => ( is => 'rw' );</code></pre>
183 <h1>Role Example</h1>
189 <pre><code>package Person;
192 <span class="highlight">with 'HasPermissions';</span></code></pre>
196 <h1>Method Modifiers</h1>
200 <li>"<strong>Before</strong> foo(), do this first"</li>
201 <li>"Do this <strong>after</strong> foo()</li>
202 <li>"Put this code <strong>around</strong> foo()"</li>
207 <h1>Before & After</h1>
209 <pre><code>before 'foo'
210 => sub { warn 'About to call foo()' };
213 => sub { warn 'Leaving foo()' };</code></pre>
220 <pre><code>around 'foo' => sub {
221 my $real_foo = shift;
224 warn 'Just before foo()';
226 $self->$real_foo( @_, bar => 42 );
228 return ( @return, 'modify return values' );
233 <h1>Type Constraints</h1>
236 <li>NOT A FULL-BLOWN TYPE SYSTEM!</li>
237 <li>But still darn useful</li>
238 <li>Constrain attribute values</li>
239 <li>Coerce from other types</li>
244 <h1>Type Constraint Example</h1>
246 <pre><code>package Person;
249 has 'weight' => ( is => 'ro', <span class="highlight">isa => 'Int'</span> );
252 Person->new( weight => 'fat' );</code></pre>
259 <li>Attributes can define delegations</li>
260 <li>Lets you hide some implementation details</li>
261 <li>Fewer objects to chase around</li>
268 <pre><code>package Person;
271 has 'blog_uri' => (
274 <span class="highlight">handles => { 'blog_hostname' => 'host' },</span>
277 <span class="highlight">$person->blog_hostname;</span>
278 # really calls $person->blog_uri->host
282 <h1>Constructors</h1>
285 <li>Moose creates <code>new()</code> for you</li>
286 <li>Provide an optional <code>BUILDARGS()</code> and <code>BUILD()</code></li>
294 <li>Provide an optional <code>DEMOLISH()</code></li>
299 <h1>Moose Meta-API</h1>
302 <li>Answers questions like ...
304 <li>What methods does this class have?</li>
305 <li>What are its parents?</li>
306 <li>What attributes does it have (including inherited attributes)?</li>
307 <li>What roles does it do?</li>
308 <li>Much, much, more</li>
315 <h1>Moose Meta-API</h1>
318 <li>Not just for introspection ...
320 <li>Add methods, attributes, roles, etc</li>
321 <li>Extend and alter core features</li>
331 <li>A quick bit of propoganda ...</li>
338 <pre><code>package Person;
341 has last_name => (
348 <h1>Without Moose</h1>
350 <pre class="small"><code>package Person;
360 if (exists $args{last_name}) {
361 confess "Attribute (last_name) does not pass the type constraint because: "
362 . "Validation failed for 'Str' with value $args{last_name}"
363 if ref($args{last_name});
364 $self->{last_nane} = $args{last_name};
367 return bless $self, $class;
375 confess "Attribute (last_name) does not pass the type constraint because: "
376 . "Validation failed for 'Str' with value $value"
378 $self->{last_name} = $value;
381 return $self->{last_name};
387 <h1>Side by side</h1>
389 <table class="side-by-side">
392 <pre><code>package Person;
395 has last_name => (
401 <pre class="small"><code>package Person;
411 if (exists $args{last_name}) {
412 confess "Attribute (last_name) does not pass the type constraint because: "
413 . "Validation failed for 'Str' with value $args{last_name}"
414 if ref($args{last_name});
415 $self->{last_nane} = $args{last_name};
418 return bless $self, $class;
426 confess "Attribute (last_name) does not pass the type constraint because: "
427 . "Validation failed for 'Str' with value $value"
429 $self->{last_name} = $value;
432 return $self->{last_name};
441 <h1>Side by side</h1>
443 <table class="side-by-side">
446 <pre><code><span class="match-moose">package Person;</span>
449 has last_name => (
455 <pre class="small"><code><span class="match-unsweet">package Person;</span>
465 if (exists $args{last_name}) {
466 confess "Attribute (last_name) does not pass the type constraint because: "
467 . "Validation failed for 'Str' with value $args{last_name}"
468 if ref($args{last_name});
469 $self->{last_nane} = $args{last_name};
472 return bless $self, $class;
480 confess "Attribute (last_name) does not pass the type constraint because: "
481 . "Validation failed for 'Str' with value $value"
483 $self->{last_name} = $value;
486 return $self->{last_name};
494 <h1>Side by side</h1>
496 <table class="side-by-side">
499 <pre><code>package Person;
500 <span class="match-moose">use Moose;</span>
502 has last_name => (
508 <pre class="small"><code>package Person;
509 <span class="match-unsweet">use strict;
516 my $self = {};</span>
518 if (exists $args{last_name}) {
519 confess "Attribute (last_name) does not pass the type constraint because: "
520 . "Validation failed for 'Str' with value $args{last_name}"
521 if ref($args{last_name});
522 $self->{last_nane} = $args{last_name};
525 <span class="match-unsweet">return bless $self, $class;
533 confess "Attribute (last_name) does not pass the type constraint because: "
534 . "Validation failed for 'Str' with value $value"
536 $self->{last_name} = $value;
539 return $self->{last_name};
547 <h1>Side by side</h1>
549 <table class="side-by-side">
552 <pre><code>package Person;
555 <span class="match-moose">has last_name => (</span>
558 <span class="match-moose">);</span></code></pre>
561 <pre class="small"><code>package Person;
571 <span class="match-unsweet">if (exists $args{last_name}) {</span>
572 confess "Attribute (last_name) does not pass the type constraint because: "
573 . "Validation failed for 'Str' with value $args{last_name}"
574 if ref($args{last_name});
575 <span class="match-unsweet">$self->{last_nane} = $args{last_name};
578 return bless $self, $class;
586 confess "Attribute (last_name) does not pass the type constraint because: "
587 . "Validation failed for 'Str' with value $value"
589 $self->{last_name} = $value;
592 return $self->{last_name};
600 <h1>Side by side</h1>
602 <table class="side-by-side">
605 <pre><code>package Person;
608 has last_name => (
609 <span class="match-moose">is => 'rw',</span>
614 <pre class="small"><code>package Person;
624 if (exists $args{last_name}) {
625 confess "Attribute (last_name) does not pass the type constraint because: "
626 . "Validation failed for 'Str' with value $args{last_name}"
627 if ref($args{last_name});
628 $self->{last_nane} = $args{last_name};
631 return bless $self, $class;
634 <span class="match-unsweet">sub last_name {
638 my $value = shift;</span>
639 confess "Attribute (last_name) does not pass the type constraint because: "
640 . "Validation failed for 'Str' with value $value"
642 <span class="match-unsweet">$self->{last_name} = $value;
645 return $self->{last_name};
646 }</span></code></pre>
653 <h1>Side by side</h1>
655 <table class="side-by-side">
658 <pre><code>package Person;
661 has last_name => (
663 <span class="match-moose">isa => 'Str',</span>
667 <pre class="small"><code>package Person;
677 if (exists $args{last_name}) {
678 <span class="match-unsweet">confess "Attribute (last_name) does not pass the type constraint because: "
679 . "Validation failed for 'Str' with value $args{last_name}"
680 if ref($args{last_name});</span>
681 $self->{last_nane} = $args{last_name};
684 return bless $self, $class;
692 <span class="match-unsweet">confess "Attribute (last_name) does not pass the type constraint because: "
693 . "Validation failed for 'Str' with value $value"
694 if ref($value);</span>
695 $self->{last_name} = $value;
698 return $self->{last_name};
706 <h1>Side by side</h1>
708 <table class="side-by-side">
709 <tr class="incremental">
713 <tr class="incremental">
714 <td>92 characters</td>
715 <td>741 characters</td>
719 <pre><code>package Person;
722 has last_name => (
728 <pre class="small"><code>package Person;
738 if (exists $args{last_name}) {
739 confess "Attribute (last_name) does not pass the type constraint because: "
740 . "Validation failed for 'Str' with value $args{last_name}"
741 if ref($args{last_name});
742 $self->{last_nane} = $args{last_name};
745 return bless $self, $class;
753 confess "Attribute (last_name) does not pass the type constraint because: "
754 . "Validation failed for 'Str' with value $value"
756 $self->{last_name} = $value;
759 return $self->{last_name};
769 <pre class="small"><code>sub new {
774 if (exists $args{last_name}) {
775 confess "Attribute (last_name) does not pass the type constraint because: "
776 . "Validation failed for 'Str' with value $args{last_name}"
777 if ref($args{last_name});
778 $self->{last_nane} = $args{last_name};
781 return bless $self, $class;
788 <pre class="small"><code>if (exists $args{last_name}) {
789 confess "Attribute (last_name) does not pass the type constraint because: "
790 . "Validation failed for 'Str' with value $args{last_name}"
791 if ref($args{last_name});
792 $self->{last_nane} = $args{last_name};
799 <code>$self->{last_nane} = $args{last_name};</code>
804 <code>$self->{last_na<span class="highlight">n</span>e}</code>
810 <pre><code>package Person;
813 has last_name => (
819 <div class="slide fake-slide0">
820 <h1>Moose Classes</h1>
824 <h1>Moose Classes</h1>
827 <li>Moose classes are Perl packages which <code>use Moose</code></li>
832 <h1>Moose.pm and Your Class</h1>
834 <pre><code>package Person;
835 use Moose;</code></pre>
838 <li><code>Moose.pm</code> provides declarative sugar</li>
839 <li>Turns on <code>strict</code> and <code>warnings</code></li>
840 <li>Creates metaclasses for your class: <code>Person->meta</code></li>
841 <li>Moose classes automatically inherit from <code>Moose::Object</code></li>
846 <h1>What <code>Moose::Object</code> Provides</h1>
849 <li>Constructor - <code>new()</code></li>
850 <li>Calls your <code>BUILDARGS()</code> and/or <code>BUILD()</code></li>
851 <li>Calls your <code>DEMOLISH</code> during object destruction</li>
859 <li><code>extends</code> is sugar for declaring parent classes</li>
862 <pre><code>package Employee;
864 <span class="highlight">extends 'Person';</span></code></pre>
871 <li>Each call to <code>extends</code> <strong>resets</strong> your parents</li>
874 <h2 class="wrong">WRONG</h2>
876 <pre><code>package EvilEmployee;
879 extends 'Thief';</pre></code>
881 <h2 class="right">RIGHT</h2>
883 <pre><code>package EvilEmployee;
885 extends 'Person', 'Thief';</pre></code>
889 <h1>Extending un-Moose-y Parents</h1>
891 <pre><code>package My::LWP;
893 extends 'LWP';</pre></code>
896 <li>No <code>Moose::Object</code>, so ...
898 <li>No attribute-handling <code>new()</code></li>
899 <li>No <code>BUILDARGS()</code> or <code>BUILD()</code></li>
900 <li>No <code>DEMOLISH()</code></li>
903 <li>But see <code>MooseX::NonMoose</code> for a workaround</li>
908 <h1><code>overrides</code> and <code>super</code></h1>
911 <li><code>overrides</code> is another method modifier</li>
912 <li>An alternative to Perl's <code>SUPER::</code></li>
917 <h1><code>overrides</code> and <code>super</code></h1>
919 <pre><code>package Employee;
922 <span class="incremental current">extends 'Person';</span>
924 <span class="incremental">overrides</span> work => sub {
927 die "Pay me first" unless $self->got_paid;
928 <span class="incremental">super();</span>
929 }<span class="incremental">;</span></code></pre>
932 <h1>Caveat <code>super</code></h1>
935 <li>Mostly like <code>$self->SUPER::work(@_)</code></li>
936 <li><strong>But</strong> cannot change <code>@_</code>!</li>
937 <li>Binds the parent's method at compile time</li>
942 <h1>Attributes (Part 1)</h1>
945 <li><code>has 'foo'</code></li>
946 <li>Use <code>is => 'ro'</code> or <code>is => 'rw'</code></li>
947 <li>Attributes without "is" have no accessors</li>
952 <h1>Read-write attributes</h1>
954 <pre><code>package Person;
957 has 'first_name' => ( <span class="highlight">is => 'rw'</span> );
960 Person->new( first_name => 'Dave' );
962 $person->first_name('Stevan');
963 print $person->first_name; # Stevan</code></pre>
968 <h1>Read-only attributes</h1>
970 <pre><code>package Person;
973 has 'first_name' => ( <span class="highlight">is => 'ro'</span> );
976 Person->new( first_name => 'Dave' );
978 $person->first_name('Stevan');
979 print $person->first_name; # Dave</code></pre>
984 <h1>There is More to Come</h1>
987 <li>Attributes have a <em>lot</em> of features</li>
992 <h1>Cleaning Up Moose Droppings</h1>
994 <pre><code>package Person;
998 Person->can('extends');</code></pre>
1001 <li>Not very hygienic</li>
1006 <h1>Cleaning Up Moose Droppings</h1>
1008 <pre><code>package Person;
1016 Person->can('extends');</code></pre>
1023 <li><code>no Moose</code> at the end of a package is a best practice</li>
1029 <h1>Immutability</h1>
1032 <li><span style="font-family: URW Chancery L; font-size: 140%">Stevan's Incantation of Fleet-Footedness</span></li>
1035 <pre><code>package Person;
1038 <span class="highlight">__PACKAGE__->meta->make_immutable;</span></code></pre>
1042 <h1>What <code>make_immutable</code> does</h1>
1046 <li>Uses <code>eval</code> to "inline" a constructor</li>
1047 <li>Memoizes a lot of meta-information</li>
1048 <li>Makes loading your class slower</li>
1049 <li>Makes object creation <em>much</em> faster</li>
1054 <h1>When to Immutabilize?</h1>
1057 <li><em>Almost</em> always</li>
1058 <li>Startup time vs execution time</li>
1063 <h1>Classes - Exercises</h1>
1066 $ prove -lv t/00-prereq.t
1068 Missing anything? Install it. (see tarballs/)
1070 # prove -lv t/01-classes.t