Slide 1

Slide 1 text

Ynon Perek [email protected] http://ynonperek.com Moose Workshop Friday, July 6, 12

Slide 2

Slide 2 text

Agenda • Moose Overview • Classes • Roles • Attributes • Meta Object System • Type System • Moose Extensions • Design Patterns Friday, July 6, 12

Slide 3

Slide 3 text

Assumptions • You know how to write a Moose classes • You know how to define methods and what $self means Friday, July 6, 12

Slide 4

Slide 4 text

Moose Overview • Developed by Stevan Little (on the right) • Started 2006 • Goal: Change the world Friday, July 6, 12

Slide 5

Slide 5 text

Moose Features • From perl to OO • No boilerplate code • Optional type constraints • Inheritance and Mixins • Design Patterns Friday, July 6, 12

Slide 6

Slide 6 text

Organizations Using Moose • Cisco • IMDb • Infinity Interactive • MusicBrainz • Symantec • And others: http://moose.iinteractive.com/ about.html#organizations Friday, July 6, 12

Slide 7

Slide 7 text

Moose Alternatives • Mouse • Moo • Mo • Class::Builder Friday, July 6, 12

Slide 8

Slide 8 text

Moose HELP • IRC: irc://irc.perl.org/#moose • Mailing List: mailto:moose- [email protected] • Youtube: search for “perl moose” Friday, July 6, 12

Slide 9

Slide 9 text

Moose Classes Friday, July 6, 12

Slide 10

Slide 10 text

Moose Classes • Import sugar functions: extends, has, with, ... • Enable strict & warnings • Subclass of Moose::Object for default ctor and dtor • Create Moose::Meta::Class object package Foo; use Moose; Friday, July 6, 12

Slide 11

Slide 11 text

Moose::Object • new ( %params ) • BUILDARGS ( %params ) • DESTROY • does( $role_name ) • DOES( $class_or_role_name ) • dump( $maxdepth ) Friday, July 6, 12

Slide 12

Slide 12 text

Example: Getting Info package Pet; use Moose; has 'name', is => 'ro', isa => 'Str', default => 'Lassy'; has 'past_owners', is => 'ro', isa => 'ArrayRef[Str]'; package main; my $dog = Pet->new( past_owners => ['James', 'Mike'] ); # show dog's info. No need to import Data::Dumper warn $dog->dump; # DOES returns true for objects of the class, subclasses or # implementors of the role print "Good boy" if $dog->DOES('Pet'); Friday, July 6, 12

Slide 13

Slide 13 text

Class Construction • new method is automatically generated. • Takes parameters hash or hash ref package main; # Pass a hash ref to prevent copying my $enterprise = Starship->new( { captain => 'James T Kirk', crew => ['Dr. McCoy', 'Scott', 'Lt. Uhura'], }); Friday, July 6, 12

Slide 14

Slide 14 text

Class Construction • Construction hooks: • BUILD • BUILDARGS • attribute builders Friday, July 6, 12

Slide 15

Slide 15 text

Class Construction • BUILD is called every time a new object is created • If inheritance is in effect, parent’s BUILD is called before child BUILD is called automatically • Used for: • Object state validation (whole object) • Tracking objects creation Friday, July 6, 12

Slide 16

Slide 16 text

Object State Validation package Starship; use Moose; has 'captain', is => 'ro', isa => 'Str', required => 1; has 'crew', is => 'rw', isa => 'ArrayRef[Str]', required => 1; sub BUILD { my $self = shift; if ( $self->captain ~~ $self->crew ) { my $captain = $self->captain; die "Validation Error: Cannot use $captain for both Captain and Crew"; } } package main; # Validation error my $enterprise = Starship->new( { captain => 'James T Kirk', crew => ['Dr. McCoy', 'Scott', 'Lt. Uhura', 'James T Kirk'], }); Friday, July 6, 12

Slide 17

Slide 17 text

BUILDARGS • Used to manipulate arguments before object creation • Takes the arguments hash as input, returns hashref • Wrap in ‘around’ modifier to change • Used for: • Single arguments ctor Friday, July 6, 12

Slide 18

Slide 18 text

