Moose workshop

Post on 10-May-2015

1.616 views 10 download

Tags:

description

Object Oriented got a lot easier since Moose came around. This keynote is a one-day advanced Moose workshop covering (almost) everything Moose has to offer perl developers

Transcript of Moose workshop

Ynon Perekynonperek@yahoo.comhttp://ynonperek.com

Moose Workshop

Friday, July 6, 12

Agenda

•Moose Overview

• Classes

• Roles

• Attributes

•Meta Object System

• Type System

•Moose Extensions

•Design Patterns

Friday, July 6, 12

Assumptions

• You know how to write a Moose classes

• You know how to define methods and what $self means

Friday, July 6, 12

Moose Overview

•Developed by Stevan Little (on the right)

• Started 2006

• Goal: Change the world

Friday, July 6, 12

Moose Features

• From perl to OO

•No boilerplate code

•Optional type constraints

• Inheritance and Mixins

•Design Patterns

Friday, July 6, 12

Organizations Using Moose

• Cisco

• IMDb

• Infinity Interactive

•MusicBrainz

• Symantec

• And others: http://moose.iinteractive.com/about.html#organizations

Friday, July 6, 12

Moose Alternatives

•Mouse

•Moo

•Mo

• Class::Builder

Friday, July 6, 12

Moose HELP

• IRC: irc://irc.perl.org/#moose

•Mailing List: mailto:moose-subscribe@perl.org

• Youtube: search for “perl moose”

Friday, July 6, 12

Moose Classes

Friday, July 6, 12

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

Moose::Object

• new ( %params )

• BUILDARGS ( %params )

•DESTROY

• does( $role_name )

•DOES( $class_or_role_name )

• dump( $maxdepth )

Friday, July 6, 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::Dumperwarn $dog->dump;

# DOES returns true for objects of the class, subclasses or# implementors of the roleprint "Good boy" if $dog->DOES('Pet');

Friday, July 6, 12

Class Construction

• new method is automatically generated.

• Takes parameters hash or hash ref

package main;# Pass a hash ref to prevent copyingmy $enterprise = Starship->new( {        captain => 'James T Kirk',        crew => ['Dr. McCoy', 'Scott', 'Lt. Uhura'],    });

Friday, July 6, 12

Class Construction

• Construction hooks:

• BUILD

• BUILDARGS

• attribute builders

Friday, July 6, 12

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

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 errormy $enterprise = Starship->new( {        captain => 'James T Kirk',        crew => ['Dr. McCoy', 'Scott', 'Lt. Uhura', 'James T Kirk'],    });

Friday, July 6, 12

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

BUILDARGS Examplepackage 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

Class Destruction

•Moose implemented DESTROY, which will call your DEMOLISH

• It handles inheritance correctly: demolish child before super

Friday, July 6, 12

Class Destruction

•When program ends, prints out:

Bar ::DemolishFoo::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

Construction Destruction

Do’s and Don’ts

Friday, July 6, 12

Do

• Provide reasonable validations with BUILD

Friday, July 6, 12

Do

• Use warn( $obj->dump ) for debug

Friday, July 6, 12

Do

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

Friday, July 6, 12

Do

• Consider using:

__PACKAGE__->meta->make_immutable;

• To improve performance of objects creation

• Consider MooseX::AutoImmute

Friday, July 6, 12

Don’t

•Never override new ( it’ll break stuff down the road )

Friday, July 6, 12

Don’t

•Don’t use BUILD when attribute builders are sufficient

Friday, July 6, 12

Don’t

•Never call $self->SUPER::BUILD

•Moose does that for you

Friday, July 6, 12

Don’t

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

Friday, July 6, 12

Don’t

•Don’t write BUILD method for your roles ( Moose ignores them )

Friday, July 6, 12

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

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

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

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

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

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

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

Friday, July 6, 12

Moose RolesAn alternative to deep hierarchies and base classes

Friday, July 6, 12

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

Classes & Roles

Alive

Think Think

Alive

Person Computer Chicken

Friday, July 6, 12

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

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

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

Partial Implementationpackage 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

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

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

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

Method Conflict

with 'Breakable' => { -alias => { break => 'break_bone' }, -excludes => 'break', },

'Breakdancer' => { -alias => { break => 'break_dance' }, -excludes => 'break', };

Friday, July 6, 12

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

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

Friday, July 6, 12

Attributes

Friday, July 6, 12

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

Attribute Options

• is, reader, writer

• isa

• required, default, builder

