Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

rumor on the Intertubes is that Perl is Dead

Slide 3

Slide 3 text

is a member of the zombie horde

Slide 4

Slide 4 text

(Moose)(is)(a) [postmodern) (object] [system)

Slide 5

Slide 5 text

(Moose)(is)(a) [postmodern) (object] [system) Stable! 2+ years old! Used widely ! in production!

Slide 6

Slide 6 text

(Moose)(is)(a) [postmodern) (object] [system) Stable! 2+ years old! Used widely ! in production! Rich Ancestry CLOS Smalltalk Perl6 …

Slide 7

Slide 7 text

(Moose)(is)(a) [postmodern) (object] [system) Stable! 2+ years old! Used widely ! in production! Rich Ancestry CLOS Smalltalk Perl6 … Perlish Plays well with CPAN and vanilla perl 5 OOP

Slide 8

Slide 8 text

(Moose)(is)(a) [postmodern) (object] [system) Stable! 2+ years old! Used widely ! in production! Rich Ancestry CLOS Smalltalk Perl6 … Perlish Plays well with CPAN and vanilla perl 5 OOP

Slide 9

Slide 9 text

Moose is not a toy It is serious Business!

Slide 10

Slide 10 text

MOOSE is an Amplifier

Slide 11

Slide 11 text

package Person; use strict; use warnings; sub new { my ($class, %args) = @_; bless { name => $args{name}, age => $args{age} || 0, } => ref($class) || $class; } sub name { my $self = shift; $self->{name} = shift if @_; $self->{name}; } sub age { my $self = shift; $self->{age} = shift if @_; $self->{age}; } 1; The Old Way

Slide 12

Slide 12 text

The Old Way package Person; use strict; use warnings; use base 'Class::Accessor'; __PACKAGE__->mk_accessor(qw[name age]); 1;

Slide 13

Slide 13 text

The Old Way package Person; use strict; use warnings; use base 'Class::Accessor'; __PACKAGE__->mk_accessor(qw[name age]); sub new { my ($class, $params) = @_; $params = {} unless defined $params; $params->{age} = 0; $class->SUPER::new($params); } 1;

Slide 14

Slide 14 text

package Person; use Moose; has ‘name’ => (is => ‘rw’); has ‘age’ => (is => ‘rw’, default => 0); 1; The Moose Way

Slide 15

Slide 15 text

package Person; use Moose; use Moose::Util::TypeConstraints; use DateTime::Duration; class_type 'DateTime::Duration'; coerce 'DateTime::Duration' => from 'Int' => via { DateTime::Duration->new(years => $_) } => from 'HashRef' => via { DateTime::Duration->new( %$_ ) }; has 'name' => ( is => 'rw', isa => subtype('Str' => where { length $_ > 0 }), required => 1, ); has 'age' => ( is => 'rw', isa => 'DateTime::Duration', coerce => 1, lazy => 1, default => sub { DateTime::Duration->new }, ); 1; The Moose Way

Slide 16

Slide 16 text

package Person; use Moose; use Moose::Util::TypeConstraints; use DateTime::Duration; class_type 'DateTime::Duration'; coerce 'DateTime::Duration' => from 'Int' => via { DateTime::Duration->new(years => $_) } => from 'HashRef' => via { DateTime::Duration->new( %$_ ) }; has 'name' => ( is => 'rw', isa => subtype('Str' => where { length $_ > 0 }), required => 1, ); has 'age' => ( is => 'rw', isa => 'DateTime::Duration', coerce => 1, lazy => 1, default => sub { DateTime::Duration->new }, ); 1; The Moose Way

Slide 17

Slide 17 text

package Person; use Moose; use Moose::Util::TypeConstraints; use DateTime::Duration; class_type 'DateTime::Duration'; coerce 'DateTime::Duration' => from 'Int' => via { DateTime::Duration->new(years => $_) } => from 'HashRef' => via { DateTime::Duration->new( %$_ ) }; has 'name' => ( is => 'rw', isa => subtype('Str' => where { length $_ > 0 }), required => 1, ); has 'age' => ( is => 'rw', isa => 'DateTime::Duration', coerce => 1, lazy => 1, default => sub { DateTime::Duration->new }, ); 1; The Moose Way

Slide 18

Slide 18 text

package Person; use Moose; use Moose::Util::TypeConstraints; use DateTime::Duration; class_type 'DateTime::Duration'; coerce 'DateTime::Duration' => from 'Int' => via { DateTime::Duration->new(years => $_) } => from 'HashRef' => via { DateTime::Duration->new( %$_ ) }; has 'name' => ( is => 'rw', isa => subtype('Str' => where { length $_ > 0 }), required => 1, ); has 'age' => ( is => 'rw', isa => 'DateTime::Duration', coerce => 1, lazy => 1, default => sub { DateTime::Duration->new }, ); 1; The Moose Way