BUILDARGS Example package Person; use Moose; has 'name', is => 'ro', isa => 'Str', required => 1; around BUILDARGS => sub { my $orig = shift; my $class = shift; my @params = @_; # Sole parameter that is not a ref # is considered the name if ( ( @params == 1 ) && ( ! ref $params[0] ) ) { return $class->$orig( name => $params[0] ); } else { return $class->$orig ( @params ); } }; # Watch the semicolon Friday, July 6, 12

Slide 19

Slide 19 text

Class Destruction • Moose implemented DESTROY, which will call your DEMOLISH • It handles inheritance correctly: demolish child before super Friday, July 6, 12

Slide 20

Slide 20 text

Class Destruction • When program ends, prints out: Bar::Demolish Foo::Demolish package Foo; use Moose; sub DEMOLISH { warn 'Foo::Demolish' } package Bar; use Moose; extends 'Foo'; sub DEMOLISH { warn 'Bar::Demolish' } package main; my $b = Bar->new; Friday, July 6, 12

Slide 21

Slide 21 text

Construction Destruction Do’s and Don’ts Friday, July 6, 12

Slide 22

Slide 22 text

Do • Provide reasonable validations with BUILD Friday, July 6, 12

Slide 23

Slide 23 text

Do • Use warn( $obj->dump ) for debug Friday, July 6, 12

Slide 24

Slide 24 text

Do • Consider namespace::autoclean to remove Moose sugar methods from your classes (has, with, etc.) Friday, July 6, 12

Slide 25

Slide 25 text

Do • Consider using: __PACKAGE__->meta->make_immutable; • To improve performance of objects creation • Consider MooseX::AutoImmute Friday, July 6, 12

Slide 26

Slide 26 text

Don’t • Never override new ( it’ll break stuff down the road ) Friday, July 6, 12

Slide 27

Slide 27 text

Don’t • Don’t use BUILD when attribute builders are sufficient Friday, July 6, 12

Slide 28

Slide 28 text

Don’t • Never call $self->SUPER::BUILD • Moose does that for you Friday, July 6, 12

Slide 29

Slide 29 text

Don’t • Don’t apply a method modifier (before, after, around) to BUILD Friday, July 6, 12

Slide 30

Slide 30 text

Don’t • Don’t write BUILD method for your roles ( Moose ignores them ) Friday, July 6, 12

Slide 31

Slide 31 text

after • Add code after a method is executed • Receives: method name and subroutine to add package Secret; use Mouse; has 'message', is => 'ro', required => 1, clearer => 'reset'; has 'counter', is => 'rw', default => 3; after 'message' => sub { my $self = shift; $self->counter( $self->counter - 1 ); if ( $self->counter <= 0 ) { $self->reset; } }; package main; my $secret = Secret->new( message => 'This message will self destroy'); print $secret->message, "\n" for (1..5); Friday, July 6, 12

Slide 32

Slide 32 text

What Is Printed ? package Foo; use Moose; sub DEMOLISH { warn 'Foo::Demolish' } sub BUILD { warn 'Foo::Build' } package Bar; use Moose; extends 'Foo'; sub DEMOLISH { warn 'Bar::Demolish' } sub BUILD { warn 'Bar::Build' } package main; my $b = Bar->new; Friday, July 6, 12

Slide 33

Slide 33 text

Method Modifiers • Alter code by injecting other code before or after the modified method • Can use from roles, subclasses or class itself Friday, July 6, 12

Slide 34

Slide 34 text

before • Before lets us inject code before a method is called • Spot the bug on the right package Logger; use Mouse; sub log { my $self = shift; my ($msg) = @_; print $msg; } before 'log' => sub { select *STDERR }; after 'log' => sub { select *STDOUT }; package main; my $log = Logger->new; $log->log("hello\n"); Friday, July 6, 12

Slide 35

Slide 35 text

around • around has two more advantages: • Can use return value of original method • Can skip calling original method altogether • You have the power Friday, July 6, 12

Slide 36

Slide 36 text

around • First parameter: original method as CODE ref • Second parameter is the object • Can call $self->$orig to get requested functionality package AroundExample; use Mouse; use feature ':5.10'; sub foo { print "In Foo\n" } around 'foo' => sub { my $orig = shift; my $self = shift; say "Around: before calling method"; $self->$orig(@_); say "Around: after calling method"; }; Friday, July 6, 12

Slide 37

Slide 37 text

around • Forbid login before noon package User; use Mouse; use DateTime; sub login { warn 'Welcome' } around 'login' => sub { my $now = DateTime->now; if ( $now->hour < 12 ) { my $orig = shift; my $self = shift; $self->$orig(@_); } }; Friday, July 6, 12

Slide 38

Slide 38 text

Friday, July 6, 12

Slide 39

Slide 39 text

Moose Roles An alternative to deep hierarchies and base classes Friday, July 6, 12

Slide 40

Slide 40 text

Role • Encapsulates behavior. Something that classes do • Cannot be instansiated • Classes consume roles - which means everything in the role is copied into the class Friday, July 6, 12

Slide 41

Slide 41 text

Classes & Roles Alive Think Think Alive Person Computer Chicken Friday, July 6, 12

Slide 42

Slide 42 text

Roles Example package Glass; use Moose; with 'Breakable'; package main; my $g = Glass->new; $g->break; $g->fix; package Breakable; use Moose::Role; has 'is_broken', is => 'rw', isa => 'Bool'; sub break { my $self = shift; print "Ouch\n" if ! $self->is_broken; $self->is_broken(1); } sub fix { my $self = shift; print "Works now\n" if $self->is_broken; $self->is_broken(0); } Friday, July 6, 12

Slide 43

Slide 43 text

Moose Roles • Use Moose::Role to define a role • Use ‘with’ to consume a role • Inside a role, define methods, attributes and modifiers • Use ‘does’ to find out if an object implements a role Friday, July 6, 12

Slide 44

Slide 44 text

Partial Implementation • Use ‘requires’ in a role to force your consumer to define a method • Useful for: • Partial implementations (template method) • Abstract Base Class Friday, July 6, 12

Slide 45

Slide 45 text

Partial Implementation package MultipleFileUploader; use Moose::Role; requires 'upload_file'; sub upload_files { my $self = shift; my @success; foreach my $f ( @_ ) { die "Invalid file: $f" if ! $f->DOES('File'); $self->upload_file ( $f ) && push @success, $f; } return @success; } Friday, July 6, 12

Slide 46

Slide 46 text

Method Conflicts • Consuming two roles with the same method names results in a conflict • Class must then implement the conflicted method on its own • Can call role implementation using their namespace Friday, July 6, 12

Slide 47

Slide 47 text

Method Conflicts package R1; use Moose::Role; sub foo { warn 'R1::foo' } package R2; use Moose::Role; sub foo { warn 'R2::foo' } package Test; use Moose; with qw/R1 R2/; Compilation Error Friday, July 6, 12

Slide 48

Slide 48 text

Method Conflict • Can use -alias to make a copy of a role’s method by another name • Can use -excludes to avoid consuming a specific method • Combine both to work around a conflict Friday, July 6, 12

Slide 49

Slide 49 text

Method Conflict with 'Breakable' => { -alias => { break => 'break_bone' }, -excludes => 'break', }, 'Breakdancer' => { -alias => { break => 'break_dance' }, -excludes => 'break', }; Friday, July 6, 12

Slide 50

Slide 50 text

Dynamic Roles • Roles can be added to instances after creation • Usage: debug tracing on specific obejct, dynamically change objects by configuration • Code: use Moose::Util qw( apply_all_roles ); my $car = Car->new; apply_all_roles( $car, 'Breakable' ); Friday, July 6, 12

Slide 51

Slide 51 text

Lab • Implement a Comparable role which requires a single method: compare($other) - returns -1 if $other is greater than $self; 0 if they are equal and +1 if $self is greater. • Use compare to implement the following: greater_than, greater_or_equal, less_than, less_or_equal • Implement a class that consumes the role Friday, July 6, 12

Slide 52

Slide 52 text

Friday, July 6, 12

Slide 53

Slide 53 text

Attributes Friday, July 6, 12

Slide 54

Slide 54 text

Moose Attributes • An attribute is a property that every member of a class has • Some attributes are optional (e.g. some people have a middle name) Friday, July 6, 12

Slide 55

Slide 55 text

Attribute Options • is, reader, writer • isa • required, default, builder • lazy Friday, July 6, 12

Slide 56

Slide 56 text

Readers & Writers • Use ‘is’ to auto generate reader/writer • Use ‘writer’ to specify writer’s name • Use ‘reader’ to specify reader’s name package Product; use Moose; has 'name' => ( is => 'rw', reader => 'get_name', writer => '_set_name', ); has 'price' => ( is => 'rw', reader => 'get_price', writer => 'set_price', ); Friday, July 6, 12

Slide 57

Slide 57 text

Isa • Use isa to force a type constraint • Available Types include: Bool, Str, Num, Int, ScalarRef, ArrayRef, HashRef, CodeRef • Can use another object as type constraint • Many more type constraints with option to extend the list yourself Friday, July 6, 12

Slide 58

Slide 58 text

Isa package Store; use Moose; use Client; use Product; has 'owner', is => 'ro', isa => 'Str'; has 'clients', is => 'rw', isa => 'ArrayRef[Client]'; has 'products', is => 'rw', isa => 'ArrayRef[Product]'; has 'revenue', is => 'rw', isa => 'Num'; 1; Friday, July 6, 12

Slide 59

Slide 59 text

Subtypes • Use subtypes to easily define new constraints: use Moose::Util::TypeConstraints; subtype 'Age', as 'Int', where { $_ >= 0 && $_ <= 120 }, message { "Invalid Age: $_ "}; Friday, July 6, 12

Slide 60

Slide 60 text

Enumerations • Use enum function to declare an enum subtype • An enum takes a single value from a predefined list enum 'EyeColor', [qw/green blue brown gray/]; Friday, July 6, 12

Slide 61

Slide 61 text

Required / Default / Builder • Use required for fields that take their value from “outside” • Use default / builder for everything else Friday, July 6, 12

Slide 62

Slide 62 text

Builder • Use builder for more complex initialization logic • builder works better than default for inheritance package Person; use Moose; has 'pet', is => 'ro', builder => '_build_pet'; has 'age', is => 'rw', required => 1; sub _build_pet { my $self = shift; if ( $self->age < 13 ) { return "None"; } else { return "Dog"; } } package main; my $p = Person->new(age => 10); print $p->pet; Friday, July 6, 12

Slide 63

Slide 63 text

lazy • Create your attributes only when they are needed • Use lazy_build to type less package Person; use Moose; has 'pet', is => 'ro', lazy_build => 1; has 'age', is => 'rw', required => 1; sub _build_pet { my $self = shift; if ( $self->age < 13 ) { return "None"; } else { return "Dog"; } } package main; my $p = Person->new(age => 10); print $p->pet; Friday, July 6, 12

Slide 64

Slide 64 text

Dependency Injection • A technique used in testing to build more testable versions of your classes • If an attribute has both a builder AND was passed externally, external value wins Friday, July 6, 12

Slide 65

Slide 65 text

Lab • Implement a Logger class with one method: log. In the ctor, logger can take a file name • If no arguments passed, create a screen logger (write all output to screen) • If a file name was provided, write to that file • Use dependency injection to test your Logger Solution: https://gist.github.com/3029901 Friday, July 6, 12

Slide 66

Slide 66 text

Delegation • A relationship between classes. A class attribute is an object of a different class • Can then redirect all calls on containing object to the attribute - thus delegating specific methods Friday, July 6, 12

Slide 67

Slide 67 text

Delegation Contact Email Send Mail Send Mail Phone Call Call Friday, July 6, 12

Slide 68

Slide 68 text

Delegation • Moose handles delegation for you • Attribute should declare “handles” option package Contact; use Moose; has 'email' => ( is => 'ro', handles => [ qw/send_mail/ ] ); Friday, July 6, 12

Slide 69

Slide 69 text

Delegate • Another option is to delegate an entire role • Moose will delegate all methods in the role automatically has 'uri' => ( is => 'ro', isa => 'URI', handles => 'HasURI', ); Friday, July 6, 12

Slide 70

Slide 70 text

Native Delegation • Give your object “native” feel by using standard data type methods • Currently supported: Array, Hash, Number, String, Bool, Counter • Useful for: Fields that should “work like” the native data type Friday, July 6, 12

Slide 71

Slide 71 text

Native Delegation • Native arrays have push, pop, shift, unshift and more • Can now use: $q->add_item to add an item to the queue has 'q' => ( is => 'ro', isa => 'ArrayRef[Int]', default => sub { [] }, traits => [qw/Array/], handles => { add_item => 'push', next_item => 'shift', }, ); package main; my $q = Queue->new; $q->add_item(10, 20); Friday, July 6, 12

Slide 72

Slide 72 text

Native Delegation • Array functions: Moose::Meta::Attribute::Native::Trait::Array • Hash functions: Moose::Meta::Attribute::Native::Trait::Hash Friday, July 6, 12

Slide 73

Slide 73 text

Friday, July 6, 12

Slide 74

Slide 74 text

Attributes: Advanced Topics • Predicates & Clearers • Constructor Parameters • Weak References • Triggers Friday, July 6, 12

Slide 75

Slide 75 text

Predicates & Clearers • User can upload photos, other users can “like” • Every photo starts with 0 likes • How many “likes” do you have before the image is online ? Uploading Image No likes yet Image Online 0 Likes. Go find more friends Friday, July 6, 12

Slide 76

Slide 76 text

Predicates & Clearers • Provide two new methods on $self: unpublish and is_published • Setting value to undef does not affect predicate package Photo; use Moose; has 'likes' => ( is => 'rw', clearer => 'unpublish', predicate => 'is_published', ); sub publish { my $self = shift; $self->likes ( 0 ); } Friday, July 6, 12

Slide 77

Slide 77 text

Predicates & Clearers sub like { my $self = shift; die 'Cannot like an Unpublished photo' if ! $self->is_published; $self->likes ( $self->likes + 1 ); } Friday, July 6, 12

Slide 78

Slide 78 text

Constructor Parameters • Sometimes the name of the attribute is not the same as the name of the constructor param • A possible workaround is BUILDARGS, but that’s too tedious • A better way: Use init_arg • Usage: modify constructor param name, prevent dependency injection Friday, July 6, 12

Slide 79

Slide 79 text

Example: init_arg • Use to modify constructor parameter name • Attribute name is size, while object creation is performed with: Cls->new( bigness => 7 ) has 'bigness' => ( is => 'ro', init_arg => 'size', ); Friday, July 6, 12

Slide 80

Slide 80 text

Example: init_arg • Use init_arg => undef to prevent dependency injection • Use with caution has '_genetic_code' => ( is => 'ro', lazy_build => 1, init_arg => undef, ); Friday, July 6, 12

Slide 81

Slide 81 text

Weak References Course Student Student Student Learns At Friday, July 6, 12

Slide 82

Slide 82 text

Weak References • When an object leaves scope, it’s ref-count decreases • Circular references cause objects to remain in memory • Weak references to the rescue Friday, July 6, 12

Slide 83

Slide 83 text

Weak Ref • When a Course object leaves the last scope - it will now be deleted • When Course object leaves scope, Moose will automatically clear all “learns_at” attributes of students package Student; use Moose; has 'name', is => 'ro', required => 1; has 'learns_at', is => 'rw', weak_ref => 1; Full Example: https://gist.github.com/3031636 Friday, July 6, 12

Slide 84

Slide 84 text

Triggers • Called when attribute value is set • Called when set from new or explicitly • Is not called when set from default or builder has 'size' => ( is => 'rw', trigger => \&_size_set, ); sub _size_set { my ( $self, $size, $old_size ) = @_; } Friday, July 6, 12

Slide 85

Slide 85 text

Friday, July 6, 12

Slide 86

Slide 86 text

Lab • Improve Students/Course example to use native delegation • Use method modifiers to add custom logic Friday, July 6, 12

Slide 87

Slide 87 text

Meta Moose Friday, July 6, 12

Slide 88

Slide 88 text

What is MOP • An abstraction to build abstractions - or simply put - an API to build an object system • Moose is one object system built upon Class::MOP • Understanding Class::MOP and Moose’s use of it reveals new features in Moose Friday, July 6, 12

Slide 89

Slide 89 text

MOP Parts • The Class protocol • The Attribute protocol • The Method protocol • The Instance protocol Friday, July 6, 12

Slide 90

Slide 90 text

Moose and Class::MOP • Moose is built on top of Class::MOP • Prefixed Moose::Meta (for example Moose::Meta::Class) • Get with $self->meta Friday, July 6, 12

Slide 91

Slide 91 text

What Meta Can Do For You • Class and Object Introspection • Modify objects and classes dynamically (add/remove methods, attributes, roles) • Add more information to attributes (label, persistent) Friday, July 6, 12

Slide 92

Slide 92 text

Object Introspection package main; my $z = Zombie->new; for my $attr ( $z->meta->get_all_attributes ) { say $attr->name; } for my $method ( $z->meta->get_all_methods ) { say $method->fully_qualified_name; } if ( $z->meta->has_method( 'eat_brain' ) ) { $z->eat_brain; } Full Source: https://gist.github.com/3032056 Friday, July 6, 12

Slide 93

Slide 93 text

Object Introspection • All meta methods listed under: Class::MOP::Class and Moose::META::Class • In most cases, using roles is a better idea than dynamic checking Friday, July 6, 12

Slide 94

Slide 94 text

Validate Type Constraints • Use $self->meta->get_attribtue(attr)->type_constraint to get meta object of type constraints • $constraint->check( $value ) • $constraint->validate( $value ) or die $constraint->get_message( $value ); • $constraint->assert_valid( $value ) Friday, July 6, 12

Slide 95

Slide 95 text

Class Modification • $meta->add_attribute • $meta->remove_attribute • $meta->add_method • $meta->remove_method • $meta->make_immutable Friday, July 6, 12

Slide 96

Slide 96 text

Moose::Util • A bundle of useful functions that take away some of the pain of working with meta • Start here before implementing your own. Friday, July 6, 12

Slide 97

Slide 97 text

Moose::Util • find_meta( $class_or_obj ) • does_role( $class_or_obj, $role ) • apply_all_roles( $applicant, @roles ) • english_list( @items ) Friday, July 6, 12

Slide 98

Slide 98 text

Friday, July 6, 12

Slide 99

Slide 99 text

Moose Types Customizable Type System Friday, July 6, 12

Slide 100

Slide 100 text

Moose Type System • Verify attribute values are “valid” - of a certain type • Types have names, so they can be reused • Type checking is just sugar for method arguments validation. Perl does not associate types with variables • Earlier error detection Friday, July 6, 12

Slide 101

Slide 101 text

Stock Types • Bool, Maybe[‘a], Str, Num, Int, ClassName, RoleName • Ref, ScalarRef[‘a], ArrayRef[‘a], HashRef[‘a], CodeRef • RegexpRef, GlobRef, FileHandle • Object Friday, July 6, 12

Slide 102

Slide 102 text

Type Registry • A type is an instance of Moose::Meta::TypeConstraint • All types are stored in the type registry. Use get_type_constraint_registry from Moose::Util::TypeConstraints to get it Friday, July 6, 12

Slide 103

Slide 103 text

Example: Print All Constraints use v5.14; use Data::Dumper; use Moose::Util::TypeConstraints; my $registry = Moose::Util::TypeConstraints::get_type_constraint_registry(); print Dumper($registry->type_constraints); Friday, July 6, 12

Slide 104

Slide 104 text

Extending The Type System • Every Moose object is a new type • There are also helper methods to create new types • A new type can be named or anonymous Friday, July 6, 12

Slide 105

Slide 105 text

Named Subtypes: enum use v5.14; package Person::Types; use Moose::Util::TypeConstraints; enum 'Person::Types::EyeColor', [qw/gray brown green blue/]; package Person; use Moose; use Moose::Util::TypeConstraints; has 'eyecolor' => ( is => 'ro', isa => 'Person::Types::EyeColor', ); Friday, July 6, 12

Slide 106

Slide 106 text

Anonymous Subtypes: enum use v5.14; package Person; use Moose; use Moose::Util::TypeConstraints; has 'eyecolor' => ( is => 'ro', isa => enum [qw/gray blue brown green/], ); Friday, July 6, 12

Slide 107

Slide 107 text

More Subtypes • subtype( %opts ) - Create a new subtype • role_type ‘barks’, { role => ‘Some::Library::Role::Barks’ } • union ‘UnionName’, [qw/Str ArrayRef/]; - Create a new subtype that can hold either string or an array Friday, July 6, 12

Slide 108

Slide 108 text

Subtypes • Provide ‘as’ to specify base type • Provide ‘where’ to add constraint on the base type • Provide your own error message with ‘message’ subtype 'NaturalLessThanTen', as 'Natural', where { $_ < 10 }, message { "This number ($_) is not less than ten!" }; Friday, July 6, 12

Slide 109

Slide 109 text

Subtypes Do’s • Define all your subtype in a single module for code reuse. Use that module from every Moose class Friday, July 6, 12

Slide 110

Slide 110 text

Subtypes Do’s • Prefer namespaced subtypes: ZombieApocalipse::Human::EyeColor is better than EyeColor • Zombies may have different eye color ... Friday, July 6, 12

Slide 111

Slide 111 text

Type Coercion Proceed With Caution Friday, July 6, 12

Slide 112

Slide 112 text

Type Coercion • Automatically convert invalid data to valid • Int ------> ArrayRef[Int] • Str ------> Person • High risk - an invalid value could coerce thus skipping type validation Friday, July 6, 12

Slide 113

Slide 113 text

Type Coercion use v5.14; package Student; use Moose; use Moose::Util::TypeConstraints; subtype 'GradesArray', as 'ArrayRef[Int]'; coerce 'GradesArray', from 'Int', via { [ $_ ] }; has 'grades', is => 'ro', isa => 'GradesArray', coerce => 1; package main; my $s = Student->new( grades => 77 ); print $s->dump; Friday, July 6, 12

Slide 114

Slide 114 text

Coercion Don’ts • Don’t add coercion on Moose’s subtypes (unfortunately it’ll work) • Generally, try to avoid coercions Friday, July 6, 12

Slide 115

Slide 115 text

Friday, July 6, 12

Slide 116

Slide 116 text

Subtypes Lab • Define a new subtype for hex numbers (numbers of the format 0x22) • Add a coercion from HexNum to Int Friday, July 6, 12

Slide 117

Slide 117 text

MooseX More Than Moose Friday, July 6, 12

Slide 118

Slide 118 text

eXtending Moose • Moose is (relatively) easy to change and extend • Writing extensions can take some time and effort BUT • There are tons of Moose Extensions on CPAN • Prefixed MooseX, they provide extra or modified functionality Friday, July 6, 12

Slide 119

Slide 119 text

Useful MooseX • MooseX::StrictConstructor • MooseX::Singleton • MooseX::Declare • MooseX::FollowPBP • MooseX::Privacy • MooseX::SingleArg • MooseX::MultiMethods • MooseX::HasDefaults • MooseX::APIRole Friday, July 6, 12

Slide 120

Slide 120 text

Simple eXtensions • MooseX::StrictConstructor • MooseX::Singleton • MooseX::FollowPBP • MooseX::SingleArg • MooseX::HasDefaults • MooseX::Privacy Friday, July 6, 12

Slide 121

Slide 121 text

MooseX::StrictConstructor • Throw exception if constructor was passed an unexpected argument package Contact; use Moose; use MooseX::StrictConstructor; has 'email', is => 'ro'; has 'name', is => 'ro'; package main; # Throw an exception Contact->new( name => 'Bob', emial => '[email protected]'); Friday, July 6, 12

Slide 122

Slide 122 text

MooseX::Singleton • Create only one instance of a class • Has initialization method to pass arguments if needed package App; use MooseX::Singleton; package main; { my $app = App->instance; } { # same one my $app = App->instance; } Friday, July 6, 12

Slide 123

Slide 123 text

MooseX::FollowPBP • Use set_x and get_x as default reader and writer • SEE ALSO: Perl::Critic Friday, July 6, 12

Slide 124

Slide 124 text

MooseX::SingleArg • Easily create single arg constructor (without wrapping BUILDARGS) use v5.14; package Contact; use Moose; use MooseX::SingleArg; single_arg 'name'; has 'name', is => 'ro'; package main; my $c = Contact->new('Mike'); say $c->name; Friday, July 6, 12

Slide 125

Slide 125 text

MooseX::HasDefaults • Automatically use: is => ‘ro’ or: is => ‘rw’ use v5.14; package Point; use Moose; use MooseX::HasDefaults::RO; has ['x', 'y', 'z']; Friday, July 6, 12

Slide 126

Slide 126 text

MooseX::Privacy • Restrict visibility of methods • private can only be called from within the class • protected can only be called from within the class or any of its subclasses • Doesn’t work for roles use MooseX::Privacy; has config => ( is => 'rw', isa => 'Some::Config', traits => [qw/Private/], ); private_method foo => sub { return 23; }; protected_method bar => sub { return 42; }; Friday, July 6, 12

Slide 127

Slide 127 text

Heavy Lifting • Logging: Log4perl • MooseX::APIRole • MooseX::Declare • MooseX::MultiMethods Friday, July 6, 12

Slide 128

Slide 128 text

Log4perl • Logging is all about keeping a record of your info at runtime • Log4perl lets you control how your application logs its data • Perl’s implementation of log4j Friday, July 6, 12

Slide 129

Slide 129 text

Log4perl alternatives • print/warn debug messages: Too simple for real apps • roll-your-own: Too much work... • Log4perl is currently the best logging solution for medium- large perl applications Friday, July 6, 12

Slide 130

Slide 130 text

Log4perl and Moose • Use MooseX::Log:: Log4perl role in your class • New attributes: log and logger package MyApp; use Moose; with 'MooseX::Log::Log4perl'; sub go { my $self = shift; $self->log->debug('Starting method go'); $self->log->info('Go go go'); $self->log('IO')->info('reading data'); } Friday, July 6, 12

Slide 131

Slide 131 text

Log4perl Output • Completely customizable • Output log to: Screen, File, Socket, DBI, and more • Example: [2012/07/06 14:54:34] 130.pl MyApp::go 130.pl (9) MyApp - Starting method go [2012/07/06 14:54:34] 130.pl MyApp::go 130.pl (10) MyApp - Go go go [2012/07/06 14:54:34] 130.pl MyApp::go 130.pl (12) IO - reading data Friday, July 6, 12

Slide 132

Slide 132 text

Log4perl Configuration log4perl.logger = DEBUG, Screen, Logfile log4perl.appender.Screen = Log::Log4perl::Appender::Screen log4perl.appender.Screen.layout = PatternLayout log4perl.appender.Screen.layout.ConversionPattern= \ [%r] %F %l %c - %m%n log4perl.appender.Logfile = Log::Log4perl::Appender::File log4perl.appender.Logfile.filename = my.log log4perl.appender.Logfile.layout = PatternLayout log4perl.appender.Logfile.layout.ConversionPattern = \ [%d] %F %l %c - %m%n Friday, July 6, 12

Slide 133

Slide 133 text

Log4perl Initialization • Load configuration file on startup with: Log::Log4perl::init(filename) package main; use Log::Log4perl; Log::Log4perl::init('log.conf'); Friday, July 6, 12

Slide 134

Slide 134 text

Log4perl Docs • Usage: perldoc Log::Log4perl • Conversion Patterns Layout: http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/ PatternLayout.html Friday, July 6, 12

Slide 135

Slide 135 text

MooseX::APIRole • Automatically create a role out of a class • all subroutines become ‘requires’ • Easy to use and very powerful package Logger; use Moose; use MooseX::APIRole; sub info { } sub error { } make_api_role 'Logger::API'; package Test; use Moose; # Fails - Test does not implement # required methods with 'Logger::API'; Friday, July 6, 12

Slide 136

Slide 136 text

MooseX::Declare • Use modern OO syntax for your moose objects • ‘class’ keywords declares a class. Inside, MooseX::Method::Signatures is in effect. • ‘role’ keyword declares a role Friday, July 6, 12

Slide 137

Slide 137 text

MooseX::Declare use MooseX::Declare; class BankAccount { has 'balance' => ( isa => 'Num', is => 'rw', default => 0 ); method deposit (Num $amount) { $self−>balance( $self−>balance + $amount ); } method withdraw (Num $amount) { my $current_balance = $self−>balance(); ( $current_balance >= $amount ) || confess "Account overdrawn"; $self−>balance( $current_balance − $amount ); } } Friday, July 6, 12

Slide 138

Slide 138 text

MooseX::Declare • Still experimental, API could change • Inside a method $self is already defined for you, as well as other input parameters • Awesome. perldoc MooseX::Declare for more Friday, July 6, 12

Slide 139

Slide 139 text

MooseX::MultiMethods • Allow multi methods dispatcher based on input arguments • Define multiple handlers instead of long if-else blocks Friday, July 6, 12

Slide 140

Slide 140 text

MooseX::MultiMethods package Paper; use Moose; package Scissors; use Moose; package Rock; use Moose; package Game; use Moose; use MooseX::MultiMethods; multi method play (Paper $x, Rock $y) { 1 } multi method play (Scissors $x, Paper $y) { 1 } multi method play (Rock $x, Scissors $y) { 1 } multi method play (Any $x, Any $y) { 0 } my $game = Game->new; # 1, Paper covers Rock print $game->play(Paper->new, Rock->new); Friday, July 6, 12

Slide 141

Slide 141 text

Friday, July 6, 12

Slide 142

Slide 142 text

Thanks For Listening • Ynon Perek • [email protected] • ynonperek.com Friday, July 6, 12