Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Extending Moose
 for Applications
  Shawn M Moore
  Best Practical Solutions


              1
Twitter!

@sartak Hey wait, what is "meta"?




                2
(or IRC)



   3
Extending Moose for
    Applications




         4
Domain-specific
Metaprogramming




       5
Extending Moose for
    Applications

  Domain-specific
 Metaprogramming



         6
Extending Moose for
    Applications

  Domain-specific
 Metaprogramming



         7
Extending Moose for
    Applications

  Domain-specific
 Metaprogramming



         8
9
Context-oriented Programming with
ContextL

Towards a Secure Programming Language:
An Access Control System for CommonLisp...
Metaprogramming




       11
Metaprogramming

  $obj->can('method_name')




            12
Metaprogramming

  $obj->can('method_name')


   $obj->isa('Class::Name')




             13
Metaprogramming

  $obj->can('method_name')


   $obj->isa('Class::Name')


  $obj->DOES('RoleName')



             14
Metaprogramming

  $obj->can('method_name')


   $obj->isa('Class::Name')


  $obj->DOES('RoleName')


         eval "code...
Metaprogramming
my $code = setup();
$code .= important_stuff();
$code .= teardown();

eval $code;




                   16
Metaprogramming


__PACKAGE__->meta->make_immutable




               17
Metaprogramming


__PACKAGE__->meta->make_immutable




               18
Metaprogramming

my $meta = __PACKAGE__->meta;

$meta->make_immutable;




                   19
Metaprogramming

print $meta;

Moose::Meta::Class=HASH(0x966910)




                    20
Moose::Meta::Class
Attributes                              Methods
name                                    new_object
vers...
Metaprogramming
my $code = setup();
$code .= important_stuff();
$code .= teardown();

eval $code;




                   22
package Point;
use Moose;

has 'x' => (is => 'rw', isa => 'Int');
has 'y' => (is => 'rw', isa => 'Int');

