Move around yuval's slides
[gitmo/moose-website.git] / hosted-presentations / 2008 / nothingmuch-NPW / practical_moose.s5
1 Title:        Moose
2 Location:     YAPC::Asia::2008
3 Presenter:    Yuval Kogman
4 Date:         2008
5 Theme:        moose
6
7 Moose Is Not
8 ============
9
10 * Experimental
11 * A toy
12 * Just another accessor builder
13 * A source filter
14 * Perl black magic
15 * Perl 6 in Perl 5
16
17 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
18
19 Moose Is
20 ========
21
22 * A complete modern object framework for Perl
23
24 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
25
26 Moose Is
27 ========
28
29 * Syntactic Sugar for `Class::MOP`
30 * Rich ancestry
31     * CLOS (Common Lisp Object System)
32     * Smalltalk
33     * Alces latifrons
34     * Perl 6
35     * …
36 * Stable & Production ready
37 * Polite, incremental
38
39 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
40
41 A Simple Example
42 ================
43
44 <pre><code>
45 package Person;
46
47 use strict;
48 use warnings;
49
50 sub new {
51     my ( $class, @args ) = @_;
52
53     @args = %{$args[0]} if @args == 1;
54
55     return bless {
56         @args,
57     }, $class;
58 }
59
60 sub name {
61     my ($self, @args) = @_;
62     $self->{name} = $args[0] if @args;
63     return $self->{name};
64 }
65
66 sub age {
67     my ($self, @args) = @_;
68     $self->{age} = $args[0] if @args;
69     return $self->{age}; 
70 }
71
72 1;
73 </code></pre>
74
75 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
76
77 A Simple Moose Example
78 ======================
79
80 <pre><code>
81 package Person;
82 use Moose;
83
84 has name => (is => 'rw');
85 has age  => (is => 'rw');
86
87 1;
88 </code></pre>
89
90 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
91
92 A Simple Moose Example (cont.)
93 ==============================
94
95 * `use Moose;` 
96     * imports keywords
97     * `use strict; use warnings;`
98     * `@ISA = qw(Moose::Object) unless @ISA`
99
100 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
101
102 A Simple Moose Example (cont.)
103 ==============================
104
105 * `has` declares attributes
106     * generates accessors
107     * `is => 'rw'` → read/write accessor
108     * `is => 'ro'` → read only accessor
109     * `writer`, `reader`
110
111 * `new` inherited from `Moose::Object`
112
113
114 ##########
115
116 Now we're going to discuss more features of the attributes
117
118 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
119
120 Variations on a Moose Example
121 =============================
122
123 <pre><code>
124 package Manager;
125 use Moose;
126
127 has name => (
128     is  => 'rw',
129     isa => 'Str',
130     default => 'Bob'
131 );
132
133 has staff => (
134     is      => 'ro',
135     isa     => 'ArrayRef',
136     lazy    => 1,
137     default => sub { [qw(Bob Alice Tim)] },
138 );
139 </code></pre>
140 ##########
141
142 Adds default, isa
143
144 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
145
146 Variations on a Moose Example (cont.)
147 =====================================
148
149 * `default` is a
150     * code reference
151     * or non-reference (numbers, strings)
152     * used when no parameter is given to `new`
153
154 * `lazy` delays `default`
155     * called on first usage of `$object->staff`
156     * not inside `new`
157
158 ##########
159 discusses default
160
161 non refs make accidental sharing hard
162
163 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
164
165 Variations on a Moose Example (cont.)
166 =====================================
167
168 * `isa` specifies a type
169     * `Moose::Util::TypeConstraints`
170         * `Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object and Role`
171     * Types don't need to exist
172 <pre><code>
173             has 'date' => (isa => 'DateTime'); # DWIM
174 </code></pre>
175 ##########
176
177 isa, type constraints
178
179 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
180
181 Typical Family
182 ==============
183
184 * Types have a hierarchy
185     * `Item` ⊃ `Defined` ⊃ `Ref` ⊃ `Object`
186
187 <pre><code>
188         subtype 'Ref'
189             => as 'Defined'
190             => where {  ref($_) };
191
192         subtype 'Object'
193             => as 'Ref'
194             => where { blessed($_) }
195 </code></pre>
196 ##########
197
198 type hierarchy
199
200 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
201
202 Conventional Delegates
203 ======================
204
205 <pre><code>
206 package Employee;
207 use Moose;
208 extends qw(Person);
209     
210 has manager =>  (
211     is  => 'ro',
212     isa => 'Manager',
213     handles => {
214         manager_name => 'name',
215         coworkers    => 'staff',
216     }
217 );
218 </code></pre>
219
220 * manager `handles` certain methods for `Employee`
221     * `$emp->coworkers` == `$emp->manager->staff `
222
223 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
224
225 Conventional Delegates (cont.)
226 ==============================
227
228 <pre><code>
229 has phone => (
230     ...
231     handles => [qw(number extension)],
232 );
233 </code></pre>
234
235 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
236
237 Conventional Delegates (cont.)
238 ==============================
239
240 <pre><code>
241 has phone => (
242     ...
243     isa     => "Phone",
244     handles => qr/^[a-z]\w+$/,
245 );
246 </code></pre>
247
248 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
249
250 Conventional Delegates (cont.)
251 ==============================
252
253 <pre><code>
254 has phone => (
255     ...
256     handles => "Dialing", # a role
257 );
258 </code></pre>
259
260 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
261
262 UnConventional Delegates
263 ========================
264
265 <pre><code>
266 package Company;
267 use Moose;
268 use MooseX::AttributeHelpers;
269    
270 has employees => (
271     metaclass => 'Collection::Array',
272     isa => 'ArrayRef[Employees]',
273     is  => 'rw',
274     provides => {
275         push  => 'add_employee',
276         pop   => 'remove_employee',
277         count => 'number_of_employees',
278         empty => 'any_employees',
279     },
280 );
281 </code></pre>
282 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
283
284 Modified Methods
285 ================
286
287 <pre><code>
288 before 'employees' => sub { warn 'calling employees' };
289
290 after 'employees' => sub { warn 'finished calling employees' };
291 </code></pre>
292
293 *  Pre/Post hooks
294     * Get a copy of `@_`
295     * Return value is ignored
296
297 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
298
299 Modified Methods (cont.)
300 ========================
301
302 <pre><code>
303 around 'employees' => sub { 
304     my ($next, $self, @args) = @_;
305     ...
306     my @return = $self->$next(@args);
307     ...
308     return @return;
309 };
310 </code></pre>
311
312 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
313
314 Modified Methods (cont.)
315 ========================
316
317 <pre><code>
318 package Employee;
319 use Moose;
320
321 sub do_work {
322     my $self = shift;
323     
324     $self->punch_in;
325     
326     inner(); # call subclass here
327     
328     $self->punch_out;
329 }
330 </code></pre>
331
332 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
333
334 Modified Methods (cont.)
335 ========================
336
337 <pre><code>
338 package Employee::Chef;
339 use Moose;
340
341 extends qw(Employee);
342
343 augment do_work => sub {
344     my $self = shift;
345     
346     while ( @burgers ) {
347         $self->flip_burger(shift @burgers);
348     }
349 };
350
351 $chef->do_work; # punch in, flip burgers, punch out
352 </code></pre>
353 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
354
355 Some Type of Coercion
356 =====================
357
358 <pre><code>
359 package Employee;
360 use Moose;
361 use Moose::Util::TypeConstraints;
362 extends qw(Person);
363
364 class_type 'Manager';
365
366 coerce 'Manager' => (
367     from 'Str' => via { Manager->new( name => $_ ) },
368 );
369
370 has manager => (
371     is => 'ro',
372     isa => 'Manager',
373     required => 1, 
374     coerce => 1,
375 );
376 </code></pre>
377
378 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
379
380 Some Type of Coercion (cont.)
381 =============================
382
383 <pre><code>
384 # import type constraint keywords
385 use Moose::Util::TypeConstraints;
386
387
388 # define Manager, a subtype of Object
389 class_type "Manager";
390
391
392 # define the conversion
393 ... via { Manager->new( name => $_ ) }
394
395
396 # enable it per attribute
397 has manager => (
398     ...
399     coerce => 1,
400 );
401 </code></pre>
402
403 ##########
404
405 breakdown of the example
406
407 class types are automatically created for all Moose classes
408
409 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
410
411 Some Type of Digression
412 =======================
413
414 <pre><code>
415 has employees => (
416     is => 'rw',
417     isa => 'ArrayRef[Employee]',
418 );
419
420 has shopping_carts => (
421     is => 'rw',
422     isa => 'ArrayRef[ArrayRef[ShinyBead]]'
423 );
424 </code></pre>
425
426 ##########
427
428 Going to go into features of the type system for a bit
429
430 Parametrized types
431
432 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
433 Some Type of Digression (cont.)
434 ===============================
435
436 <pre><code>
437 has language => (
438     is => 'rw',
439     isa => 'English | Welsh | Scots | Gaelic',
440 );  
441
442 has member => (
443     is => 'rw',
444     isa => 'Employee | ArrayRef[ Employee | Group ]',
445 );
446 </code></pre>
447
448 ##########
449
450 Union types
451
452 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
453
454 Some Type of Digression (cont.)
455 ===============================
456
457 <pre><code>
458 package Foo;
459 use Moose;
460 use Moose::Util::TypeConstraints;
461
462 use Test::Deep qw(eq_deeply ...);
463
464 type 'SomethingTricky' => where {
465     eq_deeply( $_, ... );
466 };
467
468 has 'bar' => (
469     is  => 'rw',
470     isa => 'SomethingTricky',
471 );
472 </code></pre>
473
474 ##########
475
476 Test::Deep custom validator
477
478 Can use any validation from the CPAN
479
480 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
481
482 Some Parametrized Type of Coercion
483 ==================================
484
485 <pre><code>
486 use Moose::Util::TypeConstraints;
487
488 subtype 'ArrayRef[Employee]' => as 'ArrayRef';
489
490 coerce 'ArrayRef[Employee]' => (
491     from 'ArrayRef[Str]' via {
492         [ map { Employee->new( name => $_ ) } @$_ ]
493     },
494 );
495
496 has staff => (
497     isa    => 'ArrayRef[Employee]',
498     coerce => 1,
499 );
500 </code></pre>
501
502 ##########
503
504 coerce parametrized ArrayRef[Employee] from ArrayRef[Str]
505
506 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
507
508 Role of the Moose 
509 =================
510
511 * A role is like a…
512     * Java Interface: safe
513     * mixin: useful
514 * A role is for small reusable behaviors
515     * better than using a multiple inheritence
516
517 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
518
519 Role of the Moose (cont.)
520 =========================
521
522 * Roles on the CPAN:
523     * `MooseX::Clone` - Flexible `clone` method
524     * `MooseX::Storage` - Flexible serialization
525     * `MooseX::Getopt` - `@ARGV` aware constructor
526     * `MooseX::LogDispatch` - `$self->logger->info("something happenned")`
527     * `MooseX::Param` - `param` method like `CGI.pm`'s,
528
529 ##########
530
531 Some examples of small reusable behaviors
532
533 Param is good for interacting with e.g. CGI::Expand or similar modules
534
535 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
536
537 Role of the Moose (cont.)
538 =========================
539
540 <pre><code>
541 package Minion;
542 use Moose;
543
544 extends qw(Employee);
545
546 with qw(Salaried::Hourly);
547
548
549 package Boss;
550 use Moose;
551
552 extends qw(Employee);
553
554 with qw(Salaried::Monthly);
555
556 </code></pre>
557
558 * `with` adds roles into your class
559     * `Salaried::Hourly` was added to `Minion`
560
561 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
562
563 Role of the Moose (cont.)
564 =========================
565
566 <pre><code>
567 package Salaried;
568 use Moose::Role;
569
570 requires 'paycheck_amount';
571 </code></pre>
572
573 * Just an interface
574
575 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
576
577 Role of the Moose (cont.)
578 =========================
579
580 <pre><code>
581 package Salaried::Hourly;
582 use Moose::Role;
583
584 with qw(Salaried);
585
586 has hourly_rate => (
587     isa => "Num",
588     is  => "rw",
589     required => 1,
590 );
591
592 has logged_hours => (
593     isa => "Num",
594     is  => "rw",
595     default => 0,
596 );
597
598 # satisfy the Salaried interface:
599 sub paycheck_amount {
600     my $self = shift;
601     $self->logged_hours * $self->hourly_rate;
602 }
603
604 </code></pre>
605
606 * More than an interface
607
608 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
609
610 Role of the Moose (cont.)
611 =========================
612
613 * More than Java Interfaces
614     * Interfaces are behavior "contracts"
615     * Roles can also have code
616
617 ##########
618 roles can have attributes and methods
619 roles provide behavior, not just interface
620
621 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
622
623 Role of the Moose (cont.)
624 =========================
625
626 * Role Composition
627     * Not inheritence
628     * Symmetric
629     * Unordered
630
631 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
632
633 Role of the Moose (cont.)
634 =========================
635
636 * Role Composition
637     * Less ambiguity
638     * Compile time errors
639     * …And ways to fix them
640
641 ##########
642 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
643 multiple inheritence silently assumes you want the first class
644
645 roles cause errors at compile time, unlike multiple inheritence
646
647 roles also provide easy ways to fix the errors
648
649 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
650
651 Role of the Moose (cont.)
652 =========================
653
654 <pre><code>
655 package Ballet;
656 use Moose::Role;
657
658 sub dance {
659     pirouette();
660 }
661
662 package Punk;
663 use Moose::Role
664
665 sub dance {
666     MOSH!!!11one();
667 }
668
669 package Foo;
670 use Moose;
671
672 # KABOOM:
673 with qw(
674     Punk
675     Ballet
676 );
677 </code></pre>
678
679 ##########
680
681 conflicts
682
683 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
684
685 Role of the Moose (cont.)
686 =========================
687
688 <pre><code>
689 package Ent::Puppy;
690 use Moose;
691
692 with (
693     Tree => {
694         alias => {
695             bark => "tree_bark",
696         },
697     },
698     Dog => {
699         alias => {
700             bark => "bark_sound",
701         }
702     },
703 );
704
705 sub bark {
706     my $self = shift;
707     
708     if ( $condition ) {
709         $self->tree_bark;
710     } else {
711         $self->bark_sound;
712     }
713 }
714 </code></pre>
715
716 * Not that common in practice
717  
718 ##########
719
720 Composition parameters
721 Easier conflict resolution
722 Finer grained control
723
724 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
725
726 MOPs Mean Cleanliness
727 =====================
728
729 * Moose is based on `Class::MOP`
730     * Metaobject Protocol for Perl 5
731     * "makes an object for everything"
732     
733 <pre><code>
734 my $class = $obj->meta;       # $obj's metaclass
735 my $meta  = MyApp->meta;      # MyApp's metaclass
736 my $emo   = $obj->meta->meta; # even more meta!
737
738 warn  $obj->meta->name;
739 </code></pre>
740
741 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
742
743 Looking in From the Inside
744 ===========================
745
746 <pre><code>
747 my $metaclass = $self->meta; 
748
749 $metaclass->superclasses;
750
751 $metaclass->linearized_isa;
752
753 $metaclass->has_method("foo");
754
755 $metaclass->compute_all_applicable_attributes;
756
757 # … lots more
758 </code></pre>
759 ##########
760
761 simple introspection
762
763 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
764
765 Looking in From the Inside (cont.)
766 ==================================
767
768 <pre><code>
769 Moose::Meta::Class->create( Bar =>
770       version      => '0.01',
771       superclasses => [ 'Foo' ],
772       attributes => [
773           Moose::Meta::Attribute->new( bar => ... ),
774           Moose::Meta::Attribute->new( baz => ... ),
775       ],
776       methods => {
777           calculate_bar => sub { ... },
778           construct_baz => sub { ... }
779       },
780 );
781
782 my $anon_meta = Moose::Meta::Class->create_anon_class( ... );
783 </code></pre>
784
785 ##########
786
787 Classes can be created programmatically
788 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
789
790 Looking in From the Inside (cont.)
791 ==================================
792
793 <pre><code>
794 has foo => ( is => "rw" );
795
796 __PACKAGE__->meta->add_attribute(
797     "foo",  
798     is => "rw",
799 );
800 </code></pre>
801
802 * Moose is just sugar
803     * The MOP does the hard work
804
805 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
806
807 The Metaclass Tango
808 ===================
809
810 * Metaclassses control class behavior
811
812 <pre><code>
813 has employees => (
814     metaclass => 'Collection::Array',
815     ...
816 );
817 </code></pre>
818
819 * custom attribute metaclasses
820     * change how attributes work
821 * Many customizable parts
822     * `Moose::Meta::Class`, `Moose::Meta::Attribute, ``Moose::Meta::Method`, `Moose::Meta::Method::Accessor` `Moose::Meta::Instance`, `Moose::Meta::Role`, `Moose::Meta::TypeConstraint`, …,
823
824 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
825
826 Working in the Meta Frame
827 =========================
828
829 * `$work` project:
830 * CMS for a flash website
831 * Content is in XML
832
833 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
834
835 Working in the Meta Frame (cont.)
836 =================================
837
838 * Step 1. use Moose
839 * Step 2. ???
840 * Step 3. Profit!
841
842 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
843
844 Working in the Meta Frame (cont.)
845 =================================
846
847 * Step 2.1. Client's XML schemas → Moose classes
848     * Automatic class definitions
849     * High level objects in runtime
850     * XML storage backed
851         * SAX → Moose
852         * Moose → SAX
853
854 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
855
856 Working in the Meta Frame (cont.)
857 =================================
858
859 * Step 2.2. Meta descriptions
860     * Extend the metaclasses
861     * Embed additional information
862         * field types
863         * access control
864
865 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
866
867 Working in the Meta Frame (cont.)
868 =================================
869
870 * Step 2.3 Introspection goodness
871     * Generic web frontend
872     * Object introspection based
873         * HTML view
874         * Editing widgets
875     * Clean, extensible
876
877 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
878
879 Drawbacks of Moose
880 ==================
881
882 * Load time
883     * `MooseX::Compile` is in the works
884 * Some features are slow
885     * but you only pay for what you use
886 * Extending non-Hash based classes is tricky.
887     * but possible: `MooseX::GlobRef::Object`
888
889 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
890
891 Benefits of Moose
892 =================
893
894 * Less boilerplate
895     * attribute storage/access
896     * construction
897     * destruction
898     * verification
899     * …
900
901 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
902
903 Benefits of Moose (cont.)
904 =========================
905
906 * Shorter
907     * less reading
908     * less writing
909     * less code means fewer bugs
910
911 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
912
913 Benefits of Moose (cont.)
914 =========================
915
916 * Less testing
917     * Moose is very well tested
918         * no need to check accessor behavior, etc
919     * focus on your code's purpose
920         * not that it is "assembled" correctly
921         * http://c2.com/cgi/wiki?IntentionNotAlgorithm
922
923 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
924
925 Benefits of Moose (cont.)
926 =========================
927
928 * More readable
929     * declarative style is self documenting
930     * good signal to noise ratio
931
932 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
933
934 Benefits of Moose (cont.)
935 =========================
936
937 * Meta object protocol
938     * Cleans up Perl's OO
939     * Provides introspection
940     * Enables powerful abstractions
941
942 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
943
944 Benefits of Moose (cont.)
945 =========================
946
947 * It's the new black
948     * All the cool kids hang out on #moose
949     * Smart sounding buzzwords
950     * Chicks dig antlers
951     * Ruby is so 2007
952
953 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
954
955 Bonus Material
956 ==============
957
958 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
959
960 Autobox
961 =======
962
963 <pre><code>
964 package Units::Bytes;
965 use Moose::Role;
966 use Moose::Autobox;
967
968 sub bytes     { $_[0]                   }
969 sub kilobytes { $_[0] * 1024            }
970 sub megabytes { $_[0] * 1024->kilobytes }
971 sub gigabytes { $_[0] * 1024->megabytes }
972 sub terabytes { $_[0] * 1024->gigabytes }
973
974 Moose::Autobox->mixin_additional_role(
975     SCALAR => 'Units::Bytes',
976 );
977 </code></pre>
978
979 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
980
981 Autobox (cont.)
982 ===============
983
984 <pre><code>
985 use Units::Bytes;
986 use Moose::Autobox; # autoboxing is lexical
987
988 is(5->bytes,     5,             '... got 5 bytes');
989 is(5->kilobytes, 5120,          '... got 5 kilobytes');
990 is(2->megabytes, 2097152,       '... got 2 megabytes');
991 is(1->gigabytes, 1073741824,    '... got 1 gigabyte');
992 is(2->terabytes, 2199023255552, '... got 2 terabytes');
993 </code></pre>
994
995 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
996
997 perl -Moose
998 ===========
999
1000 * Moose One Liners with `oose.pm`
1001
1002 <pre><code>
1003 perl -Moose -e 'has foo => ( is=> "rw" ); Class->new( foo => 1 )'
1004 </code></pre>
1005
1006 * Useful for testing if something works
1007 * Helpful on IRC
1008 * `Devel::REPL` is cooler though ;-)
1009
1010 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1011
1012 MooseX::POE
1013 ===========
1014
1015 <pre><code>
1016 package Counter;
1017 use MooseX::POE;
1018 use MooseX::AttributeHelpers;
1019
1020 has count => (
1021     traits => [qw(Counter)],
1022     provides => { inc => "increment_count" },
1023 );
1024
1025 sub START {
1026     shift->yield('increment');
1027 }
1028
1029 event increment => sub {
1030     my $self = shift;
1031
1032     warn "Count is now " . $self->count;
1033
1034     $self->increment_count;
1035     $self->yield('increment') unless $self->count > 3;
1036 };
1037
1038 Counter->new( count => 0 );
1039 POE::Kernel->run();
1040 </code></pre>
1041
1042 * PoCos made easy
1043 * Every object has a `POE::Session`
1044 * `event` declares POE object states
1045
1046 ✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
1047
1048 Fin
1049 ===
1050
1051 * Slides written by:
1052     * Chris Prather
1053     * Stevan Little
1054     * Robert Boone
1055
1056 * Slides deleted by:
1057     * Yuval Kogman