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">
67 <li>My name is Yuval</li>
73 <h1>WHY AM I HERE?</h1>
78 <p><img src="porn/cog.jpg" style="height: 75%"></p>
83 <p><img src="porn/chamonix.jpg" style="height: 75%"></p>
88 <p><img src="porn/clkao.jpg" style="height: 75%"></p>
93 <p><img src="porn/office.jpg" style="height: 75%"></p>
98 <p><img src="porn/kitchen.jpg" style="height: 75%"></p>
103 <p><img src="porn/blood.jpg" style="height: 75%"></p>
108 <p><img src="porn/intestines.jpg" style="height: 75%"></p>
113 <p><img src="porn/duck_head.jpg" style="height: 75%"></p>
118 <p><img src="porn/stinkytofu.jpg" style="height: 75%"></p>
123 <p><img src="porn/hunting.jpg" style="height: 75%"></p>
128 <p><img src="porn/tokyo.jpg" style="height: 75%"></p>
133 <p><img src="porn/tokyo_crazy.jpg" style="height: 75%"></p>
138 <p><img src="porn/uni.jpg" style="height: 75%"></p>
143 <p><img src="porn/vomit.jpg" style="height: 75%"></p>
148 <p><img src="porn/phone.jpg" style="height: 75%"></p>
153 <p><img src="porn/phone_no.jpg" style="height: 75%"></p>
158 <p><img src="porn/glasses.jpg" style="height: 75%"></p>
163 <p><img src="porn/glasses_no.jpg" style="height: 75%"></p>
168 <p><img src="porn/visa.jpg" style="height: 75%"></p>
173 <p><img src="porn/visa_no.jpg" style="height: 75%"></p>
178 <p><img src="porn/orz.jpg" style="height: 50%"></p>
180 <p><span style="font-family: sans-serif; font-weight: bold; font-size: 3em">orz orz orz </span></p>
185 <p><img src="porn/cog.jpg" style="height: 75%"></p>
190 <p><img src="porn/tubes.jpg" style="height: 75%"></p>
195 <p><img src="porn/jetpack.jpg" style="height: 75%"></p>
200 <p><img src="porn/food.jpg" style="height: 75%"></p>
205 <p><img src="porn/mousse.jpg" style="height: 75%"></p>
210 <p><img src="porn/beer.jpg" style="height: 75%"></p>
215 <p><img src="porn/zipbox.jpg" style="height: 75%"></p>
220 <p><img src="porn/laundry.jpg" style="height: 75%"></p>
225 <h1>So here I am</h1>
236 <p><img src="porn/moose_danger.jpg" style="height: 75%"></p>
241 <h1>Moose Is Not</h1>
244 <li>Experimental</li>
246 <li>Just another accessor builder</li>
247 <li>A source filter</li>
248 <li>Perl black magic</li>
249 <li>Perl 6 in Perl 5</li>
258 <li><a href="http://moose.perl.org">http://moose.perl.org</a></li>
259 <li>A complete modern object framework for Perl</li>
268 <li>Syntactic Sugar for <code>Class::MOP</code></li>
271 <li>CLOS (Common Lisp Object System)</li>
273 <li>Alces latifrons</li>
277 <li>Stable & Production ready</li>
278 <li>Polite, incremental</li>
284 <h1>A Simple Example</h1>
293 my ( $class, @args ) = @_;
295 @args = %{$args[0]} if @args == 1;
303 my ($self, @args) = @_;
304 $self->{name} = $args[0] if @args;
305 return $self->{name};
309 my ($self, @args) = @_;
310 $self->{age} = $args[0] if @args;
320 <h1>A Simple Moose Example</h1>
326 has name => (is => 'rw');
327 has age => (is => 'rw');
335 <h1>A Simple Moose Example (cont.)</h1>
338 <li><code>use Moose;</code>
340 <li>imports keywords</li>
341 <li><code>use strict; use warnings;</code></li>
342 <li><code>@ISA = qw(Moose::Object) unless @ISA</code></li>
349 <h1>A Simple Moose Example (cont.)</h1>
352 <li><p><code>has</code> declares attributes</p>
355 <li>generates accessors</li>
356 <li><code>is => 'rw'</code> → read/write accessor</li>
357 <li><code>is => 'ro'</code> → read only accessor</li>
358 <li><code>writer</code>, <code>reader</code></li>
360 <li><p><code>new</code> inherited from <code>Moose::Object</code></p></li>
364 <p>Now we’re going to discuss more features of the attributes</p>
369 <h1>Variations on a Moose Example</h1>
385 default => sub { [qw(Bob Alice Tim)] },
390 <p>Adds default, isa</p>
395 <h1>Variations on a Moose Example (cont.)</h1>
398 <li><p><code>default</code> is a</p>
401 <li>code reference</li>
402 <li>or non-reference (numbers, strings)</li>
403 <li>used when no parameter is given to <code>new</code></li>
405 <li><p><code>lazy</code> delays <code>default</code></p>
408 <li>called on first usage of <code>$object->staff</code></li>
409 <li>not inside <code>new</code></li>
414 <p>discusses default</p>
416 <p>non refs make accidental sharing hard</p>
421 <h1>Variations on a Moose Example (cont.)</h1>
424 <li><code>isa</code> specifies a type
426 <li><code>Moose::Util::TypeConstraints</code>
428 <li><code>Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object and Role</code></li>
430 <li>Types don’t need to exist</li>
435 has 'date' => (isa => 'DateTime'); # DWIM
439 <p>isa, type constraints</p>
444 <h1>Typical Family</h1>
447 <li>Types have a hierarchy
449 <li><code>Item</code> ⊃ <code>Defined</code> ⊃ <code>Ref</code> ⊃ <code>Object</code></li>
456 => where { ref($_) };
460 => where { blessed($_) }
464 <p>type hierarchy</p>
469 <h1>Conventional Delegates</h1>
480 manager_name => 'name',
481 coworkers => 'staff',
487 <li>manager <code>handles</code> certain methods for <code>Employee</code>
489 <li><code>$emp->coworkers</code> == <code>$emp->manager->staff</code></li>
496 <h1>Conventional Delegates (cont.)</h1>
501 handles => [qw(number extension)],
508 <h1>Conventional Delegates (cont.)</h1>
514 handles => qr/^[a-z]w+$/,
521 <h1>Conventional Delegates (cont.)</h1>
526 handles => "Dialing", # a role
533 <h1>UnConventional Delegates</h1>
538 use MooseX::AttributeHelpers;
541 metaclass => 'Collection::Array',
542 isa => 'ArrayRef[Employees]',
545 push => 'add_employee',
546 pop => 'remove_employee',
547 count => 'number_of_employees',
548 empty => 'any_employees',
556 <h1>Modified Methods</h1>
559 before 'employees' => sub { warn 'calling employees' };
561 after 'employees' => sub { warn 'finished calling employees' };
567 <li>Get a copy of <code>@_</code></li>
568 <li>Return value is ignored</li>
575 <h1>Modified Methods (cont.)</h1>
578 around 'employees' => sub {
579 my ($next, $self, @args) = @_;
581 my @return = $self->$next(@args);
590 <h1>Modified Methods (cont.)</h1>
601 inner(); # call subclass here
610 <h1>Modified Methods (cont.)</h1>
613 package Employee::Chef;
616 extends qw(Employee);
618 augment do_work => sub {
622 $self->flip_burger(shift @burgers);
626 $chef->do_work; # punch in, flip burgers, punch out
632 <h1>Some Type of Coercion</h1>
637 use Moose::Util::TypeConstraints;
640 class_type 'Manager';
642 coerce 'Manager' => (
643 from 'Str' => via { Manager->new( name => $_ ) },
657 <h1>Some Type of Coercion (cont.)</h1>
660 # import type constraint keywords
661 use Moose::Util::TypeConstraints;
664 # define Manager, a subtype of Object
665 class_type "Manager";
668 # define the conversion
669 ... via { Manager->new( name => $_ ) }
672 # enable it per attribute
680 <p>breakdown of the example</p>
682 <p>class types are automatically created for all Moose classes</p>
687 <h1>Some Type of Digression</h1>
692 isa => 'ArrayRef[Employee]',
695 has shopping_carts => (
697 isa => 'ArrayRef[ArrayRef[ShinyBead]]'
702 <p>Going to go into features of the type system for a bit</p>
704 <p>Parametrized types</p>
709 <h1>Some Type of Digression (cont.)</h1>
714 isa => 'English | Welsh | Scots | Gaelic',
719 isa => 'Employee | ArrayRef[ Employee | Group ]',
729 <h1>Some Type of Digression (cont.)</h1>
734 use Moose::Util::TypeConstraints;
736 use Test::Deep qw(eq_deeply ...);
738 type 'SomethingTricky' => where {
739 eq_deeply( $_, ... );
744 isa => 'SomethingTricky',
749 <p>Test::Deep custom validator</p>
751 <p>Can use any validation from the CPAN</p>
756 <h1>Some Parametrized Type of Coercion</h1>
759 use Moose::Util::TypeConstraints;
761 subtype 'ArrayRef[Employee]' => as 'ArrayRef';
763 coerce 'ArrayRef[Employee]' => (
764 from 'ArrayRef[Str]' via {
765 [ map { Employee->new( name => $_ ) } @$_ ]
770 isa => 'ArrayRef[Employee]',
776 <p>coerce parametrized ArrayRef[Employee] from ArrayRef[Str]</p>
781 <h1>Role of the Moose </h1>
784 <li>A role is like a…
786 <li>Java Interface: safe</li>
787 <li>mixin: useful</li>
789 <li>A role is for small reusable behaviors
791 <li>better than using a multiple inheritence</li>
798 <h1>Role of the Moose (cont.)</h1>
801 <li>Roles on the CPAN:
803 <li><code>MooseX::Clone</code> - Flexible <code>clone</code> method</li>
804 <li><code>MooseX::Storage</code> - Flexible serialization</li>
805 <li><code>MooseX::Getopt</code> - <code>@ARGV</code> aware constructor</li>
806 <li><code>MooseX::LogDispatch</code> - <code>$self->logger->info("something happenned")</code></li>
807 <li><code>MooseX::Param</code> - <code>param</code> method like <code>CGI.pm</code>’s,</li>
812 <p>Some examples of small reusable behaviors</p>
814 <p>Param is good for interacting with e.g. CGI::Expand or similar modules</p>
819 <h1>Role of the Moose (cont.)</h1>
825 extends qw(Employee);
827 with qw(Salaried::Hourly);
833 extends qw(Employee);
835 with qw(Salaried::Monthly);
840 <li><code>with</code> adds roles into your class
842 <li><code>Salaried::Hourly</code> was added to <code>Minion</code></li>
849 <h1>Role of the Moose (cont.)</h1>
855 requires 'paycheck_amount';
859 <li>Just an interface</li>
865 <h1>Role of the Moose (cont.)</h1>
868 package Salaried::Hourly;
879 has logged_hours => (
885 # satisfy the Salaried interface:
886 sub paycheck_amount {
888 $self->logged_hours * $self->hourly_rate;
894 <li>More than an interface</li>
900 <h1>Role of the Moose (cont.)</h1>
903 <li>More than Java Interfaces
905 <li>Interfaces are behavior “contracts”</li>
906 <li>Roles can also have code</li>
911 <p>roles can have attributes and methods
912 roles provide behavior, not just interface</p>
917 <h1>Role of the Moose (cont.)</h1>
922 <li>Not inheritence</li>
931 <h1>Role of the Moose (cont.)</h1>
936 <li>Less ambiguity</li>
937 <li>Compile time errors</li>
938 <li>…And ways to fix them</li>
943 <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
944 multiple inheritence silently assumes you want the first class</p>
946 <p>roles cause errors at compile time, unlike multiple inheritence</p>
948 <p>roles also provide easy ways to fix the errors</p>
953 <h1>Role of the Moose (cont.)</h1>
986 <h1>Role of the Moose (cont.)</h1>
1000 bark => "bark_sound",
1017 <li>Not that common in practice</li>
1021 <p>Composition parameters
1022 Easier conflict resolution
1023 Finer grained control</p>
1028 <h1>MOPs Mean Cleanliness</h1>
1031 <li>Moose is based on <code>Class::MOP</code>
1033 <li>Metaobject Protocol for Perl 5</li>
1034 <li>“makes an object for everything”</li>
1039 my $class = $obj->meta; # $obj's metaclass
1040 my $meta = MyApp->meta; # MyApp's metaclass
1041 my $emo = $obj->meta->meta; # even more meta!
1043 warn $obj->meta->name;
1049 <h1>Looking in From the Inside</h1>
1052 my $metaclass = $self->meta;
1054 $metaclass->superclasses;
1056 $metaclass->linearized_isa;
1058 $metaclass->has_method("foo");
1060 $metaclass->compute_all_applicable_attributes;
1066 <p>simple introspection</p>
1071 <h1>Looking in From the Inside (cont.)</h1>
1074 Moose::Meta::Class->create( Bar =>
1076 superclasses => [ 'Foo' ],
1078 Moose::Meta::Attribute->new( bar => ... ),
1079 Moose::Meta::Attribute->new( baz => ... ),
1082 calculate_bar => sub { ... },
1083 construct_baz => sub { ... }
1087 my $anon_meta = Moose::Meta::Class->create_anon_class( ... );
1091 <p>Classes can be created programmatically</p>
1096 <h1>Looking in From the Inside (cont.)</h1>
1099 has foo => ( is => "rw" );
1101 __PACKAGE__->meta->add_attribute(
1108 <li>Moose is just sugar
1110 <li>The MOP does the hard work</li>
1117 <h1>The Metaclass Tango</h1>
1120 <li>Metaclassses control class behavior</li>
1125 metaclass => 'Collection::Array',
1131 <li>custom attribute metaclasses
1133 <li>change how attributes work</li>
1135 <li>Many customizable parts
1137 <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>
1144 <h1>Working in the Meta Frame</h1>
1147 <li><code>$work</code> project:</li>
1148 <li>CMS for a flash website</li>
1149 <li>Content is in XML</li>
1155 <h1>Working in the Meta Frame (cont.)</h1>
1158 <li>Step 1. use Moose</li>
1159 <li>Step 2. ???</li>
1160 <li>Step 3. Profit!</li>
1166 <h1>Working in the Meta Frame (cont.)</h1>
1169 <li>Step 2.1. Client’s XML schemas → Moose classes
1171 <li>Automatic class definitions</li>
1172 <li>High level objects in runtime</li>
1173 <li>XML storage backed
1175 <li>SAX → Moose</li>
1176 <li>Moose → SAX</li>
1184 <h1>Working in the Meta Frame (cont.)</h1>
1187 <li>Step 2.2. Meta descriptions
1189 <li>Extend the metaclasses</li>
1190 <li>Embed additional information
1192 <li>field types</li>
1193 <li>access control</li>
1201 <h1>Working in the Meta Frame (cont.)</h1>
1204 <li>Step 2.3 Introspection goodness
1206 <li>Generic web frontend</li>
1207 <li>Object introspection based
1210 <li>Editing widgets</li>
1212 <li>Clean, extensible</li>
1219 <h1>Drawbacks of Moose</h1>
1224 <li><code>MooseX::Compile</code> is in the works</li>
1226 <li>Some features are slow
1228 <li>but you only pay for what you use</li>
1230 <li>Extending non-Hash based classes is tricky.
1232 <li>but possible: <code>MooseX::GlobRef::Object</code></li>
1239 <h1>Benefits of Moose</h1>
1242 <li>Less boilerplate
1244 <li>attribute storage/access</li>
1245 <li>construction</li>
1246 <li>destruction</li>
1247 <li>verification</li>
1255 <h1>Benefits of Moose (cont.)</h1>
1260 <li>less reading</li>
1261 <li>less writing</li>
1262 <li>less code means fewer bugs</li>
1269 <h1>Benefits of Moose (cont.)</h1>
1274 <li>Moose is very well tested
1276 <li>no need to check accessor behavior, etc</li>
1278 <li>focus on your code’s purpose
1280 <li>not that it is “assembled” correctly</li>
1281 <li>http://c2.com/cgi/wiki?IntentionNotAlgorithm</li>
1289 <h1>Benefits of Moose (cont.)</h1>
1294 <li>declarative style is self documenting</li>
1295 <li>good signal to noise ratio</li>
1302 <h1>Benefits of Moose (cont.)</h1>
1305 <li>Meta object protocol
1307 <li>Cleans up Perl’s OO</li>
1308 <li>Provides introspection</li>
1309 <li>Enables powerful abstractions</li>
1316 <h1>Benefits of Moose (cont.)</h1>
1319 <li>It’s the new black
1321 <li>All the cool kids hang out on #moose</li>
1322 <li>Smart sounding buzzwords</li>
1323 <li>Chicks dig antlers</li>
1324 <li>Ruby is so 2007</li>
1331 <h1>Bonus Material</h1>
1339 package Units::Bytes;
1344 sub kilobytes { $_[0] * 1024 }
1345 sub megabytes { $_[0] * 1024->kilobytes }
1346 sub gigabytes { $_[0] * 1024->megabytes }
1347 sub terabytes { $_[0] * 1024->gigabytes }
1349 Moose::Autobox->mixin_additional_role(
1350 SCALAR => 'Units::Bytes',
1357 <h1>Autobox (cont.)</h1>
1361 use Moose::Autobox; # autoboxing is lexical
1363 is(5->bytes, 5, '... got 5 bytes');
1364 is(5->kilobytes, 5120, '... got 5 kilobytes');
1365 is(2->megabytes, 2097152, '... got 2 megabytes');
1366 is(1->gigabytes, 1073741824, '... got 1 gigabyte');
1367 is(2->terabytes, 2199023255552, '... got 2 terabytes');
1373 <h1>perl -Moose</h1>
1376 <li>Moose One Liners with <code>oose.pm</code></li>
1380 perl -Moose -e 'has foo => ( is=> "rw" ); Class->new( foo => 1 )'
1384 <li>Useful for testing if something works</li>
1385 <li>Helpful on IRC</li>
1386 <li><code>Devel::REPL</code> is cooler though ;-)</li>
1392 <h1>MooseX::POE</h1>
1397 use MooseX::AttributeHelpers;
1400 metaclass => 'Counter',
1401 provides => { inc => "increment_count" },
1405 shift->yield('increment');
1408 event increment => sub {
1411 warn "Count is now " . $self->count;
1413 $self->increment_count;
1414 $self->yield('increment') unless $self->count > 3;
1417 Counter->new( count => 0 );
1422 <li>PoCos made easy</li>
1423 <li>Every object has a <code>POE::Session</code></li>
1424 <li><code>event</code> declares POE object states</li>
1433 <li><p>Slides written by:</p>
1436 <li>Chris Prather</li>
1437 <li>Stevan Little</li>
1438 <li>Robert Boone</li>
1440 <li><p>Slides deleted by:</p>
1443 <li>Yuval Kogman</li>