sub clear { ... ...
Point->meta
my $point = Point->meta;




                    24
Point->meta
my $point = Point->meta;

$point->name # ?




                    25
Point->meta
my $point = Point->meta;

$point->name # Point




                       26
Point->meta
my $point = Point->meta;

$point->name # Point

$point->get_attribute_list # ?




                       27
Point->meta
my $point = Point->meta;

$point->name # Point

$point->get_attribute_list # y, x




                       28
Point->meta
my $point = Point->meta;

$point->name # Point

$point->get_attribute_list # y, x

$point->has_method('clear')...
Point->meta
my $point = Point->meta;

$point->name # Point

$point->get_attribute_list # y, x

$point->has_method('clear')...
package Point3D;
use Moose;

extends 'Point';

has 'z' => (is => 'rw', isa => 'Int');

after clear => sub { ... };




   ...
Point3D->meta
my $point3d = Point3D->meta;




                   32
Point3D->meta
my $point3d = Point3D->meta;

$point3d->name # ?




                     33
Point3D->meta
my $point3d = Point3D->meta;

$point3d->name # Point3D




                   34
Point3D->meta
my $point3d = Point3D->meta;

$point3d->name # Point3D

$point3d->get_attribute_list # ?




               ...
Point3D->meta
my $point3d = Point3D->meta;

$point3d->name # Point3D

$point3d->get_attribute_list # z




               ...
Point3D->meta
my $point3d = Point3D->meta;

$point3d->name # Point3D

$point3d->get_attribute_list # z

$point3d->has_meth...
Point3D->meta
my $point3d = Point3D->meta;

$point3d->name # Point3D

$point3d->get_attribute_list # z

$point3d->has_meth...
package Point3D;
use Moose;

extends 'Point';

has 'z' => (is => 'rw', isa => 'Int');


after clear => sub { ... };



   ...
Finding Things
      Local                   Global
has_attribute             find_attribute_by_name

has_method           ...
REST Interface
my $class = url2class($url);
my $meta = $class->meta;

for ($meta->get_all_attributes) {
   my $name = $_->...
use Moose;
    42
my $point = Moose::Meta::Class->create(
   'Point',
);




                         43
my $point = Moose::Meta::Class->create(
   'Point',
);

$point->superclasses('Moose::Object');




                       ...
my $point = Moose::Meta::Class->create(
   'Point',
);

$point->superclasses('Moose::Object');

$point->add_attribute(
   ...
…

$point->add_attribute(
   'y',
   is => 'ro',
   isa => 'Int',
);




                         46
…

$point->add_attribute(
   'y',
   is => 'ro',
   isa => 'Int',
);

$point->add_method(clear => sub {
    ...
});




  ...
Ecosystem

    Classes
   Attributes
    Methods
     Roles
Type Constraint
 Type Coercion

                  48
Ecosystem

    Classes            Moose::Meta::Class

   Attributes
    Methods
     Roles
Type Constraint
 Type Coercion
...
Ecosystem

    Classes                Moose::Meta::Class

   Attributes            Moose::Meta::Attribute

    Methods    ...
Ecosystem

my $x =
  Point->meta->get_attribute('x')

$x->name         #x
$x->get_read_method # x
$x->type_constraint # In...
Ecosystem

my $clear =
 Point->meta->get_method('clear')

$clear->name      # clear
$clear->package_name # Point




     ...
Extending


1. Extend a metaclass
2. Use it
Extending


Class that counts its instances
package HasCounter;
use Moose::Role;

has count => (
   is   => 'rw',
   isa   => 'Int',
   default => 0,
);

sub incremen...
package CountInstances;
use Moose::Role;

with 'HasCounter';

after new_object => sub {
   my $self = shift;
   $self->inc...
package Point;
use Moose -traits => [
   'CountInstances',
];

has x => (
   is => 'ro',
   isa => 'Int',
);

...
Point->meta->count # 0

Point->new
Point->meta->count # 1

Point->new for 1 .. 5
Point->meta->count # 6
Base                 Meta
Point->new

             Point->meta->new_object

                         after new_object

   ...
package Line;
use Moose;

has start => (
   is => 'ro',
   isa => 'Point',
);

has end => (
   is => 'ro',
   isa => 'Poin...
Base                Meta
Line->new

            Line->meta->new_object
package HasCounter;
use Moose::Role;
use MooseX::AttributeHelpers;

has count => (
   traits => ['Counter'],
   provides =...
package FieldType;
use Moose::Role;
use Moose::Util::TypeConstraints;

has render_as => (
   is => 'ro',
   isa => (enum [...
package User;
use Moose;

has name => (
   traits => ['FieldType'],
   is     => 'rw',
   isa    => 'Str',
   render_as =>...
...

has password => (
   traits => ['FieldType'],
   is     => 'rw',
   isa    => 'Str',
   render_as => 'password',
);
...

has biography => (
   traits => ['FieldType'],
   is     => 'rw',
   isa    => 'Str',
   render_as => 'textarea',
);
traits => ['FieldType'],
render_as => 'text',

traits => ['FieldType'],
render_as => 'password',

traits => ['FieldType'],...
traits => ['FieldType'],
render_as => 'text',

traits => ['FieldType'],
render_as => 'password',

traits => ['FieldType'],...
Moose::Exporter
Moose::Util::MetaRole
Moose::Exporter
Moose::Util::MetaRole
Moose::Exporter
Moose::Util::MetaRole
package MyWeb::OO;

use Moose ();
use Moose::Exporter;
use Moose::Util::MetaRole;

use FieldType;

Moose::Exporter->setup_...
my $class = shift;
my %options = @_;

Moose->init_meta(%options);
   Moose::Util::MetaRole::apply_metaclass_roles(
   for_...
package User;
use MyWeb::OO;

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

...
package User;
use MyWeb::OO;
use MyWeb::OO::Persistent;
use MyWeb::OO::RESTful;
use MyWeb::OO::IncludeInAdminUI;
use MyWeb...
Immutability
sub _initialize_body {
  my $self = shift;
  my $source = 'sub {';
  $source .= "n" . 'my $class = shift;';

  $source .= ...
KiokuDB
Fey::ORM
KiokuDB
   Fey::ORM

ContextL (CLOS)
ROLES!
Thank you!
Extending Moose
Upcoming SlideShare
Loading in …5
×

Extending Moose

3,716 views

Published on

Using Moose provides many immediate and obvious benefits, starting with the
obviation of typing "use strict" and "use warnings" in your classes.

The real power of Moose, however, rests in its extensibility. By subclassing
Moose's metaclasses, you can augment and change Moose's behavior to suit your
application's needs. This extensibility is powered by the meta-object protocol
of Moose's foundation, Class::MOP.

The motivating example for extending Moose will be the creation of a small web
framework to empower a Twitter-alike. The focus will be creating meta-level
roles so that metaclasses may select exactly which changes in behavior they
wish to exhibit. Modules that will be used include Moose::Exporter (to define
sugary keywords) and Moose::Util::MetaRole (to extend classes composably).

Experience with using Moose to create regular classes is expected. Having some
familiarity with roles will let you get more out of the talk. No experience
with metaprogramming is required.

Published in: Technology, Education
  • DOWNLOAD THAT BOOKS INTO AVAILABLE FORMAT (2019 Update) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download Full doc Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download doc Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... ......................................................................................................................... ................................................................................................................................... eBook is an electronic version of a traditional print book that can be read by using a personal computer or by using an eBook reader. (An eBook reader can be a software application for use on a computer such as Microsoft's free Reader application, or a book-sized computer that is used solely as a reading device such as Nuvomedia's Rocket eBook.) Users can purchase an eBook on diskette or CD, but the most popular method of getting an eBook is to purchase a downloadable file of the eBook (or other reading material) from a Web site (such as Barnes and Noble) to be read from the user's computer or reading device. Generally, an eBook can be downloaded in five minutes or less ......................................................................................................................... .............. Browse by Genre Available eBooks .............................................................................................................................. Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, ......................................................................................................................... ......................................................................................................................... .....BEST SELLER FOR EBOOK RECOMMEND............................................................. ......................................................................................................................... Blowout: Corrupted Democracy, Rogue State Russia, and the Richest, Most Destructive Industry on Earth,-- The Ride of a Lifetime: Lessons Learned from 15 Years as CEO of the Walt Disney Company,-- Call Sign Chaos: Learning to Lead,-- StrengthsFinder 2.0,-- Stillness Is the Key,-- She Said: Breaking the Sexual Harassment Story That Helped Ignite a Movement,-- Atomic Habits: An Easy & Proven Way to Build Good Habits & Break Bad Ones,-- Everything Is Figureoutable,-- What It Takes: Lessons in the Pursuit of Excellence,-- Rich Dad Poor Dad: What the Rich Teach Their Kids About Money That the Poor and Middle Class Do Not!,-- The Total Money Makeover: Classic Edition: A Proven Plan for Financial Fitness,-- Shut Up and Listen!: Hard Business Truths that Will Help You Succeed, ......................................................................................................................... .........................................................................................................................
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Extending Moose

  1. 1. Extending Moose for Applications Shawn M Moore Best Practical Solutions 1
  2. 2. Twitter! @sartak Hey wait, what is "meta"? 2
  3. 3. (or IRC) 3
  4. 4. Extending Moose for Applications 4
  5. 5. Domain-specific Metaprogramming 5
  6. 6. Extending Moose for Applications Domain-specific Metaprogramming 6
  7. 7. Extending Moose for Applications Domain-specific Metaprogramming 7
  8. 8. Extending Moose for Applications Domain-specific Metaprogramming 8
  9. 9. 9
  10. 10. Context-oriented Programming with ContextL Towards a Secure Programming Language: An Access Control System for CommonLisp Rhapsody: How CLOS simplifies System-in- a-Package Design 10
  11. 11. Metaprogramming 11
  12. 12. Metaprogramming $obj->can('method_name') 12
  13. 13. Metaprogramming $obj->can('method_name') $obj->isa('Class::Name') 13
  14. 14. Metaprogramming $obj->can('method_name') $obj->isa('Class::Name') $obj->DOES('RoleName') 14
  15. 15. Metaprogramming $obj->can('method_name') $obj->isa('Class::Name') $obj->DOES('RoleName') eval "code" 15
  16. 16. Metaprogramming my $code = setup(); $code .= important_stuff(); $code .= teardown(); eval $code; 16
  17. 17. Metaprogramming __PACKAGE__->meta->make_immutable 17
  18. 18. Metaprogramming __PACKAGE__->meta->make_immutable 18
  19. 19. Metaprogramming my $meta = __PACKAGE__->meta; $meta->make_immutable; 19
  20. 20. Metaprogramming print $meta; Moose::Meta::Class=HASH(0x966910) 20
  21. 21. Moose::Meta::Class Attributes Methods name new_object version clone_object attributes rebless_instance methods subclasses superclasses linearized_isa roles add_attribute attribute_metaclass has_method method_metaclass get_all_method_names constructor_name is_immutable constructor_class calculate_all_roles 21
  22. 22. Metaprogramming my $code = setup(); $code .= important_stuff(); $code .= teardown(); eval $code; 22
  23. 23. package Point; use Moose; has 'x' => (is => 'rw', isa => 'Int'); has 'y' => (is => 'rw', isa => 'Int'); sub clear { ... } 23
  24. 24. Point->meta my $point = Point->meta; 24
  25. 25. Point->meta my $point = Point->meta; $point->name # ? 25
  26. 26. Point->meta my $point = Point->meta; $point->name # Point 26
  27. 27. Point->meta my $point = Point->meta; $point->name # Point $point->get_attribute_list # ? 27
  28. 28. Point->meta my $point = Point->meta; $point->name # Point $point->get_attribute_list # y, x 28
  29. 29. Point->meta my $point = Point->meta; $point->name # Point $point->get_attribute_list # y, x $point->has_method('clear') # ? 29
  30. 30. Point->meta my $point = Point->meta; $point->name # Point $point->get_attribute_list # y, x $point->has_method('clear') # 1 30
  31. 31. package Point3D; use Moose; extends 'Point'; has 'z' => (is => 'rw', isa => 'Int'); after clear => sub { ... }; 31
  32. 32. Point3D->meta my $point3d = Point3D->meta; 32
  33. 33. Point3D->meta my $point3d = Point3D->meta; $point3d->name # ? 33
  34. 34. Point3D->meta my $point3d = Point3D->meta; $point3d->name # Point3D 34
  35. 35. Point3D->meta my $point3d = Point3D->meta; $point3d->name # Point3D $point3d->get_attribute_list # ? 35
  36. 36. Point3D->meta my $point3d = Point3D->meta; $point3d->name # Point3D $point3d->get_attribute_list # z 36
  37. 37. Point3D->meta my $point3d = Point3D->meta; $point3d->name # Point3D $point3d->get_attribute_list # z $point3d->has_method('clear') # ? 37
  38. 38. Point3D->meta my $point3d = Point3D->meta; $point3d->name # Point3D $point3d->get_attribute_list # z $point3d->has_method('clear') # 1 38
  39. 39. package Point3D; use Moose; extends 'Point'; has 'z' => (is => 'rw', isa => 'Int'); after clear => sub { ... }; 39
  40. 40. Finding Things Local Global has_attribute find_attribute_by_name has_method find_method_by_name get_attribute_list get_all_attributes get_method_list get_all_methods superclasses class_precedence_list 40
  41. 41. REST Interface my $class = url2class($url); my $meta = $class->meta; for ($meta->get_all_attributes) { my $name = $_->name; my $tc = $_->type_constraint; my $default = $_->default; if ($_->is_required) { ... } } 41
  42. 42. use Moose; 42
  43. 43. my $point = Moose::Meta::Class->create( 'Point', ); 43
  44. 44. my $point = Moose::Meta::Class->create( 'Point', ); $point->superclasses('Moose::Object'); 44
  45. 45. my $point = Moose::Meta::Class->create( 'Point', ); $point->superclasses('Moose::Object'); $point->add_attribute( 'x', is => 'ro', isa => 'Int', ); 45
  46. 46. … $point->add_attribute( 'y', is => 'ro', isa => 'Int', ); 46
  47. 47. … $point->add_attribute( 'y', is => 'ro', isa => 'Int', ); $point->add_method(clear => sub { ... }); 47
  48. 48. Ecosystem Classes Attributes Methods Roles Type Constraint Type Coercion 48
  49. 49. Ecosystem Classes Moose::Meta::Class Attributes Methods Roles Type Constraint Type Coercion 49
  50. 50. Ecosystem Classes Moose::Meta::Class Attributes Moose::Meta::Attribute Methods Moose::Meta::Method Roles Moose::Meta::Role Type Constraint Moose::Meta::TypeConstraint Type Coercion Moose::Meta::TypeCoercion 50
  51. 51. Ecosystem my $x = Point->meta->get_attribute('x') $x->name #x $x->get_read_method # x $x->type_constraint # Int 51
  52. 52. Ecosystem my $clear = Point->meta->get_method('clear') $clear->name # clear $clear->package_name # Point 52
  53. 53. Extending 1. Extend a metaclass 2. Use it
  54. 54. Extending Class that counts its instances
  55. 55. package HasCounter; use Moose::Role; has count => ( is => 'rw', isa => 'Int', default => 0, ); sub increment { my $self = shift; $self->count( $self->count + 1 ); }
  56. 56. package CountInstances; use Moose::Role; with 'HasCounter'; after new_object => sub { my $self = shift; $self->increment; };
  57. 57. package Point; use Moose -traits => [ 'CountInstances', ]; has x => ( is => 'ro', isa => 'Int', ); ...
  58. 58. Point->meta->count # 0 Point->new Point->meta->count # 1 Point->new for 1 .. 5 Point->meta->count # 6
  59. 59. Base Meta Point->new Point->meta->new_object after new_object Point->meta->increment
  60. 60. package Line; use Moose; has start => ( is => 'ro', isa => 'Point', ); has end => ( is => 'ro', isa => 'Point', );
  61. 61. Base Meta Line->new Line->meta->new_object
  62. 62. package HasCounter; use Moose::Role; use MooseX::AttributeHelpers; has count => ( traits => ['Counter'], provides => { inc => 'increment', }, );
  63. 63. package FieldType; use Moose::Role; use Moose::Util::TypeConstraints; has render_as => ( is => 'ro', isa => (enum [ 'text', 'textarea', 'password', ..., ]), );
  64. 64. package User; use Moose; has name => ( traits => ['FieldType'], is => 'rw', isa => 'Str', render_as => 'text', );
  65. 65. ... has password => ( traits => ['FieldType'], is => 'rw', isa => 'Str', render_as => 'password', );
  66. 66. ... has biography => ( traits => ['FieldType'], is => 'rw', isa => 'Str', render_as => 'textarea', );
  67. 67. traits => ['FieldType'], render_as => 'text', traits => ['FieldType'], render_as => 'password', traits => ['FieldType'], render_as => 'textarea',
  68. 68. traits => ['FieldType'], render_as => 'text', traits => ['FieldType'], render_as => 'password', traits => ['FieldType'], render_as => 'textarea',
  69. 69. Moose::Exporter Moose::Util::MetaRole
  70. 70. Moose::Exporter Moose::Util::MetaRole
  71. 71. Moose::Exporter Moose::Util::MetaRole
  72. 72. package MyWeb::OO; use Moose (); use Moose::Exporter; use Moose::Util::MetaRole; use FieldType; Moose::Exporter->setup_import_methods( also => 'Moose', ); sub init_meta { ... }
  73. 73. my $class = shift; my %options = @_; Moose->init_meta(%options); Moose::Util::MetaRole::apply_metaclass_roles( for_class => $options{for_class}, attribute_metaclass_roles => ['FieldType'], ); return $options{for_class}->meta;
  74. 74. package User; use MyWeb::OO; has name => ( is => 'rw', isa => 'Str', field_type => 'text', ); ...
  75. 75. package User; use MyWeb::OO; use MyWeb::OO::Persistent; use MyWeb::OO::RESTful; use MyWeb::OO::IncludeInAdminUI; use MyWeb::OO::SpamTarget; database_name 'person'; # legacy has email => ( is => 'rw', isa => 'Str', field_type => 'text', spam_this => 1, admin_editable => 0, primary_key => 1, );
  76. 76. Immutability
  77. 77. sub _initialize_body { my $self = shift; my $source = 'sub {'; $source .= "n" . 'my $class = shift;'; $source .= "n" . 'return $class->Moose::Object::new(@_)'; $source .= "n if $class ne '" . $self->associated_metaclass->name . "';n"; $source .= $self->_generate_params('$params', '$class'); $source .= $self->_generate_instance('$instance', '$class'); $source .= $self->_generate_slot_initializers; $source .= $self->_generate_triggers(); $source .= ";n" . $self->_generate_BUILDALL(); $source .= ";nreturn $instance"; $source .= ";n" . '}'; ...
  78. 78. KiokuDB Fey::ORM
  79. 79. KiokuDB Fey::ORM ContextL (CLOS)
  80. 80. ROLES!
  81. 81. Thank you!

×