Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Intro to MOP (presented at YAPC::NA)

Intro to MOP (presented at YAPC::NA)

Upasana

June 22, 2016
Tweet

More Decks by Upasana

Other Decks in Programming

Transcript

  1. Meta Object Protocol
    (MOP)
    Upasana
    [email protected]

    View Slide

  2. About me

    Software developer at booking.com

    View Slide

  3. We are hiring
    https://workingatbooking.com/

    View Slide

  4. Backstory

    GNOME Outreach Program for Women
    internship in 2013

    Structured exceptions in Moose

    Want to share whatever I learnt during my
    internship

    View Slide

  5. Topics
    1) Little bit about object oriented programming (OOP)
    2) Little bit about OOP in perl (the old style)
    3) Meta object protocol (MOP)
    4) History of MOP
    5) Applications of MOP

    View Slide

  6. Topics
    6) Implementing MOP in Perl (the easy way)
    7) Why #6 might not be a good idea
    8) Metaclass incompatibility
    9) Mixins
    10) MOP in Moose
    11) Drawbacks of MOP
    12) Where to go next?

    View Slide

  7. How a class looks like?

    Class name

    Superclasses

    View Slide

  8. How a class looks like?

    Attributes
    – is read only or read-write
    – type (int, float etc.)
    – default value if any
    – getter method (accessor)
    – setter method (mutator)

    View Slide

  9. How a class looks like?

    Methods
    – method name
    – body

    View Slide

  10. Classes in Perl

    Perl doesn't provide any special syntax for
    classes

    Perl packages are classes

    View Slide

  11. Attributes in Perl classes

    No special syntax or support for declaring and
    manipulating attributes

    Attributes are stored in the object itself

    As a hash of key-value pairs

    View Slide

  12. Object?

    A hash reference

    blessed into a class

    View Slide

  13. OOP in Perl
    package Rectangle;
    sub new {
    my $self = shift;
    my $attributes = { @_ };
    bless $attributes, $self;
    }
    Rectangle->new(
    height => 10,
    width => 20,
    );

    View Slide

  14. OOP in Perl
    package Rectangle;
    sub new {
    my $self = shift;
    my $attributes = { @_ };
    bless $attributes, $self;
    }
    Rectangle->new(
    height => 10,
    width => 20,
    );

    View Slide

  15. OOP in Perl
    package Rectangle;
    sub new {
    my $self = shift;
    my $attributes = { @_ };
    bless $attributes, $self;
    }
    Rectangle->new(
    height => 10,
    width => 20,
    );

    View Slide

  16. OOP in Perl
    package Rectangle;
    sub new {
    my $self = shift;
    my $attributes = { @_ };
    bless $attributes, $self;
    }
    Rectangle->new(
    height => 10,
    width => 20,
    );

    View Slide

  17. OOP in Perl
    package Rectangle;
    sub new {
    my $self = shift;
    my $attributes = { @_ };
    bless $attributes, $self;
    }
    Rectangle->new(
    height => 10,
    width => 20,
    );

    View Slide

  18. OOP in Perl
    package Rectangle;
    sub new {
    my $self = shift;
    my $attributes = { @_ };
    bless $attributes, $self;
    }
    Rectangle->new(
    height => 10,
    width => 20,
    );

    View Slide

  19. OOP in Perl
    package Rectangle;
    sub new {
    my $self = shift;
    my $attributes = { @_ };
    bless $attributes, $self;
    }
    Rectangle->new(
    height => 10,
    width => 20,
    );

    View Slide

  20. What is MOP?

    provides the vocabulary to access and
    manipulate the structure and behavior of
    objects.

    View Slide

  21. Functions of MOP

    Creating new classes

    Deleting existing classes

    Changing the class structure

    Changing methods of the class

    At runtime

    View Slide

  22. History of MOP

    First introduced in the Smalltalk

    Common LISP Object System (CLOS) was
    influenced by Smalltalk

    CLOS allowed multiple inheritance unlike
    Smalltalk

    View Slide

  23. MOP in modern languages

    Javascript has Joose

    OpenC++

    Java has Reflection API

    Perl has Moose

    View Slide

  24. Why do we need a MOP?

    View Slide

  25. Testing

    View Slide

  26. Testing

    I work at booking.com

    Our website is moving very fast

    Many rollouts in a day

    View Slide

  27. Testing

    We don't test everything

    At one point, rollouts became hard

    Some things need to be tested manually

    View Slide

  28. Testing
    package Web::Handler {
    has 'search' => (
    url => '/search', #...
    );
    has 'hotel' => (
    url => '/hotel', #...
    );
    # ...
    }

    View Slide

  29. Testing
    package Web::Handler {
    has 'search' => (
    url => '/search', #...
    );
    has 'hotel' => (
    url => '/hotel', #...
    );
    # ...
    }

    View Slide

  30. Testing
    package Web::Handler {
    has 'search' => (
    url => '/search', #...
    );
    has 'hotel' => (
    url => '/hotel', #...
    );
    # ...
    }

    View Slide

  31. Testing

    Give me all the attributes of Web::Handler.

    Run tests for all the attributes.

    View Slide

  32. Testing
    # This is pseudocode, don't expect this
    # to compile
    my $attr =
    Web::Handler->meta->get_attributes_list;
    foreach my $a ( @$attr ) {
    next unless $a->attribute_exists('url');
    my $url = $a->get_attribute('url');
    die “test fails...\n”
    if( !LWP::Simple::get($url) );
    }

    View Slide

  33. Testing
    # This is pseudocode, don't expect this
    # to compile
    my $attr =
    Web::Handler->meta->get_attributes_list;
    foreach my $a ( @$attr ) {
    next unless $a->attribute_exists('url');
    my $url = $a->get_attribute('url');
    die “test fails...\n”
    if( !LWP::Simple::get($url) );
    }

    View Slide

  34. Testing
    # don't expect this to compile
    my $attr =
    Web::Handler->meta->get_attributes_list;
    foreach my $a ( @$attr ) {
    next unless $a->attribute_exists('url');
    my $url = $a->get_attribute('url');
    die “test fails...\n”
    if( !LWP::Simple::get($url) );
    }

    View Slide

  35. Testing
    # don't expect this to compile
    my $attr =
    Web::Handler->meta->get_attributes_list;
    foreach my $a ( @$attr ) {
    next unless $a->attribute_exists('url');
    my $url = $a->get_attribute('url');
    die “test fails...\n”
    if( !LWP::Simple::get($url) );
    }

    View Slide

  36. Testing
    # don't expect this to compile
    my $attr =
    Web::Handler->meta->get_attributes_list;
    foreach my $a ( @$attr ) {
    next unless $a->attribute_exists('url');
    my $url = $a->get_attribute('url');
    die “test fails...\n”
    if( !LWP::Simple::get($url) );
    }

    View Slide

  37. Testing
    # don't expect this to compile
    my $attr =
    Web::Handler->meta->get_attributes_list;
    foreach my $a ( @$attr ) {
    next unless $a->attribute_exists('url');
    my $url = $a->get_attribute('url');
    die “test fails...\n”
    if( !LWP::Simple::get($url) );
    }

    View Slide

  38. Object Relational Mapping
    (ORM)

    View Slide

  39. ORM
    my $create_table_statement =<CREATE TABLE Hotel (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    address VARCHAR(255)
    );
    END

    View Slide

  40. ORM
    my $sql_parser =
    SQL::Parser->new( $create_table_statement );
    my $class_name = $sql_parser->table_name;
    my $c =
    Moose::Meta::Class->create( $class_name );

    View Slide

  41. ORM
    my $sql_parser =
    SQL::Parser->new( $create_table_statement );
    my $class_name = $sql_parser->table_name;
    my $c =
    Moose::Meta::Class->create( $class_name );

    View Slide

  42. ORM
    my $sql_parser =
    SQL::Parser->new( $create_table_statement );
    my $class_name = $sql_parser->table_name;
    my $c =
    Moose::Meta::Class->create( $class_name );

    View Slide

  43. ORM
    my $sql_parser =
    SQL::Parser->new( $create_table_statement );
    my $class_name = $sql_parser->table_name;
    my $c =
    Moose::Meta::Class->create( $class_name );

    View Slide

  44. ORM
    foreach my $f ( $sql_parser->fields ) {
    my $tc = find_type_constraint( $f->type );
    $c->add_attribute(
    Moose::Meta::Attribute->new(
    $f->name,
    isa => $tc,
    reader => 'get_' . $f->name,
    writer => 'set_' . $f->name,
    );
    );
    }

    View Slide

  45. ORM
    foreach my $f ( $sql_parser->fields ) {
    my $tc = find_type_constraint( $f->type );
    $c->add_attribute(
    Moose::Meta::Attribute->new(
    $f->name,
    isa => $tc,
    reader => 'get_' . $f->name,
    writer => 'set_' . $f->name,
    );
    );
    }

    View Slide

  46. ORM
    foreach my $f ( $sql_parser->fields ) {
    my $tc = find_type_constraint( $f->type );
    $c->add_attribute(
    Moose::Meta::Attribute->new(
    $f->name,
    isa => $tc,
    reader => 'get_' . $f->name,
    writer => 'set_' . $f->name,
    );
    );
    }

    View Slide

  47. ORM
    foreach my $f ( $sql_parser->fields ) {
    my $tc = find_type_constraint( $f->type );
    $c->add_attribute(
    Moose::Meta::Attribute->new(
    $f->name,
    isa => $tc,
    reader => 'get_' . $f->name,
    writer => 'set_' . $f->name,
    );
    );
    }

    View Slide

  48. ORM
    foreach my $f ( $sql_parser->fields ) {
    my $tc = find_type_constraint( $f->type );
    $c->add_attribute(
    Moose::Meta::Attribute->new(
    $f->name,
    isa => $tc,
    reader => 'get_' . $f->name,
    writer => 'set_' . $f->name,
    );
    );
    }

    View Slide

  49. ORM
    foreach my $f ( $sql_parser->fields ) {
    my $tc = find_type_constraint( $f->type );
    $c->add_attribute(
    Moose::Meta::Attribute->new(
    $f->name,
    isa => $tc,
    reader => 'get_' . $f->name,
    writer => 'set_' . $f->name,
    );
    );
    }

    View Slide

  50. ORM
    foreach my $f ( $sql_parser->fields ) {
    my $tc = find_type_constraint( $f->type );
    $c->add_attribute(
    Moose::Meta::Attribute->new(
    $f->name,
    isa => $tc,
    reader => 'get_' . $f->name,
    writer => 'set_' . $f->name,
    );
    );
    }

    View Slide

  51. ORM
    package SomeDB::Class::Thing;
    .....
    sub retrieve { .... }
    sub search_where {....}
    1;
    $c->set_superclass( 'SomeDB::Class::Thing' );

    View Slide

  52. ORM
    # return me the hotel with id 123
    my $h = Hotel->retrieve( 123 );
    my $hotel_name = $h->name;
    $h->set_name( 'asdfasdf' );

    View Slide

  53. ORM
    # return me the hotel with id 123
    my $h = Hotel->retrieve( 123 ); #
    return me the hotel id 123
    my $hotel_name = $h->name;
    $h->set_name( 'asdfasdf' );

    View Slide

  54. ORM
    # return me the hotel with id 123
    my $h = Hotel->retrieve( 123 ); #
    return me the hotel id 123
    my $hotel_name = $h->name;
    $h->set_name( 'asdfasdf' );

    View Slide

  55. Implementing MOP in Perl

    View Slide

  56. Creating a class at runtime

    Perl class is a package

    Every package has a symbol table

    View Slide

  57. Symbol table

    Hash of subroutines/variables defined in a
    package

    package name with two colons appended
    $Rectangle::

    View Slide

  58. Symbol table

    Hash of subroutines/variables defined in a
    package

    package name with two colons appended
    $Rectangle::

    View Slide

  59. package Metaclass;
    sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }
    1;

    View Slide

  60. package Metaclass;
    sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }
    1;

    View Slide

  61. package Metaclass;
    sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }
    1;

    View Slide

  62. package Metaclass;
    sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }
    1;

    View Slide

  63. package Metaclass;
    sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }
    1;

    View Slide

  64. package Metaclass;
    sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }
    1;

    View Slide

  65. package Metaclass;
    sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }
    1;

    View Slide

  66. package Metaclass;
    sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }
    1;

    View Slide

  67. Metaclass->create_class(
    package => 'Rectangle',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    }
    );
    Rectangle->new(
    height => 10,
    Width => 20
    );

    View Slide

  68. Metaclass->create_class(
    package => 'Rectangle',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    }
    );
    Rectangle->new(
    height => 10,
    Width => 20
    );

    View Slide

  69. Metaclass->create_class(
    package => 'Rectangle',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    }
    );
    Rectangle->new(
    height => 10,
    Width => 20
    );

    View Slide

  70. Metaclass->create_class(
    package => 'Rectangle',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    }
    );
    Rectangle->new(
    height => 10,
    Width => 20
    );

    View Slide

  71. Metaclass->create_class(
    package => 'Rectangle',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    }
    );
    Rectangle->new(
    height => 10,
    Width => 20
    );

    View Slide

  72. sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    $options{ methods }->{ meta } = \&get_meta;
    my $methods = $options{ methods };
    while( my ($method, $body) = each( %$methods ) ) {
    no strict 'refs';
    *{ "${class}::$method" } = $body;
    } # end while loop
    }

    View Slide

  73. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }

    View Slide

  74. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }

    View Slide

  75. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }

    View Slide

  76. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }

    View Slide

  77. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }

    View Slide

  78. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }

    View Slide

  79. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }

    View Slide

  80. sub create_class {
    my ($self, %options) = @_;
    my $class = $options{ package };
    $options{ methods }->{ meta } = \&get_meta;
    my $methods = $options{ methods };
    no strict 'refs';
    while( my ($method, $body) = each( %$methods ) ) {
    *{ "${class}::$method" } = $body;
    } # end while loop
    use strict;
    set_metaclass( $class, \%options );
    }

    View Slide

  81. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }
    sub set_metaclass {
    $meta_to_class{ $_[ 0 ] } = $_[ 1 ];
    }

    View Slide

  82. my %meta_to_class;
    sub get_meta {
    my $class = shift;
    Metaclass->get_metaclass( $class );
    };
    sub get_metaclass {
    my $class = shift;
    return bless $meta_to_class{ $_[ 0 ] }, $class;
    }
    sub set_metaclass {
    $meta_to_class{ $_[ 0 ] } = $_[ 1 ];
    }

    View Slide

  83. Introspection
    Metaclass->create_class(
    package => 'Rectangle',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    },
    );
    print Dumper( Rectangle->meta );

    View Slide

  84. bless({
    'package' => 'Rectangle',
    'methods' => {
    'meta' => sub { "DUMMY" },
    'new' => sub { "DUMMY" }
    }
    }, 'Metaclass' );

    View Slide

  85. bless({
    'package' => 'Rectangle',
    'methods' => {
    'meta' => sub { "DUMMY" },
    'new' => sub { "DUMMY" }
    }
    }, 'Metaclass' );

    View Slide

  86. Inheritance

    Every package's symbol table has an array
    named ISA

    @PackageName::ISA

    View Slide

  87. Inheritance
    if( $options{ superclasses } && @{$options{ superclasses }} )
    {
    @{"${class}::ISA"} = @{$options{ superclasses }}
    }

    View Slide

  88. Inheritance
    if( $options{ superclasses } && @{$options{ superclasses }} )
    {
    @{"${class}::ISA"} = @{$options{ superclasses }};
    }

    View Slide

  89. Metaclass->create_class(
    package => 'ColoredRectangle',
    superclasses => [ 'Rectangle' ],
    );

    View Slide

  90. Metaclass->create_class(
    package => 'ColoredRectangle',
    superclasses => [ 'Rectangle' ],
    );

    View Slide

  91. And it works, I can do
    ColoredRectangle->new();

    View Slide

  92. But please don't try aforementioned
    things

    View Slide

  93. It's incomplete & may be fragile

    View Slide

  94. But why?

    View Slide

  95. “Manipulating stashes (Perl's symbol tables) is
    occasionally necessary, but incredibly messy,
    and easy to get wrong. This module hides all of
    that behind a simple API.”
    `man Package::Stash`

    View Slide

  96. But why?

    use Package::Stash;

    use Symbol::Table;

    View Slide

  97. But why?

    Metaclass.pm is very basic

    But actually Metaclasses are not so simple

    Look at Moose

    View Slide

  98. Moose

    Metaclasses for attributes

    Metaclasses for methods

    View Slide

  99. Inheritance & metaclass compatibility

    A has a method i-foo
    – Calls c-bar of
    MetaA

    B inherits from A
    – B has i-foo

    MetaB may not have
    c-bar

    View Slide

  100. Inheritance & metaclass compatibility
    package MetaA;
    ....
    sub c_bar {
    print "in c_bar\n";
    }
    1;

    View Slide

  101. Inheritance & metaclass compatibility
    MetaA->create_class(
    package => 'A',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    i_foo => sub {
    my ($self) = shift;
    my $meta = $self->meta;
    $meta->c_bar;
    },
    },
    );
    A->i_foo();

    View Slide

  102. Inheritance & metaclass incompatibility
    MetaB->create_class(
    package => 'B',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    },
    superclasses => [ 'A' ],
    );
    B->i_foo;

    View Slide

  103. Inheritance & metaclass incompatibility
    Can't locate object method "c_bar" via package
    "MetaB" at test.pl line 24.

    View Slide

  104. Inheritance & metaclass incompatibility
    i_foo => sub {
    my ($self) = shift;
    my $meta = $self->meta;
    $meta->c_bar;
    },

    View Slide

  105. Inheritance & metaclass incompatibility
    package MetaB;
    ....
    # NO c_bar
    1;

    View Slide

  106. Inheritance & metaclass incompatibility

    MetaA has a method
    c-foo

    c-foo needs to call i-
    bar in A

    MetaB inherits from
    MetaA

    B has to has i-bar

    View Slide

  107. Inheritance & metaclass incompatibility
    package MetaA;
    .....
    sub c_foo {
    my ( $self, $child ) = @_;
    $child->i_bar;
    }
    1;

    View Slide

  108. Inheritance & metaclass incompatibility
    package MetaB;
    use strict;
    use warnings;
    use parent 'MetaA';
    1;

    View Slide

  109. Inheritance & metaclass incompatibility
    MetaA->create_class(
    package => 'A',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    i_bar => sub {
    print "in i_bar\n";
    },
    },
    );
    MetaA->c_foo( 'A' );

    View Slide

  110. Inheritance & metaclass incompatibility
    MetaB->create_class(
    package => 'B',
    methods => {
    new => sub {
    my ($self) = shift;
    my $attributes = { @_ };
    return bless $attributes, $self;
    },
    # NO i_bar
    },
    );
    MetaB->c_foo( 'B' );

    View Slide

  111. Inheritance & metaclass incompatibility
    Can't locate object method "i_bar" via package
    "B" at MetaA.pm line 16.

    View Slide

  112. Inheritance & metaclass compatibility
    sub c_foo {
    my ( $self, $child ) = @_;
    $child->i_bar;
    }

    View Slide

  113. Metaclass Incompatibility

    Various ways of dealing with this

    View Slide

  114. Metaclass compatibility (Moose)

    Does parent & child metaclasses have any
    common ancestors?
    – If yes, then \o/
    – else, die

    Moose::Exception::CannotFixMetaclassComp
    atibility

    View Slide

  115. Mixins

    A class that contains a combination of
    methods from other classes

    'Included' rather than 'inherited'

    Moose roles are similar to mixins

    View Slide

  116. Rules of mixins-based inheritance

    Order of the mixins matter

    Mixins take precedence over non-mixins

    View Slide

  117. Mixins-based inheritance

    View Slide

  118. Mixins-based inheritance

    B => {M1.M2.A}

    View Slide

  119. Rules of mixins-based inheritance

    Methods in M2 will take precedence over A

    Methods in M1 will take precedence over M2

    View Slide

  120. Mixins-based inheritance

    C => { M3.B.M1.M2.A }

    View Slide

  121. Rules of mixins-based inheritance

    Methods in B will take precedence over M1

    Methods in M3 will take precedence over B

    View Slide

  122. Moose provides a great MOP

    View Slide

  123. Creating a class
    Moose::Meta::Class->create(
    'Rectangle',
    attributes => {
    'height' => {
    is => 'ro',
    isa => 'Int',
    },
    ...
    },
    );

    View Slide

  124. Introspection

    For getting attributes:
    Rectangle->meta->get_attributes_list();

    For getting methods:
    Rectangle->meta->get_methods_list();

    For getting superclasses:
    Rectangle->meta->superclasses;

    View Slide

  125. Introspection

    For getting attributes:
    Rectangle->meta->get_attributes_list();

    For getting methods:
    Rectangle->meta->get_methods_list();

    For getting superclasses:
    Rectangle->meta->superclasses;

    View Slide

  126. Introspection

    For getting attributes:
    Rectangle->meta->get_attributes_list();

    For getting methods:
    Rectangle->meta->get_methods_list();

    For getting superclasses:
    Rectangle->meta->superclasses;

    View Slide

  127. Introspection

    For getting attributes:
    Rectangle->meta->get_attributes_list();

    For getting methods:
    Rectangle->meta->get_methods_list();

    For getting superclasses:
    Rectangle->meta->superclasses;

    View Slide

  128. Changing Class definition

    For adding a new attribute:
    Rectangle->meta->add_attribute(...);

    For adding a new method:
    Rectangle->meta->add_method(...);

    View Slide

  129. Changing Class definition

    For adding a new attribute:
    Rectangle->meta->add_attribute(...);

    For adding a new method:
    Rectangle->meta->add_method(...);

    View Slide

  130. Changing Class definition

    For adding a new attribute:
    Rectangle->meta->add_attribute(...);

    For adding a new method:
    Rectangle->meta->add_method(...);

    View Slide

  131. Drawbacks of MOP

    Makes things slow

    While using Moose, don't forget to do:
    __PACKAGE__->meta->make_immutable;
    – It tells Moose that you are not going to change
    your class at runtime

    View Slide

  132. Bibliography

    The Art of the Metaobject Protocol

    Metaclass Composition Using Mixin-Based
    Inheritance by Noury Bouraqadi

    Wikipedia

    Moose documentation

    And lots of other random resources on the
    internet

    Stevan Little's awesome brain :)

    View Slide

  133. Thank you for your time

    View Slide

  134. Questions?

    View Slide


  135. Slides:
    https://speakerdeck.com/upasana20/intro-to-mop-presented-a
    t-yapc-na

    Code examples:
    https://github.com/Sweet-kid/Intro-to-MOP-YAPC

    View Slide