$30 off During Our Annual Pro Sale. View Details »

Advanced Perl Moose

ynonperek
July 06, 2012
2.5k

Advanced Perl Moose

Licensed under Creative Common Non Commercial:
http://creativecommons.org/licenses/by-nc/2.5/

ynonperek

July 06, 2012
Tweet

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  9. Moose Classes
    Friday, July 6, 12

    View Slide

  10. 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

    View Slide

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

    View Slide

  12. 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

    View Slide

  13. 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

    View Slide

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

    View Slide

  15. 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

    View Slide

  16. 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

    View Slide

  17. 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

    View Slide

  18. 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

    View Slide

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

    View Slide

  20. 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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  31. 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

    View Slide

  32. 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

    View Slide

  33. 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

    View Slide

  34. 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

    View Slide

  35. 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

    View Slide

  36. 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

    View Slide

  37. 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

    View Slide

  38. Friday, July 6, 12

    View Slide

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

    View Slide

  40. 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

    View Slide

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

    View Slide

  42. 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

    View Slide

  43. 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

    View Slide

  44. 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

    View Slide

  45. 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

    View Slide

  46. 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

    View Slide

  47. 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

    View Slide

  48. 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

    View Slide

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

    View Slide

  50. 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

    View Slide

  51. 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

    View Slide

  52. Friday, July 6, 12

    View Slide

  53. Attributes
    Friday, July 6, 12

    View Slide

  54. 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

    View Slide

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

    View Slide

  56. 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

    View Slide

  57. 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

    View Slide

  58. 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

    View Slide

  59. 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

    View Slide

  60. 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

    View Slide

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

    View Slide

  62. 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

    View Slide

  63. 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

    View Slide

  64. 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

    View Slide

  65. 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

    View Slide

  66. 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

    View Slide

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

    View Slide

  68. 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

    View Slide

  69. 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

    View Slide

  70. 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

    View Slide

  71. 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

    View Slide

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

    View Slide

  73. Friday, July 6, 12

    View Slide

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

    View Slide

  75. 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

    View Slide

  76. 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

    View Slide

  77. 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

    View Slide

  78. 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

    View Slide

  79. 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

    View Slide

  80. 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

    View Slide

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

    View Slide

  82. 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

    View Slide

  83. 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

    View Slide

  84. 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

    View Slide

  85. Friday, July 6, 12

    View Slide

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

    View Slide

  87. Meta Moose
    Friday, July 6, 12

    View Slide

  88. 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

    View Slide

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

    View Slide

  90. 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

    View Slide

  91. 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

    View Slide

  92. 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

    View Slide

  93. 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

    View Slide

  94. 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

    View Slide

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

    View Slide

  96. 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

    View Slide

  97. 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

    View Slide

  98. Friday, July 6, 12

    View Slide

  99. Moose Types
    Customizable Type System
    Friday, July 6, 12

    View Slide

  100. 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

    View Slide

  101. 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

    View Slide

  102. 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

    View Slide

  103. 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

    View Slide

  104. 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

    View Slide

  105. 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

    View Slide

  106. 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

    View Slide

  107. 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

    View Slide

  108. 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

    View Slide

  109. 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

    View Slide

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

    View Slide

  111. Type Coercion
    Proceed With Caution
    Friday, July 6, 12

    View Slide

  112. 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

    View Slide

  113. 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

    View Slide

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

    View Slide

  115. Friday, July 6, 12

    View Slide

  116. 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

    View Slide

  117. MooseX
    More Than Moose
    Friday, July 6, 12

    View Slide

  118. 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

    View Slide

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

    View Slide

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

    View Slide

  121. 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

    View Slide

  122. 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

    View Slide

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

    View Slide

  124. 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

    View Slide

  125. 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

    View Slide

  126. 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

    View Slide

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

    View Slide

  128. 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

    View Slide

  129. 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

    View Slide

  130. 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

    View Slide

  131. 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

    View Slide

  132. 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

    View Slide

  133. 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

    View Slide

  134. 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

    View Slide

  135. 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

    View Slide

  136. 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

    View Slide

  137. 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

    View Slide

  138. 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

    View Slide

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

    View Slide

  140. 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

    View Slide

  141. Friday, July 6, 12

    View Slide

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

    View Slide