Slide 19

Slide 19 text

package Person; use Moose; use Moose::Util::TypeConstraints; use DateTime::Duration; class_type 'DateTime::Duration'; coerce 'DateTime::Duration' => from 'Int' => via { DateTime::Duration->new(years => $_) } => from 'HashRef' => via { DateTime::Duration->new( %$_ ) }; has 'name' => ( is => 'rw', isa => subtype('Str' => where { length $_ > 0 }), required => 1, ); has 'age' => ( is => 'rw', isa => 'DateTime::Duration', coerce => 1, lazy => 1, default => sub { DateTime::Duration->new }, ); 1; The Moose Way

Slide 20

Slide 20 text

package Person; use Moose; use Moose::Util::TypeConstraints; use DateTime::Duration; class_type 'DateTime::Duration'; coerce 'DateTime::Duration' => from 'Int' => via { DateTime::Duration->new(years => $_) } => from 'HashRef' => via { DateTime::Duration->new( %$_ ) }; has 'name' => ( is => 'rw', isa => subtype('Str' => where { length $_ > 0 }), required => 1, ); has 'age' => ( is => 'rw', isa => 'DateTime::Duration', coerce => 1, lazy => 1, default => sub { DateTime::Duration->new }, ); 1; The Moose Way

Slide 21

Slide 21 text

package Person; use Moose; use Moose::Util::TypeConstraints; use DateTime::Duration; class_type 'DateTime::Duration'; coerce 'DateTime::Duration' => from 'Int' => via { DateTime::Duration->new(years => $_) } => from 'HashRef' => via { DateTime::Duration->new( %$_ ) }; has 'name' => ( is => 'rw', isa => subtype('Str' => where { length $_ > 0 }), required => 1, ); has 'age' => ( is => 'rw', isa => 'DateTime::Duration', coerce => 1, lazy => 1, default => sub { DateTime::Duration->new }, ); 1; The Moose Way

Slide 22

Slide 22 text

package Person; use strict; use warnings; use DateTime::Duration; use Scalar::Util 'blessed', 'looks_like_number'; use Carp 'confess'; sub new { my $class = shift; my %params; if (@_ == 1 && ref $_[0] eq 'HASH') { %params = %{$_[0]}; } else { %params = @_; } (exists $params{name} && length $params{name} > 0) || confess "You must supply a name"; if (exists $params{age}) { $params{age} = _coerce_date_time_duration($params{age}); } return bless \%params => ref $class || $class; } sub _coerce_date_time_duration { my ($val) = @_; if (blessed $val) { return $val if $val->isa('DateTime::Duration'); confess "A blessed value must be a DateTime::Duration object, not $val"; } elsif (ref $val) { return DateTime::Duration->new( %$val ) if ref $val eq 'HASH'; confess "We can only convert HASH refs to DateTime::Duration objects, not $val"; } elsif (looks_like_number($val)) { return DateTime::Duration->new(years => $val); } else { confess "Cannot coerce $val into DateTime::Duration object"; } } sub name { my $self = shift; if (@_) { my $name = shift; (length $name > 0) || confess "You must supply a name"; $self->{name} = $name; } return $self->{name}; } sub age { my $self = shift; if (@_) { $self->{age} = _coerce_date_time_duration(shift); } else { $self->{age} ||= DateTime::Duration->new; } return $self->{age}; } 1; The Old Way

Slide 23

Slide 23 text

Wait Just a Minute!

Slide 24

Slide 24 text

Wait Just a Minute! Isn’t Moose slow?

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

Moose is mostly compile time overhead

Slide 27

Slide 27 text

Moore’s Law

Slide 28

Slide 28 text

Moore’s Law Developer Speed Invention of Jolt

Slide 29

Slide 29 text

Moore’s Law Developer Speed Developer Salaries Invention of Jolt

Slide 30

Slide 30 text

Moore’s Law Developer Speed Developer Salaries Inflation Invention of Jolt

Slide 31

Slide 31 text

Moore’s Law Developer Speed Developer Salaries Inflation Rate of Bullsh*t in my graph Invention of Jolt

Slide 32

Slide 32 text

Moore’s Law Developer Speed Developer Salaries Inflation Rate of Bullsh*t in my graph Invention of Jolt Moose *will* get faster Class::MOP 0.49 - 2x speedup (XS) Class::MOP 0.57 - 20-25% speedup Class::MOP 0.59 - 25-30% speedup Computers will get faster, perl will get faster and Moose will get faster ... but your brain never will.

Slide 33

Slide 33 text

Lets do some more Moose

Slide 34

Slide 34 text

