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 $...
In the Beginning...
                              package Foo;

•   ...there was Perl 5       sub new {
                  ...
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....
Class::Accessor::Classy         Class::Accessor
Object::InsideOut         fields
                                  Hash::Fi...
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 ...
What is Moose?
• (Post)modern Perl OO framework
• Deals with the overhead of implementing
  OO, allows you to get on with ...
What is Moose?
• (Post)modern Perl OO framework
• Deals with the overhead of implementing
  OO, allows you to get on with ...
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->na...
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 => 'n...
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 S...
Types (3)
package Person;
use Moose;

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

has dob => (
    is => 'rw',
    isa => '...
Types (4)
use Person;
my $person = Person->new(
   { name => 'Mike' }
);
my $dob = DateTime->new (
   year => 1963, month ...
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'...
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',
...
Lazy default
has 'overdraft' => (
    isa => 'Bool',
    is => 'ro',
    lazy => 1,
    default => sub {
      shift->acco...
Lazy builder
has 'overdraft' => (
    isa => 'Bool',
    is => 'ro',
    lazy_build => 1,
    init_arg => undef,
);
sub _b...
Method modifiers
package Student;
# yadda yadda

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

$person->introd...
Method modifiers (2)
package Student;
# yadda yadda

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

$person->in...
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
  con...
Roles
• Code fragments that define and provide a
  small, reusable behaviour
• Not inherited - methods become part of
  con...
Roles
• Code fragments that define and provide a
  small, reusable behaviour
• Not inherited - methods become part of
  con...
Example role
package Age;
use Moose::Role;
has dob => (
    isa => 'DateTime', is =>'ro'
);
sub age {
    return DateTime-...
Using a role
package Person;
use Moose;
with qw/Age/;
has name => ( isa => 'Str', is => 'ro');

sub introduce {
    print ...
Using a role (2)
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => ... # yadda yadda
    course => 'C...
What we'd really like
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => '05-08-1963',
    course => '...
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-d...
Types to the rescue (2)
use Moose::Util::TypeConstraints;
class_type 'DateTime';

coerce 'DateTime' => from 'Str'
   => vi...
And then...
package Age;
use Moose::Role;
has dob => (
    isa => 'DateTime',
    is =>'ro',
    coerce => 1, # very impor...
Et voila...
use Student;
my $person = Student->new(
    name => 'Mike',
    dob => '05-08-1963',
    course => 'CS',
);

p...
Roles as interfaces
package Earnings;
use Moose::Role;

requires qw/annual_income/;

sub monthly_income {
    return shift...
Roles as interfaces (2)
package Person;
with qw/Earnings/;

package Student;
extends qw/Person/;

sub annual_income {
   m...
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 Delegation
package Degree;
use Moose;
use Moose::Utils::TypeConstraints;
enum 'Grade' => qw/I IIi IIii III/;


has ...
Method Delegation (2)
package Graduate;
use Moose;
extends qw/Student/;

has 'degree' => (
   isa => 'Degree',
   is => 'r...
Method Delegation (3)
my $g = Graduate->new(name => 'Mike');
my $d = Degree->new(
    awarded => '06-06-1985',
    grade =...
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 =...
More on attributes
package Student;
use MooseX::Util::TypeConstraints;
use Moose;
extends qw/Person/;
enum 'Result' => qw/...
Attribute Helpers
my $st = Student->new( name => 'Mike' );

$st->classes(
    { "Compilers" => 'fail',
     "Numerical Met...
Attribute Helpers (2)
use MooseX::AttributeHelpers;
has classes => (
    metaclass => 'Collection::Hash',
    isa => 'Hash...
Attribute Helpers (3)
my $st = Student->new( name => 'Mike' );

$st->classes(
    { "Compilers" => 'fail',
      "Numerica...
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...
Introspecting Moose
• my $metaclass = $self->meta;

• $metaclass->superclasses;
• $metaclass->linearized_isa;
• $metaclass...
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: M...
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) {
 ...
Even more Java-like?
use MooseX::Declare;

class Student extends Person with
Earnings {
   has 'id' => ( isa => 'StudentID...
How is this
implemented?
Lasciate ogne
  speranza,
voi ch'intrate
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
...
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 ...
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
 • "We do this so ...
Why Moose?
• Less code = fewer errors
• Don't waste time on class implementation
 • Better object model
 • "We do this so ...
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/...
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:SQL...
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::Gener...
Complex Example (5)
has _row => {
    isa => 'DBIx::Class::Row',
    lazy_build => 1,
}
sub _build__row {
    return shift...
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 happe...
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 _schem...
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row

• which requires _schem...
What happens?
•   address method is handled by _row

•   _row is lazy_build, so calls _build__row

• which requires _schem...
But...
# What if the student's ID changes?

has 'id' => (
    isa => 'StudentID',
    is => 'rw',
    trigger => '_build__...
Introduction To Moose
Introduction To Moose
Introduction To Moose
Introduction To Moose
Upcoming SlideShare
Loading in...5
×

Introduction To Moose

7,540

Published on

Introduction to Moose talk given at Italian Perl Workshop 2009.

Video at http://www.shadowcat.co.uk/archive/conference-video/ipw-2009/moose/

Published in: Technology
1 Comment
12 Likes
Statistics
Notes
  • This looks good. The only problem is the downloading. The downloaded file is in .key format, which I have no way to view it in Windows. Any other formats?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
7,540
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
281
Comments
1
Likes
12
Embeds 0
No embeds

No notes for slide
  • Introduction To Moose

    1. 1. Introduction to Moose Italian Perl Workshop 2009 Mike Whitaker - BBC / EnlightenedPerl.org
    2. 2. About me
    3. 3. About me • BBC iPlayer team
    4. 4. About me • BBC iPlayer team • ex-Yahoo Europe (News team)
    5. 5. About me • BBC iPlayer team • ex-Yahoo Europe (News team) • ex-CricInfo.com
    6. 6. About me • BBC iPlayer team • ex-Yahoo Europe (News team) • ex-CricInfo.com • Board member of EnlightenedPerl.org
    7. 7. Why Moose?
    8. 8. Why Moose? • For that, we need a bit of history:
    9. 9. In the Beginning...
    10. 10. In the Beginning... • ...there was Perl 5
    11. 11. In the Beginning... • ...there was Perl 5 • DIY OO
    12. 12. In the Beginning... • ...there was Perl 5 • DIY OO • perldoc perltoot
    13. 13. In the Beginning... • ...there was Perl 5 • DIY OO • perldoc perltoot package Foo; sub new { my $self = {}; return bless $self; }
    14. 14. 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}; } } }
    15. 15. Perl 5 Native OO
    16. 16. Perl 5 Native OO • A bit of a hack
    17. 17. Perl 5 Native OO • A bit of a hack • Not really a first-class part of the language
    18. 18. Perl 5 Native OO • A bit of a hack • Not really a first-class part of the language • Have to roll your own
    19. 19. So... People started writing classes to make it easier....
    20. 20. 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
    21. 21. Moose
    22. 22. What is Moose?
    23. 23. What is Moose? • (Post)modern Perl OO framework
    24. 24. What is Moose? • (Post)modern Perl OO framework • Deals with the overhead of implementing OO, allows you to get on with coding
    25. 25. 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
    26. 26. 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
    27. 27. My First Class package Person; use Moose; has name => ( is => 'rw', ); no Moose;
    28. 28. Using the class use Person; my $person = Person->new(); $person->name('Mike'); print $person->name(); > Mike
    29. 29. Adding a method package Person; use Moose; has name => ( is => 'rw' ); sub introduce { print "I'm " . $self->name; }
    30. 30. Using it use Person; my $person = Person->new(); $person->name('Mike'); $person->introduce(); > I'm Mike
    31. 31. Read-only attributes package Person; use Moose; has name => ( is => 'ro' ); sub introduce { print "I'm " . $self->name; }
    32. 32. Read-only attributes (2) use Person; my $person = Person->new(); $person->name('Mike'); # boom!
    33. 33. Read-only attributes (3) use Person; my $person = Person->new( { name => 'Mike' }, ); # no boom today!
    34. 34. Changing defaults has 'name' => ( isa => 'Str', reader => 'get_name', writer => 'set_name', init_arg => 'name', required => 1, );
    35. 35. Types package Person; use Moose; has name => ( is => 'rw', isa => 'Str', );
    36. 36. Types (2) use Person; my $person = Person->new(); $person->name('Mike'); # shiny! $person->name( [] ); # boom! # Not a Str
    37. 37. Types (3) package Person; use Moose; has name => ( is => 'rw', isa => 'Str' ); has dob => ( is => 'rw', isa => 'DateTime', );
    38. 38. 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
    39. 39. Subclassing package Student; use Moose; extends qw/Person/; has overdraft => ( isa => 'Bool', is => 'rw', );
    40. 40. Compound Types package Student; use Moose; extends qw/Person/; has classes => ( isa => 'HashRef[Str]', is => 'rw', );
    41. 41. Required attributes package Student; use Moose; extends qw/Person/; # ... has course => ( isa => 'Str', is => 'ro', required => 1, );
    42. 42. Setting defaults package Student; use Moose; has 'overdraft' => ( isa => 'Bool', default => 1, );
    43. 43. But, what if... package BankAccount; sub balance { # yadda yadda }
    44. 44. And then... package Student; use Moose; extends qw/Person/; has 'account' => ( isa => 'BankAccount', is => 'rw', required => 1, );
    45. 45. Lazy default has 'overdraft' => ( isa => 'Bool', is => 'ro', lazy => 1, default => sub { shift->account->balance < 0; } );
    46. 46. Lazy builder has 'overdraft' => ( isa => 'Bool', is => 'ro', lazy_build => 1, init_arg => undef, ); sub _build_overdraft { return shift->account->balance < 0; }
    47. 47. Method modifiers package Student; # yadda yadda after 'introduce' => sub { my $self = shift; print ', studying ' . $self->course; }
    48. 48. Using it use Student; my $person = Student->new( name => 'Mike', course => 'Computer Science', ); $person->introduce(); > I'm Mike, studying Computer Science
    49. 49. Method modifiers (2) package Student; # yadda yadda around 'introduce' => sub { my ($next, $self, @args) = @_; print "Hi, "; $self->$next(@args); print ', studying ' . $self->course; }
    50. 50. Using around use Student; my $person = Student->new( name => 'Mike', course => 'Computer Science', ); $person->introduce(); > Hi, I'm Mike, studying Computer Science
    51. 51. Roles
    52. 52. Roles • Code fragments that define and provide a small, reusable behaviour
    53. 53. Roles • Code fragments that define and provide a small, reusable behaviour • Not inherited - methods become part of consuming class
    54. 54. 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
    55. 55. 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!
    56. 56. Example role package Age; use Moose::Role; has dob => ( isa => 'DateTime', is =>'ro' ); sub age { return DateTime->now ->subtract( shift->dob() ) ->years; }
    57. 57. 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; }
    58. 58. 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
    59. 59. What we'd really like use Student; my $person = Student->new( name => 'Mike', dob => '05-08-1963', course => 'CS', );
    60. 60. Redefine our attr... package Age; use Moose::Role; has dob => ( isa => 'DateStr', is =>'ro', );
    61. 61. Types to the rescue use Moose::Util::TypeConstraints; subtype 'DateStr' => as 'Str' => where { /^dd-dd-dddd$/ };
    62. 62. 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 ); };
    63. 63. And then... package Age; use Moose::Role; has dob => ( isa => 'DateTime', is =>'ro', coerce => 1, # very important! );
    64. 64. Et voila... use Student; my $person = Student->new( name => 'Mike', dob => '05-08-1963', course => 'CS', ); print $person->age(); > 45
    65. 65. Roles as interfaces package Earnings; use Moose::Role; requires qw/annual_income/; sub monthly_income { return shift->annual_income / 12; }
    66. 66. Roles as interfaces (2) package Person; with qw/Earnings/; package Student; extends qw/Person/; sub annual_income { my $self = shift; return $self->grant_amount; }
    67. 67. Role gotchas
    68. 68. Role gotchas • Roles cannot use extends
    69. 69. Role gotchas • Roles cannot use extends • requires only works with actual methods :(
    70. 70. Role gotchas • Roles cannot use extends • requires only works with actual methods :( • for now, at least
    71. 71. Role gotchas • Roles cannot use extends • requires only works with actual methods :( • for now, at least • watch out for method and attribute conflicts
    72. 72. 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, );
    73. 73. Method Delegation (2) package Graduate; use Moose; extends qw/Student/; has 'degree' => ( isa => 'Degree', is => 'rw', );
    74. 74. 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
    75. 75. Method Delegation (4) has 'degree' => ( isa => 'Degree', is => 'rw', handles => { graduated => 'awarded' }, );
    76. 76. 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
    77. 77. 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', );
    78. 78. Attribute Helpers my $st = Student->new( name => 'Mike' ); $st->classes( { "Compilers" => 'fail', "Numerical Methods" => 'pass' } ); %{$st->classes}->{"Lisp"} = "pass";
    79. 79. Attribute Helpers (2) use MooseX::AttributeHelpers; has classes => ( metaclass => 'Collection::Hash', isa => 'HashRef[Result]', is => 'rw', provides => { set => 'add_class', keys => 'list_classes', } )
    80. 80. 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
    81. 81. Introspecting Moose
    82. 82. Introspecting Moose • my $metaclass = $self->meta;
    83. 83. Introspecting Moose • my $metaclass = $self->meta;
    84. 84. Introspecting Moose • my $metaclass = $self->meta; • $metaclass->superclasses;
    85. 85. Introspecting Moose • my $metaclass = $self->meta; • $metaclass->superclasses; • $metaclass->linearized_isa;
    86. 86. Introspecting Moose • my $metaclass = $self->meta; • $metaclass->superclasses; • $metaclass->linearized_isa; • $metaclass->has_method("foo");
    87. 87. Introspecting Moose • my $metaclass = $self->meta; • $metaclass->superclasses; • $metaclass->linearized_isa; • $metaclass->has_method("foo"); • $metaclass->get_all_attributes;
    88. 88. Method Signatures
    89. 89. Method Signatures • We have types...
    90. 90. Method Signatures • We have types... • Wouldn't it be nice if types weren't restricted to attrs + accessors?
    91. 91. Method Signatures • We have types... • Wouldn't it be nice if types weren't restricted to attrs + accessors? • Enter: MooseX::Method::Signature
    92. 92. Method Signatures package Student; use Moose; use MooseX::Method::Signatures; method attend (Str $class, DateTime $time) { # ... }
    93. 93. Method Signatures (2) method attend (Str $class, DateTime $time) { if (grep $class, $self->list_classes) { $self->schedule($time, $class); } }
    94. 94. Even more Java-like? use MooseX::Declare; class Student extends Person with Earnings { has 'id' => ( isa => 'StudentID' ); method attend ( Str $class, ... ) { # yadda yadda } }
    95. 95. How is this implemented?
    96. 96. Lasciate ogne speranza, voi ch'intrate
    97. 97. But seriously...
    98. 98. But seriously... • Devel::Declare sticks the interpreter on pause while it plays with your source
    99. 99. But seriously... • Devel::Declare sticks the interpreter on pause while it plays with your source • NOT a source filter
    100. 100. 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...
    101. 101. Why Moose?
    102. 102. Why Moose? • Less code = fewer errors
    103. 103. Why Moose? • Less code = fewer errors • Don't waste time on class implementation
    104. 104. Why Moose? • Less code = fewer errors • Don't waste time on class implementation • Better object model
    105. 105. 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"
    106. 106. 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
    107. 107. 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
    108. 108. Further Reading
    109. 109. Further Reading • http://iinteractive.com/moose/
    110. 110. Further Reading • http://iinteractive.com/moose/ • Moose::Cookbook (CPAN)
    111. 111. Further Reading • http://iinteractive.com/moose/ • Moose::Cookbook (CPAN) • http://www.stonehenge.com/merlyn/ LinuxMag/col94.html
    112. 112. Complex Example package Student; use Moose; # yadda has 'id' => ( isa => 'StudentID', is => 'rw', );
    113. 113. 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', );
    114. 114. Complex Example (3) sub _build__schema { my $self = shift; return Person::Schema->connect( $self->db ); }
    115. 115. 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}; };
    116. 116. Complex Example (5) has _row => { isa => 'DBIx::Class::Row', lazy_build => 1, } sub _build__row { return shift->_schema ->resultset('Student') ->find($self->id); }
    117. 117. Complex Example (6) has _row => { isa => 'DBIx::Class::Row', lazy_build => 1, handles => [qw/address gender/], }
    118. 118. Complex Example (7) my $student = Student->new( name => 'Mike', id => '3056', ); print $st->address(); # What happens here?
    119. 119. What happens?
    120. 120. What happens? • address method is handled by _row
    121. 121. What happens? • address method is handled by _row • _row is lazy_build, so calls _build__row
    122. 122. What happens? • address method is handled by _row • _row is lazy_build, so calls _build__row • which requires _schema, ALSO lazy_build
    123. 123. 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
    124. 124. 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!
    125. 125. But... # What if the student's ID changes? has 'id' => ( isa => 'StudentID', is => 'rw', trigger => '_build__row', );
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×