1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
5 <html xmlns="http://www.w3.org/1999/xhtml">
10 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
11 <meta name="generator" content="TextMate/S5" />
12 <meta name="version" content="S5 1.2a2" />
13 <meta name="presdate" content="2008" />
14 <meta name="author" content="Yuval Kogman" />
15 <meta name="company" content="" />
16 <!-- configuration parameters -->
17 <meta name="defaultView" content="slideshow" />
18 <meta name="controlVis" content="visible" />
19 <!-- style sheet links -->
20 <link rel="stylesheet" href="./ui/moose/slides.css" type="text/css" media="projection" id="slideProj" />
21 <link rel="stylesheet" href="./ui/moose/outline.css" type="text/css" media="screen" id="outlineStyle" />
22 <link rel="stylesheet" href="./ui/moose/print.css" type="text/css" media="print" id="slidePrint" />
23 <link rel="stylesheet" href="./ui/moose/opera.css" type="text/css" media="projection" id="operaFix" />
24 <!-- embedded styles -->
25 <style type="text/css" media="all">
26 .imgcon {width: 525px; margin: 0 auto; padding: 0; text-align: center;}
27 #anim {width: 270px; height: 320px; position: relative; margin-top: 0.5em;}
28 #anim img {position: absolute; top: 42px; left: 24px;}
29 img#me01 {top: 0; left: 0;}
30 img#me02 {left: 23px;}
32 img#me05 {top: 43px;left: 36px;}
35 <script src="./ui/moose/slides.js" type="text/javascript"></script>
40 <div id="controls"><!-- DO NOT EDIT --></div>
41 <div id="currentSlide"><!-- DO NOT EDIT --></div>
42 <div id="header"></div>
44 <h1>YAPC::Asia::2008</h1>
47 <div class="topleft"></div>
48 <div class="topright"></div>
49 <div class="bottomleft"></div>
50 <div class="bottomright"></div>
53 <div class="presentation">
69 <li>Just another accessor builder</li>
70 <li>A source filter</li>
71 <li>Perl black magic</li>
72 <li>Perl 6 in Perl 5</li>
81 <li>A complete modern object framework for Perl</li>
90 <li>Syntactic Sugar for <code>Class::MOP</code></li>
93 <li>CLOS (Common Lisp Object System)</li>
95 <li>Alces latifrons</li>
99 <li>Stable & Production ready</li>
100 <li>Polite, incremental</li>
106 <h1>A Simple Example</h1>
115 my ( $class, @args ) = @_;
117 @args = %{$args[0]} if @args == 1;
125 my ($self, @args) = @_;
126 $self->{name} = $args[0] if @args;
127 return $self->{name};
131 my ($self, @args) = @_;
132 $self->{age} = $args[0] if @args;
142 <h1>A Simple Moose Example</h1>
148 has name => (is => 'rw');
149 has age => (is => 'rw');
157 <h1>A Simple Moose Example (cont.)</h1>
160 <li><code>use Moose;</code>
162 <li>imports keywords</li>
163 <li><code>use strict; use warnings;</code></li>
164 <li><code>@ISA = qw(Moose::Object) unless @ISA</code></li>
171 <h1>A Simple Moose Example (cont.)</h1>
174 <li><p><code>has</code> declares attributes</p>
177 <li>generates accessors</li>
178 <li><code>is => 'rw'</code> → read/write accessor</li>
179 <li><code>is => 'ro'</code> → read only accessor</li>
180 <li><code>writer</code>, <code>reader</code></li>
182 <li><p><code>new</code> inherited from <code>Moose::Object</code></p></li>
186 <p>Now we’re going to discuss more features of the attributes</p>
191 <h1>Variations on a Moose Example</h1>
207 default => sub { [qw(Bob Alice Tim)] },
212 <p>Adds default, isa</p>
217 <h1>Variations on a Moose Example (cont.)</h1>
220 <li><p><code>default</code> is a</p>
223 <li>code reference</li>
224 <li>or non-reference (numbers, strings)</li>
225 <li>used when no parameter is given to <code>new</code></li>
227 <li><p><code>lazy</code> delays <code>default</code></p>
230 <li>called on first usage of <code>$object->staff</code></li>
231 <li>not inside <code>new</code></li>
236 <p>discusses default</p>
238 <p>non refs make accidental sharing hard</p>
243 <h1>Variations on a Moose Example (cont.)</h1>
246 <li><code>isa</code> specifies a type
248 <li><code>Moose::Util::TypeConstraints</code>
250 <li><code>Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object and Role</code></li>
252 <li>Types don’t need to exist</li>
257 has 'date' => (isa => 'DateTime'); # DWIM
261 <p>isa, type constraints</p>
266 <h1>Typical Family</h1>
269 <li>Types have a hierarchy
271 <li><code>Item</code> ⊃ <code>Defined</code> ⊃ <code>Ref</code> ⊃ <code>Object</code></li>
278 => where { ref($_) };
282 => where { blessed($_) }
286 <p>type hierarchy</p>
291 <h1>Conventional Delegates</h1>
302 manager_name => 'name',
303 coworkers => 'staff',
309 <li>manager <code>handles</code> certain methods for <code>Employee</code>
311 <li><code>$emp->coworkers</code> == <code>$emp->manager->staff</code></li>
318 <h1>Conventional Delegates (cont.)</h1>
323 handles => [qw(number extension)],
330 <h1>Conventional Delegates (cont.)</h1>
336 handles => qr/^[a-z]w+$/,
343 <h1>Conventional Delegates (cont.)</h1>
348 handles => "Dialing", # a role
355 <h1>UnConventional Delegates</h1>
360 use MooseX::AttributeHelpers;
363 metaclass => 'Collection::Array',
364 isa => 'ArrayRef[Employees]',
367 push => 'add_employee',
368 pop => 'remove_employee',
369 count => 'number_of_employees',
370 empty => 'any_employees',
378 <h1>Modified Methods</h1>
381 before 'employees' => sub { warn 'calling employees' };
383 after 'employees' => sub { warn 'finished calling employees' };
389 <li>Get a copy of <code>@_</code></li>
390 <li>Return value is ignored</li>
397 <h1>Modified Methods (cont.)</h1>
400 around 'employees' => sub {
401 my ($next, $self, @args) = @_;
403 my @return = $self->$next(@args);
412 <h1>Modified Methods (cont.)</h1>
423 inner(); # call subclass here
432 <h1>Modified Methods (cont.)</h1>
435 package Employee::Chef;
438 extends qw(Employee);
440 augment do_work => sub {
444 $self->flip_burger(shift @burgers);
448 $chef->do_work; # punch in, flip burgers, punch out
454 <h1>Some Type of Coercion</h1>
459 use Moose::Util::TypeConstraints;
462 class_type 'Manager';
464 coerce 'Manager' => (
465 from 'Str' => via { Manager->new( name => $_ ) },
479 <h1>Some Type of Coercion (cont.)</h1>
482 # import type constraint keywords
483 use Moose::Util::TypeConstraints;
486 # define Manager, a subtype of Object
487 class_type "Manager";
490 # define the conversion
491 ... via { Manager->new( name => $_ ) }
494 # enable it per attribute
502 <p>breakdown of the example</p>
504 <p>class types are automatically created for all Moose classes</p>
509 <h1>Some Type of Digression</h1>
514 isa => 'ArrayRef[Employee]',
517 has shopping_carts => (
519 isa => 'ArrayRef[ArrayRef[ShinyBead]]'
524 <p>Going to go into features of the type system for a bit</p>
526 <p>Parametrized types</p>
531 <h1>Some Type of Digression (cont.)</h1>
536 isa => 'English | Welsh | Scots | Gaelic',
541 isa => 'Employee | ArrayRef[ Employee | Group ]',
551 <h1>Some Type of Digression (cont.)</h1>
556 use Moose::Util::TypeConstraints;
558 use Test::Deep qw(eq_deeply ...);
560 type 'SomethingTricky' => where {
561 eq_deeply( $_, ... );
566 isa => 'SomethingTricky',
571 <p>Test::Deep custom validator</p>
573 <p>Can use any validation from the CPAN</p>
578 <h1>Some Parametrized Type of Coercion</h1>
581 use Moose::Util::TypeConstraints;
583 subtype 'ArrayRef[Employee]' => as 'ArrayRef';
585 coerce 'ArrayRef[Employee]' => (
586 from 'ArrayRef[Str]' via {
587 [ map { Employee->new( name => $_ ) } @$_ ]
592 isa => 'ArrayRef[Employee]',
598 <p>coerce parametrized ArrayRef[Employee] from ArrayRef[Str]</p>
603 <h1>Role of the Moose </h1>
606 <li>A role is like a…
608 <li>Java Interface: safe</li>
609 <li>mixin: useful</li>
611 <li>A role is for small reusable behaviors
613 <li>better than using a multiple inheritence</li>
620 <h1>Role of the Moose (cont.)</h1>
623 <li>Roles on the CPAN:
625 <li><code>MooseX::Clone</code> - Flexible <code>clone</code> method</li>
626 <li><code>MooseX::Storage</code> - Flexible serialization</li>
627 <li><code>MooseX::Getopt</code> - <code>@ARGV</code> aware constructor</li>
628 <li><code>MooseX::LogDispatch</code> - <code>$self->logger->info("something happenned")</code></li>
629 <li><code>MooseX::Param</code> - <code>param</code> method like <code>CGI.pm</code>’s,</li>
634 <p>Some examples of small reusable behaviors</p>
636 <p>Param is good for interacting with e.g. CGI::Expand or similar modules</p>
641 <h1>Role of the Moose (cont.)</h1>
647 extends qw(Employee);
649 with qw(Salaried::Hourly);
655 extends qw(Employee);
657 with qw(Salaried::Monthly);
662 <li><code>with</code> adds roles into your class
664 <li><code>Salaried::Hourly</code> was added to <code>Minion</code></li>
671 <h1>Role of the Moose (cont.)</h1>
677 requires 'paycheck_amount';
681 <li>Just an interface</li>
687 <h1>Role of the Moose (cont.)</h1>
690 package Salaried::Hourly;
701 has logged_hours => (
707 # satisfy the Salaried interface:
708 sub paycheck_amount {
710 $self->logged_hours * $self->hourly_rate;
716 <li>More than an interface</li>
722 <h1>Role of the Moose (cont.)</h1>
725 <li>More than Java Interfaces
727 <li>Interfaces are behavior “contracts”</li>
728 <li>Roles can also have code</li>
733 <p>roles can have attributes and methods
734 roles provide behavior, not just interface</p>
739 <h1>Role of the Moose (cont.)</h1>
744 <li>Not inheritence</li>
753 <h1>Role of the Moose (cont.)</h1>
758 <li>Less ambiguity</li>
759 <li>Compile time errors</li>
760 <li>…And ways to fix them</li>
765 <p>symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved
766 multiple inheritence silently assumes you want the first class</p>
768 <p>roles cause errors at compile time, unlike multiple inheritence</p>
770 <p>roles also provide easy ways to fix the errors</p>
775 <h1>Role of the Moose (cont.)</h1>
808 <h1>Role of the Moose (cont.)</h1>
822 bark => "bark_sound",
839 <li>Not that common in practice</li>
843 <p>Composition parameters
844 Easier conflict resolution
845 Finer grained control</p>
850 <h1>MOPs Mean Cleanliness</h1>
853 <li>Moose is based on <code>Class::MOP</code>
855 <li>Metaobject Protocol for Perl 5</li>
856 <li>“makes an object for everything”</li>
861 my $class = $obj->meta; # $obj's metaclass
862 my $meta = MyApp->meta; # MyApp's metaclass
863 my $emo = $obj->meta->meta; # even more meta!
865 warn $obj->meta->name;
871 <h1>Looking in From the Inside</h1>
874 my $metaclass = $self->meta;
876 $metaclass->superclasses;
878 $metaclass->linearized_isa;
880 $metaclass->has_method("foo");
882 $metaclass->compute_all_applicable_attributes;
888 <p>simple introspection</p>
893 <h1>Looking in From the Inside (cont.)</h1>
896 Moose::Meta::Class->create( Bar =>
898 superclasses => [ 'Foo' ],
900 Moose::Meta::Attribute->new( bar => ... ),
901 Moose::Meta::Attribute->new( baz => ... ),
904 calculate_bar => sub { ... },
905 construct_baz => sub { ... }
909 my $anon_meta = Moose::Meta::Class->create_anon_class( ... );
913 <p>Classes can be created programmatically</p>
918 <h1>Looking in From the Inside (cont.)</h1>
921 has foo => ( is => "rw" );
923 __PACKAGE__->meta->add_attribute(
930 <li>Moose is just sugar
932 <li>The MOP does the hard work</li>
939 <h1>The Metaclass Tango</h1>
942 <li>Metaclassses control class behavior</li>
947 metaclass => 'Collection::Array',
953 <li>custom attribute metaclasses
955 <li>change how attributes work</li>
957 <li>Many customizable parts
959 <li><code>Moose::Meta::Class</code>, <code>Moose::Meta::Attribute,</code><code>Moose::Meta::Method</code>, <code>Moose::Meta::Method::Accessor</code> <code>Moose::Meta::Instance</code>, <code>Moose::Meta::Role</code>, <code>Moose::Meta::TypeConstraint</code>, …,</li>
966 <h1>Working in the Meta Frame</h1>
969 <li><code>$work</code> project:</li>
970 <li>CMS for a flash website</li>
971 <li>Content is in XML</li>
977 <h1>Working in the Meta Frame (cont.)</h1>
980 <li>Step 1. use Moose</li>
982 <li>Step 3. Profit!</li>
988 <h1>Working in the Meta Frame (cont.)</h1>
991 <li>Step 2.1. Client’s XML schemas → Moose classes
993 <li>Automatic class definitions</li>
994 <li>High level objects in runtime</li>
995 <li>XML storage backed
1006 <h1>Working in the Meta Frame (cont.)</h1>
1009 <li>Step 2.2. Meta descriptions
1011 <li>Extend the metaclasses</li>
1012 <li>Embed additional information
1014 <li>field types</li>
1015 <li>access control</li>
1023 <h1>Working in the Meta Frame (cont.)</h1>
1026 <li>Step 2.3 Introspection goodness
1028 <li>Generic web frontend</li>
1029 <li>Object introspection based
1032 <li>Editing widgets</li>
1034 <li>Clean, extensible</li>
1041 <h1>Drawbacks of Moose</h1>
1046 <li><code>MooseX::Compile</code> is in the works</li>
1048 <li>Some features are slow
1050 <li>but you only pay for what you use</li>
1052 <li>Extending non-Hash based classes is tricky.
1054 <li>but possible: <code>MooseX::GlobRef::Object</code></li>
1061 <h1>Benefits of Moose</h1>
1064 <li>Less boilerplate
1066 <li>attribute storage/access</li>
1067 <li>construction</li>
1068 <li>destruction</li>
1069 <li>verification</li>
1077 <h1>Benefits of Moose (cont.)</h1>
1082 <li>less reading</li>
1083 <li>less writing</li>
1084 <li>less code means fewer bugs</li>
1091 <h1>Benefits of Moose (cont.)</h1>
1096 <li>Moose is very well tested
1098 <li>no need to check accessor behavior, etc</li>
1100 <li>focus on your code’s purpose
1102 <li>not that it is “assembled” correctly</li>
1103 <li>http://c2.com/cgi/wiki?IntentionNotAlgorithm</li>
1111 <h1>Benefits of Moose (cont.)</h1>
1116 <li>declarative style is self documenting</li>
1117 <li>good signal to noise ratio</li>
1124 <h1>Benefits of Moose (cont.)</h1>
1127 <li>Meta object protocol
1129 <li>Cleans up Perl’s OO</li>
1130 <li>Provides introspection</li>
1131 <li>Enables powerful abstractions</li>
1138 <h1>Benefits of Moose (cont.)</h1>
1141 <li>It’s the new black
1143 <li>All the cool kids hang out on #moose</li>
1144 <li>Smart sounding buzzwords</li>
1145 <li>Chicks dig antlers</li>
1146 <li>Ruby is so 2007</li>
1153 <h1>Bonus Material</h1>
1161 package Units::Bytes;
1166 sub kilobytes { $_[0] * 1024 }
1167 sub megabytes { $_[0] * 1024->kilobytes }
1168 sub gigabytes { $_[0] * 1024->megabytes }
1169 sub terabytes { $_[0] * 1024->gigabytes }
1171 Moose::Autobox->mixin_additional_role(
1172 SCALAR => 'Units::Bytes',
1179 <h1>Autobox (cont.)</h1>
1183 use Moose::Autobox; # autoboxing is lexical
1185 is(5->bytes, 5, '... got 5 bytes');
1186 is(5->kilobytes, 5120, '... got 5 kilobytes');
1187 is(2->megabytes, 2097152, '... got 2 megabytes');
1188 is(1->gigabytes, 1073741824, '... got 1 gigabyte');
1189 is(2->terabytes, 2199023255552, '... got 2 terabytes');
1195 <h1>perl -Moose</h1>
1198 <li>Moose One Liners with <code>oose.pm</code></li>
1202 perl -Moose -e 'has foo => ( is=> "rw" ); Class->new( foo => 1 )'
1206 <li>Useful for testing if something works</li>
1207 <li>Helpful on IRC</li>
1208 <li><code>Devel::REPL</code> is cooler though ;-)</li>
1214 <h1>MooseX::POE</h1>
1219 use MooseX::AttributeHelpers;
1222 traits => [qw(Counter)],
1223 provides => { inc => "increment_count" },
1227 shift->yield('increment');
1230 event increment => sub {
1233 warn "Count is now " . $self->count;
1235 $self->increment_count;
1236 $self->yield('increment') unless $self->count > 3;
1239 Counter->new( count => 0 );
1244 <li>PoCos made easy</li>
1245 <li>Every object has a <code>POE::Session</code></li>
1246 <li><code>event</code> declares POE object states</li>
1255 <li><p>Slides written by:</p>
1258 <li>Chris Prather</li>
1259 <li>Stevan Little</li>
1260 <li>Robert Boone</li>
1262 <li><p>Slides deleted by:</p>
1265 <li>Yuval Kogman</li>