Introduction To Moose

Mike Whitaker
Mike WhitakerMedia Publishing tech lead, Perl Advocate
Introduction to Moose
        Italian Perl Workshop 2009
  Mike Whitaker - BBC / EnlightenedPerl.org
About me
About me

• BBC iPlayer team
About me

• BBC iPlayer team
• ex-Yahoo Europe (News team)
About me

• BBC iPlayer team
• ex-Yahoo Europe (News team)
• ex-CricInfo.com
About me

• BBC iPlayer team
• ex-Yahoo Europe (News team)
• ex-CricInfo.com
• Board member of EnlightenedPerl.org
Why Moose?
Why Moose?


• For that, we need a bit of history:
In the Beginning...
In the Beginning...
• ...there was Perl 5
In the Beginning...
• ...there was Perl 5
• DIY OO
In the Beginning...
• ...there was Perl 5
• DIY OO
•   perldoc perltoot
In the Beginning...
• ...there was Perl 5
• DIY OO
•   perldoc perltoot


      package Foo;

      sub new {
        my $self = {};
        return bless $self;
      }
In the Beginning...
                              package Foo;

•   ...there was Perl 5       sub new {
                                my $self = {};

• DIY OO                      }
                                return bless $self;


•   perldoc perltoot          sub bar {
                                my $self = shift;
                                my $val = shift;
      package Foo;              if (defined $val) {
                                    $self->{bar} = $val;
      sub new {                 }
        my $self = {};          else {
        return bless $self;         return $self->{bar};
      }                         }
                              }
Perl 5 Native OO
Perl 5 Native OO

• A bit of a hack
Perl 5 Native OO

• A bit of a hack
• Not really a first-class part of the language
Perl 5 Native OO

• A bit of a hack
• Not really a first-class part of the language
• Have to roll your own
So...
People started writing classes to make it
                easier....
Introduction To Moose
Class::Accessor::Classy         Class::Accessor
Object::InsideOut         fields
                                  Hash::FieldHash
       Badger::Class Rubyish
  OP                                    Object::Declare
           Class::Maker UR         Class::Gomor
 Object::Tiny::XS Class::XSAccessor
                                         Class::Framework
       Class::Accessor::Fast Class::Simple
 Rose::Object MOP::MOP                         Coat
    Object::InsideOut         Class::STD
                                          Class::Object
   Class::Base     Class::ArrayObjects
                                                 Spiffy
     Class::Accessor::Grouped Class::Frame
 Object::Accessor Object::Tiny           Object::Simple
Class::Generate       Class::Builder   accessors
     Fukurama::Class                      Class::Define
                     Abstract::Meta::Class
Moose
What is Moose?
What is Moose?
• (Post)modern Perl OO framework
What is Moose?
• (Post)modern Perl OO framework
• Deals with the overhead of implementing
  OO, allows you to get on with coding
What is Moose?
• (Post)modern Perl OO framework
• Deals with the overhead of implementing
  OO, allows you to get on with coding
• Meta-object implementation - allows you to
  introspect your classes and objects
What is Moose?
• (Post)modern Perl OO framework
• Deals with the overhead of implementing
  OO, allows you to get on with coding
• Meta-object implementation - allows you to
  introspect your classes and objects
• Already used in production software
My First Class
package Person;
use Moose;

has name => (
    is => 'rw',
);

no Moose;
Using the class
use Person;
my $person = Person->new();

$person->name('Mike');

print $person->name();
> Mike
Adding a method
package Person;
use Moose;

has name => ( is => 'rw' );

sub introduce {
    print "I'm " . $self->name;
}
Using it
use Person;
my $person = Person->new();

$person->name('Mike');

$person->introduce();
> I'm Mike
Read-only attributes
package Person;
use Moose;

has name => ( is => 'ro' );

sub introduce {
    print "I'm " . $self->name;
}
Read-only attributes (2)

use Person;
my $person = Person->new();

$person->name('Mike');
# boom!
Read-only attributes (3)

use Person;
my $person = Person->new(
    { name => 'Mike' },
);