• lazy

Friday, July 6, 12

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

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

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

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

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

Required / Default / Builder

• Use required for fields that take their value from “outside”

• Use default / builder for everything else

Friday, July 6, 12

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

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

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

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

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

Delegation

Contact EmailSend Mail Send Mail

Phone

CallCall

Friday, July 6, 12

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

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

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

Native Delegation

•Native arrays have push, pop, shift, unshift and more

• Can now use:$q->add_itemto 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

Native Delegation

• Array functions: Moose::Meta::Attribute::Native::Trait::Array

•Hash functions:Moose::Meta::Attribute::Native::Trait::Hash

Friday, July 6, 12

Friday, July 6, 12

Attributes: Advanced Topics

• Predicates & Clearers

• Constructor Parameters

•Weak References

• Triggers

Friday, July 6, 12

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 ImageNo likes yet

Image Online0 Likes.

Go find more friends

Friday, July 6, 12

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

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

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

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

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

Weak References

Course

Student Student Student

Learns At

Friday, July 6, 12

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

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/3031636Friday, July 6, 12

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

Friday, July 6, 12

Lab

• Improve Students/Course example to use native delegation

• Use method modifiers to add custom logic

Friday, July 6, 12

Meta Moose

Friday, July 6, 12

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

MOP Parts

• The Class protocol

• The Attribute protocol

• The Method protocol

• The Instance protocol

Friday, July 6, 12

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

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

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/3032056Friday, July 6, 12

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

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

Class Modification

• $meta->add_attribute

• $meta->remove_attribute

• $meta->add_method

• $meta->remove_method

• $meta->make_immutable

Friday, July 6, 12

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

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

Friday, July 6, 12

Moose TypesCustomizable Type System

Friday, July 6, 12

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

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

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

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

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

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

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

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

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

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

Subtypes Do’s

• Prefer namespaced subtypes: ZombieApocalipse::Human::EyeColor is better thanEyeColor

• Zombies may have different eye color ...

Friday, July 6, 12

Type CoercionProceed With Caution

Friday, July 6, 12

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

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

Coercion Don’ts

•Don’t add coercion on Moose’s subtypes (unfortunately it’ll work)

• Generally, try to avoid coercions

Friday, July 6, 12

Friday, July 6, 12

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

MooseXMore Than Moose

Friday, July 6, 12

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

Useful MooseX

•MooseX::StrictConstructor

•MooseX::Singleton

•MooseX::Declare

•MooseX::FollowPBP

•MooseX::Privacy

•MooseX::SingleArg

•MooseX::MultiMethods

•MooseX::HasDefaults

•MooseX::APIRole

Friday, July 6, 12

Simple eXtensions

•MooseX::StrictConstructor

•MooseX::Singleton

•MooseX::FollowPBP

•MooseX::SingleArg

•MooseX::HasDefaults

•MooseX::Privacy

Friday, July 6, 12

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 exceptionContact->new( name => 'Bob', emial => 'bob@gmail.com');

Friday, July 6, 12

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

MooseX::FollowPBP

• Use set_x and get_x as default reader and writer

• SEE ALSO: Perl::Critic

Friday, July 6, 12

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

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

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

Heavy Lifting

• Logging: Log4perl

•MooseX::APIRole

•MooseX::Declare

•MooseX::MultiMethods

Friday, July 6, 12

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

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

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

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

Log4perl Configuration

log4perl.logger = DEBUG, Screen, Logfile

log4perl.appender.Screen = Log::Log4perl::Appender::Screenlog4perl.appender.Screen.layout = PatternLayoutlog4perl.appender.Screen.layout.ConversionPattern= \ [%r] %F %l %c - %m%n

log4perl.appender.Logfile = Log::Log4perl::Appender::Filelog4perl.appender.Logfile.filename = my.loglog4perl.appender.Logfile.layout = PatternLayoutlog4perl.appender.Logfile.layout.ConversionPattern = \ [%d] %F %l %c - %m%n

Friday, July 6, 12

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

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 methodswith 'Logger::API';

Friday, July 6, 12

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

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

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

MooseX::MultiMethods

• Allow multi methods dispatcher based on input arguments

•Define multiple handlers instead of long if-else blocks

Friday, July 6, 12

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 Rockprint $game->play(Paper->new, Rock->new);

Friday, July 6, 12

Friday, July 6, 12

Thanks For Listening

• Ynon Perek

• ynonperek@yahoo.com

• ynonperek.com

Friday, July 6, 12