package Employee; use Moose; extends 'Person'; has 'job_title' => ( is => 'rw', isa => 'Str’ );

Slide 35

Slide 35 text

package Employee; use Moose; extends 'Person'; has 'job_title' => ( is => 'rw', isa => 'Str’ ); package Manager; use Moose; extends 'Employee'; has '+job_title' => (default => 'Manager'); has 'staff' => ( is => 'ro', isa => 'ArrayRef[Employee]', default => sub { [] }, );

Slide 36

Slide 36 text

package Employee; use Moose; extends 'Person'; has 'job_title' => ( is => 'rw', isa => 'Str’ ); has 'manager' => ( is => 'ro', isa => 'Manager', handles => { coworkers => 'staff', } ); package Manager; use Moose; extends 'Employee'; has '+job_title' => (default => 'Manager'); has 'staff' => ( is => 'ro', isa => 'ArrayRef[Employee]', default => sub { [] }, );

Slide 37

Slide 37 text

package Employee; use Moose; extends 'Person'; has 'job_title' => ( is => 'rw', isa => 'Str’ ); has 'manager' => ( is => 'ro', isa => 'Manager', handles => { coworkers => 'staff', } ); package Manager; use Moose; use MooseX::AttributeHelpers; extends 'Employee'; has '+job_title' => (default => 'Manager'); has 'staff' => ( metaclass => 'Collection::Array', is => 'ro', isa => 'ArrayRef[Employee]', default => sub { [] }, provides => { count => 'staff_size', empty => 'has_staff', push => 'add_to_staff', pop => 'lay_off_new_guy', } );

Slide 38

Slide 38 text

package Employee; use Moose; extends 'Person'; has 'job_title' => ( is => 'rw', isa => 'Str’ ); has 'manager' => ( is => 'ro', isa => 'Manager', handles => { coworkers => 'staff', } ); package Manager; use Moose; use MooseX::AttributeHelpers; extends 'Employee'; has '+job_title' => (default => 'Manager'); has 'staff' => ( metaclass => 'Collection::Array', is => 'ro', isa => 'ArrayRef[Employee]', default => sub { [] }, provides => { count => 'staff_size', empty => 'has_staff', push => 'add_to_staff', pop => 'lay_off_new_guy', } ); after 'add_to_staff' => sub { my ($self, $employee) = @_; $employee->manager($self); };

Slide 39

Slide 39 text

package Employee; use Moose; extends 'Person'; has 'job_title' => ( is => 'rw', isa => 'Str’ ); has 'manager' => ( is => 'ro', isa => 'Manager', clearer => 'remove_manager', predicate => 'has_manager', handles => { coworkers => 'staff', } ); package Manager; use Moose; use MooseX::AttributeHelpers; extends 'Employee'; has '+job_title' => (default => 'Manager'); has 'staff' => ( metaclass => 'Collection::Array', is => 'ro', isa => 'ArrayRef[Employee]', default => sub { [] }, provides => { count => 'staff_size', empty => 'has_staff', push => 'add_to_staff', pop => 'lay_off_new_guy', } ); after 'add_to_staff' => sub { my ($self, $employee) = @_; $employee->manager($self); };

Slide 40

Slide 40 text

package Employee; use Moose; extends 'Person'; has 'job_title' => ( is => 'rw', isa => 'Str’ ); has 'manager' => ( is => 'ro', isa => 'Manager', clearer => 'remove_manager', predicate => 'has_manager', handles => { coworkers => 'staff', } ); package Manager; use Moose; use MooseX::AttributeHelpers; extends 'Employee'; has '+job_title' => (default => 'Manager'); has 'staff' => ( metaclass => 'Collection::Array', is => 'ro', isa => 'ArrayRef[Employee]', default => sub { [] }, provides => { count => 'staff_size', empty => 'has_staff', push => 'add_to_staff', pop => 'lay_off_new_guy', } ); after 'add_to_staff' => sub { my ($self, $employee) = @_; $employee->manager($self); }; around 'lay_off_new_guy' => sub { my $next = shift; my $self = shift; my $new_guy = $self->$next(@_); $new_guy->remove_manager; $new_guy; };

Slide 41

Slide 41 text

The Old Way package Employee; use strict; use warnings; use base 'Person'; sub new { my ($class, %params) = @_; my %params; if (@_ == 1 && ref $_[0] eq 'HASH') { %params = %{$_[0]}; } else { %params = @_; } (blessed $params{manager} && $params{manager}->isa('Manager')) || confess "You must supply a name"; my $self = $class->SUPER::new(%params); $self->{manager} = $params{manager}; $self->{job_title} = $params{job_title} if exists $params{job_title}; return $self; } sub job_title { my $self = shift; if (@_) { $self->{job_title} = shift; } return $self->{job_title}; } sub manager { my $self = shift; if (@_) { my $manager = shift; (blessed $manager && $manager->isa('Manager')) || confess "You must supply a manager"; $self->{manager} = $manager; } return $self->{manager}; } sub remove_manager { my $self = shift; delete $self->{manager} } sub has_manager { my $self = shift; exists $self->{manager} ? 1 : 0 } sub coworkers { my $self = shift; $self->manager->staff } package Manager; use strict; use warnings; use base 'Employee'; sub new { my ($class, %params) = @_; my %params; if (@_ == 1 && ref $_[0] eq 'HASH') { %params = %{$_[0]}; } else { %params = @_; } if (exists $params{staff}) { (ref $params{staff} eq 'ARRAY') || confess "Staff must be an ARRAY ref"; foreach (@{$params{staff}}) { ($_->isa('Employee')) || confess "You staff elements must “ . “be Employee objects"; } } else { $params{staff} = []; } my $self = $class->SUPER::new(%params); $self->{staff} = $params{staff}; $self->{job_title} = $params{job_title} || 'Manager'; return $self; } sub staff { my $self = shift; if (@_) { my $staff = shift; if (defined $staff) { (ref $staff eq 'ARRAY') || confess "Staff must be an ARRAY ref"; foreach (@{$staff}) { ($_->isa('Employee')) || confess "You staff elements must be Employee objects"; } } else { $staff = []; } } return $self->{staff}; } sub staff_size { my $self = shift; $self->{staff} ||= []; $#{ $self->{staff} } } sub has_staff { my $self = shift; $self->{staff} ||= []; @{ $self->{staff} } ? 1 : 0 } sub add_to_staff { my ($self, $employee) = @_; (blessed $employee && $employee->isa('Employee')) || confess "You can only add employee instances"; $self->{staff} ||= []; push @{ $self->{staff} } => $employee; $employee->manager($self); } sub lay_off_new_guy { my $self = shift; return undef if defined $self->{staff} my $new_guy = pop @{ $self->{staff} }; $new_guy->remove_manager; $new_guy; }

Slide 42

Slide 42 text

package Salaried; use Moose::Role; requires 'paycheck_amount';

Slide 43

Slide 43 text

package Salaried; use Moose::Role; requires 'paycheck_amount'; package Salaried::Hourly; use Moose::Role; with 'Salaried'; has hourly_rate => ( is => 'rw', isa => 'Int', required => 1, ); has logged_hours => ( is => 'rw', isa => 'Int', default => 0, ); sub paycheck_amount { my $self = shift; $self->logged_hours * $self->hourly_rate; }

Slide 44

Slide 44 text

package Salaried; use Moose::Role; requires 'paycheck_amount'; package Salaried::Hourly; use Moose::Role; with 'Salaried'; has hourly_rate => ( is => 'rw', isa => 'Int', required => 1, ); has logged_hours => ( is => 'rw', isa => 'Int', default => 0, ); sub paycheck_amount { my $self = shift; $self->logged_hours * $self->hourly_rate; } package Salaried::Yearly; use Moose::Role; with 'Salaried'; has salary => ( is => 'rw', isa => 'Int', required => 1, ); sub paycheck_amount { my $self = shift; $self->salary / 12 }

Slide 45

Slide 45 text

package Salaried; use Moose::Role; requires 'paycheck_amount'; package Salaried::Hourly; use Moose::Role; with 'Salaried'; has hourly_rate => ( is => 'rw', isa => 'Int', required => 1, ); has logged_hours => ( is => 'rw', isa => 'Int', default => 0, ); sub paycheck_amount { my $self = shift; $self->logged_hours * $self->hourly_rate; } package Salaried::Yearly; use Moose::Role; with 'Salaried'; has salary => ( is => 'rw', isa => 'Int', required => 1, ); sub paycheck_amount { my $self = shift; $self->salary / 12 } package Employee; use Moose; extends 'Person'; with 'Salaried::Hourly'; # ... package Manager; use Moose; extends ’Employee'; with 'Salaried::Yearly'; # ...

Slide 46

Slide 46 text

Benefits of Moose

Slide 47

Slide 47 text

Benefits of Moose Code is less tedious

Slide 48

Slide 48 text

Benefits of Moose Code is less tedious Code is shorter

Slide 49

Slide 49 text

Benefits of Moose Code is less tedious Code is shorter Less low-level testing

Slide 50

Slide 50 text

Benefits of Moose Code is less tedious Code is shorter Less low-level testing Code is more descriptive

Slide 51

Slide 51 text

The Pit of Moose Despair

Slide 52

Slide 52 text

The Pit of Moose Despair Compile Time Cost

Slide 53

Slide 53 text

The Pit of Moose Despair Compile Time Cost Some Features Are Slow

Slide 54

Slide 54 text

The Pit of Moose Despair Compile Time Cost A Lot of Kool-aid Some Features Are Slow

Slide 55

Slide 55 text

The Pit of Moose Despair Compile Time Cost A Lot of Kool-aid Some Features Are Slow Sometimes doesn’t! play well with others

Slide 56

Slide 56 text

The End