# no boom today!
Changing defaults
has 'name' => (
    isa => 'Str',
    reader => 'get_name',
    writer => 'set_name',
    init_arg => 'name',
    required => 1,
);
Types
package Person;
use Moose;

has name => (
    is => 'rw',
    isa => 'Str',
);
Types (2)
use Person;
my $person = Person->new();

$person->name('Mike');
# shiny!

$person->name( [] );
# boom!
# Not a Str
Types (3)
package Person;
use Moose;

has name => ( is => 'rw', isa => 'Str' );

has dob => (
    is => 'rw',
    isa => 'DateTime',
);
Types (4)
use Person;
my $person = Person->new(
   { name => 'Mike' }
);
my $dob = DateTime->new (
   year => 1963, month => 8, day => 5,
);
$person->dob($dob);
print $person->dob->year;
> 1963
Subclassing
package Student;
use Moose;
extends qw/Person/;

has overdraft => (
    isa => 'Bool',
    is => 'rw',
);
Compound Types
package Student;
use Moose;
extends qw/Person/;

has classes => (
    isa => 'HashRef[Str]',
    is => 'rw',
);
Required attributes
package Student;
use Moose;
extends qw/Person/;
# ...
has course => (
    isa => 'Str',
    is => 'ro',
    required => 1,
);
Setting defaults
package Student;
use Moose;

has 'overdraft' => (
    isa => 'Bool',
    default => 1,
);
But, what if...

package BankAccount;

sub balance {
    # yadda yadda
}
And then...
package Student;
use Moose;
extends qw/Person/;

has 'account' => (
    isa => 'BankAccount',
    is => 'rw',
    required => 1,
);
Lazy default
has 'overdraft' => (
    isa => 'Bool',
    is => 'ro',
    lazy => 1,
    default => sub {
      shift->account->balance < 0;
    }
);
Lazy builder
has 'overdraft' => (
    isa => 'Bool',
    is => 'ro',
    lazy_build => 1,
    init_arg => undef,
);
sub _build_overdraft {
   return shift->account->balance < 0;
}
Method modifiers
package Student;
# yadda yadda

after 'introduce' => sub {
    my $self = shift;
    print ', studying ' . $self->course;
}
Using it
use Student;
my $person = Student->new(
    name => 'Mike',
    course => 'Computer Science',
);

$person->introduce();
> I'm Mike, studying Computer Science
Method modifiers (2)
package Student;
# yadda yadda

around 'introduce' => sub {
    my ($next, $self, @args) = @_;
    print "Hi, ";
    $self->$next(@args);
    print ', studying ' . $self->course;
}
Using around
use Student;
my $person = Student->new(
    name => 'Mike',
    course => 'Computer Science',
);

$person->introduce();
> Hi, I'm Mike, studying Computer Science
Roles
Roles
• Code fragments that define and provide a
  small, reusable behaviour
Roles
• Code fragments that define and provide a
  small, reusable behaviour
• Not inherited - methods become part of
  consuming class
Roles
• Code fragments that define and provide a
  small, reusable behaviour
• Not inherited - methods become part of
  consuming class
 • can be overriden by comsuming class
Roles
• Code fragments that define and provide a
  small, reusable behaviour
• Not inherited - methods become part of
  consuming class
 • can be overriden by comsuming class
 • like MI but better!
Example role
package Age;
use Moose::Role;
has dob => (
    isa => 'DateTime', is =>'ro'
);
sub age {
    return DateTime->now
     ->subtract( shift->dob() )
     ->years;
}
Using a role
package Person;
use Moose;
with qw/Age/;
has name => ( isa => 'Str', is => 'ro');

sub introduce {
    print "I'm " . $self->name .
       ', age ' . $self->age;
}
Using a role (2)
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => ... # yadda yadda
    course => 'CS',
);

$person->introduce();
> Hi, I'm Mike, age 45, studying CS
What we'd really like
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => '05-08-1963',
    course => 'CS',
);
Redefine our attr...
package Age;
use Moose::Role;
has dob => (
    isa => 'DateStr',
    is =>'ro',
);
Types to the rescue

use Moose::Util::TypeConstraints;

subtype 'DateStr'
    => as 'Str'
    => where {
        /^dd-dd-dddd$/
    };
Types to the rescue (2)
use Moose::Util::TypeConstraints;
class_type 'DateTime';

coerce 'DateTime' => from 'Str'
   => via {
      my ($d, $m, $y) = split /-/, $_;
      return DateTime->new(
        year => $y, month => $m, day => $d
     );
  };
And then...
package Age;
use Moose::Role;
has dob => (
    isa => 'DateTime',
    is =>'ro',
    coerce => 1, # very important!
);
Et voila...
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => '05-08-1963',
    course => 'CS',
);

print $person->age();
> 45
Roles as interfaces
package Earnings;
use Moose::Role;

requires qw/annual_income/;

sub monthly_income {
    return shift->annual_income / 12;
}
Roles as interfaces (2)
package Person;
with qw/Earnings/;

package Student;
extends qw/Person/;

sub annual_income {
   my $self = shift;
   return $self->grant_amount;
}
Role gotchas
Role gotchas

• Roles cannot use extends
Role gotchas

• Roles cannot use extends
• requires only works with actual methods :(
Role gotchas

• Roles cannot use extends
• requires only works with actual methods :(
 • for now, at least
Role gotchas

• Roles cannot use extends
• requires only works with actual methods :(
 • for now, at least
• watch out for method and attribute
  conflicts
Method Delegation
package Degree;
use Moose;
use Moose::Utils::TypeConstraints;
enum 'Grade' => qw/I IIi IIii III/;


has 'grade' => ( isa => 'Grade' );
has 'awarded' => (
    isa => 'DateTime',
    coerce => 1,
);
Method Delegation (2)
package Graduate;
use Moose;
extends qw/Student/;

has 'degree' => (
   isa => 'Degree',
   is => 'rw',
);
Method Delegation (3)
my $g = Graduate->new(name => 'Mike');
my $d = Degree->new(
    awarded => '06-06-1985',
    grade => 'IIii',
);
$g->degree($d);

print $g->degree->awarded->year;
> 1985
Method Delegation (4)
has 'degree' => (
   isa => 'Degree',
   is => 'rw',
   handles => {
       graduated => 'awarded'
   },
);
Method Delegation (5)
my $g = Graduate->new(name => 'Mike');
my $d = Degree->new(
    awarded => '06-06-1985',
    grade => 'IIii',
);
$g->degree($d);

print $g->graduated->year;
> 1985
More on attributes
package Student;
use MooseX::Util::TypeConstraints;
use Moose;
extends qw/Person/;
enum 'Result' => qw/pass fail/;
has classes => (
    isa => 'HashRef[Result]',
    is => 'rw',
    predicate => 'has_classes',
);
Attribute Helpers
my $st = Student->new( name => 'Mike' );

$st->classes(
    { "Compilers" => 'fail',
     "Numerical Methods" => 'pass' }
);

%{$st->classes}->{"Lisp"} = "pass";
Attribute Helpers (2)
use MooseX::AttributeHelpers;
has classes => (
    metaclass => 'Collection::Hash',
    isa => 'HashRef[Result]',
    is => 'rw',
    provides => {
        set => 'add_class',
        keys => 'list_classes',
    }
)
Attribute Helpers (3)
my $st = Student->new( name => 'Mike' );

$st->classes(
    { "Compilers" => 'fail',
      "Numerical Methods" => 'pass' }
);

$st->add_class("Lisp" => 'pass');
print join ", ", $st->list_classes();
> Compilers, Numerical Methods, Lisp
Introspecting Moose
Introspecting Moose
• my $metaclass = $self->meta;
Introspecting Moose
• my $metaclass = $self->meta;
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
• $metaclass->linearized_isa;
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
• $metaclass->linearized_isa;
• $metaclass->has_method("foo");
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
• $metaclass->linearized_isa;
• $metaclass->has_method("foo");
• $metaclass->get_all_attributes;
Method Signatures
Method Signatures

• We have types...
Method Signatures

• We have types...
• Wouldn't it be nice if types weren't
  restricted to attrs + accessors?
Method Signatures

• We have types...
• Wouldn't it be nice if types weren't
  restricted to attrs + accessors?
• Enter: MooseX::Method::Signature
Method Signatures
package Student;
use Moose;
use MooseX::Method::Signatures;

method attend (Str $class, DateTime
$time) {
     # ...
}
Method Signatures (2)
method attend
  (Str $class, DateTime $time) {
    if (grep $class,
        $self->list_classes) {
        $self->schedule($time, $class);
    }
}
Even more Java-like?
use MooseX::Declare;

class Student extends Person with
Earnings {
   has 'id' => ( isa => 'StudentID' );

    method attend ( Str $class, ... ) {
        # yadda yadda
    }
}
How is this
implemented?
Introduction To Moose
Lasciate ogne
  speranza,
voi ch'intrate
Introduction To Moose
But seriously...
But seriously...

• Devel::Declare sticks the interpreter on
  pause while it plays with your source
But seriously...

• Devel::Declare sticks the interpreter on
  pause while it plays with your source
• NOT a source filter
But seriously...

• Devel::Declare sticks the interpreter on
  pause while it plays with your source
• NOT a source filter
• You don't need to know what's going on...
Why Moose?
Why Moose?
• Less code = fewer errors
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
 • "We do this so you don't have to"
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
 • "We do this so you don't have to"
 • Less need for low level tests
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
 • "We do this so you don't have to"
 • Less need for low level tests
• More descriptive code
Further Reading
Further Reading

• http://iinteractive.com/moose/
Further Reading

• http://iinteractive.com/moose/
• Moose::Cookbook (CPAN)
Further Reading

• http://iinteractive.com/moose/
• Moose::Cookbook (CPAN)
• http://www.stonehenge.com/merlyn/
  LinuxMag/col94.html
Introduction To Moose
Complex Example
package Student;
use Moose;

# yadda

has 'id' => (
     isa => 'StudentID',
     is => 'rw',
);
Complex Example (2)
use MooseX::ClassAttribute;

class_has 'db' => (
    isa => 'Str', is => 'rw',
    default => 'dbi:SQLite:dbname=s.db'
);
class_has _schema => (
    isa => 'Person::Schema',
    lazy_build => 1, is => 'ro',
);
Complex Example (3)

sub _build__schema {
    my $self = shift;
    return Person::Schema->connect(
        $self->db
    );
}
Complex Example (4)
use Config::General;

override BUILDARGS => sub {
    my $args = super;

     my %conf = Config::General
         ->new( 'db.conf' )->getall();
     $args->{db} = $conf{db}
         if exists $conf{db};
};
Complex Example (5)
has _row => {
    isa => 'DBIx::Class::Row',
    lazy_build => 1,
}
sub _build__row {
    return shift->_schema
        ->resultset('Student')
        ->find($self->id);
}
Complex Example (6)

has _row => {
    isa => 'DBIx::Class::Row',
    lazy_build => 1,
    handles => [qw/address gender/],
}
Complex Example (7)
my $student = Student->new(
     name => 'Mike', id => '3056',
);

print $st->address();

# What happens here?
What happens?
What happens?
•   address method is handled by _row
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row

• which requires _schema, ALSO
    lazy_build
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row

• which requires _schema, ALSO
    lazy_build

• which uses id to find the right row in db
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row

• which requires _schema, ALSO
    lazy_build

• which uses id to find the right row in db
•   Tadaa!
But...
# What if the student's ID changes?

has 'id' => (
    isa => 'StudentID',
    is => 'rw',
    trigger => '_build__row',
);
1 of 129

Recommended

OO Perl with MooseOO Perl with Moose
OO Perl with MooseNelo Onyiah
5K views103 slides
Moose (Perl 5)Moose (Perl 5)
Moose (Perl 5)xSawyer
3.5K views20 slides
Introduction to MooseIntroduction to Moose
Introduction to Moosethashaa
2.2K views47 slides
Moose workshopMoose workshop
Moose workshopYnon Perek
2.4K views142 slides
Moose Best PracticesMoose Best Practices
Moose Best PracticesAran Deltac
2.4K views15 slides

More Related Content

What's hot(20)

A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
Michael Pirnat11.1K views
The jQuery DivideThe jQuery Divide
The jQuery Divide
Rebecca Murphey29.3K views
WordPress Cuztom HelperWordPress Cuztom Helper
WordPress Cuztom Helper
slicejack1.2K views
Bioinformatics p5-bioperl v2013-wim_vancriekingeBioinformatics p5-bioperl v2013-wim_vancriekinge
Bioinformatics p5-bioperl v2013-wim_vancriekinge
Prof. Wim Van Criekinge4.7K views
Bioinformatica p6-bioperlBioinformatica p6-bioperl
Bioinformatica p6-bioperl
Prof. Wim Van Criekinge679 views
Perl object ?Perl object ?
Perl object ?
ℕicolas ℝ.340 views
Transparent Object Persistence with FLOW3Transparent Object Persistence with FLOW3
Transparent Object Persistence with FLOW3
Karsten Dambekalns2.3K views
Contando uma história com O.O.Contando uma história com O.O.
Contando uma história com O.O.
Vagner Zampieri332 views
Rails for PHP DevelopersRails for PHP Developers
Rails for PHP Developers
Robert Dempsey2.3K views
Django at ScaleDjango at Scale
Django at Scale
bretthoerner8.4K views

Similar to Introduction To Moose

P6 OO vs Moose (&Moo)P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)lichtkind
1.6K views140 slides
Perl Teach-In (part 2)Perl Teach-In (part 2)
Perl Teach-In (part 2)Dave Cross
1.8K views89 slides
Moose - YAPC::NA 2012Moose - YAPC::NA 2012
Moose - YAPC::NA 2012xSawyer
1.3K views35 slides

Similar to Introduction To Moose(20)

Moo the universe and everythingMoo the universe and everything
Moo the universe and everything
Henry Van Styn1.1K views
P6 OO vs Moose (&Moo)P6 OO vs Moose (&Moo)
P6 OO vs Moose (&Moo)
lichtkind1.6K views
Perl Teach-In (part 2)Perl Teach-In (part 2)
Perl Teach-In (part 2)
Dave Cross1.8K views
What's in a language? By Cheng Lou What's in a language? By Cheng Lou
What's in a language? By Cheng Lou
React London 2017286 views
Moose - YAPC::NA 2012Moose - YAPC::NA 2012
Moose - YAPC::NA 2012
xSawyer1.3K views
DBIx::Skinnyと仲間たちDBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たち
Ryo Miyake1.9K views
Ruby 入門 第一次就上手Ruby 入門 第一次就上手
Ruby 入門 第一次就上手
Wen-Tien Chang3.5K views
A Whirlwind Tour of Test::ClassA Whirlwind Tour of Test::Class
A Whirlwind Tour of Test::Class
Curtis Poe2.5K views
The Essential Perl Hacker's ToolkitThe Essential Perl Hacker's Toolkit
The Essential Perl Hacker's Toolkit
Stephen Scaffidi3K views
Ruby :: Training 1Ruby :: Training 1
Ruby :: Training 1
Pavel Tyk837 views
Ruby 2: some new thingsRuby 2: some new things
Ruby 2: some new things
David Black798 views
Ruby 101Ruby 101
Ruby 101
Harisankar P S841 views
From Ruby to ScalaFrom Ruby to Scala
From Ruby to Scala
tod esking7.9K views
Objective C 基本介紹Objective C 基本介紹
Objective C 基本介紹
Giga Cheng641 views
PHP-05-Objects.pptPHP-05-Objects.ppt
PHP-05-Objects.ppt
rani marri3 views

Recently uploaded(20)

The Research Portal of Catalonia: Growing more (information) & more (services)The Research Portal of Catalonia: Growing more (information) & more (services)
The Research Portal of Catalonia: Growing more (information) & more (services)
CSUC - Consorci de Serveis Universitaris de Catalunya51 views
CXL at OCPCXL at OCP
CXL at OCP
CXL Forum183 views
Liqid: Composable CXL PreviewLiqid: Composable CXL Preview
Liqid: Composable CXL Preview
CXL Forum118 views

Introduction To Moose