Froscamp2010_moose

download Froscamp2010_moose

If you can't read please download the document

Transcript of Froscamp2010_moose

Moose

Rene Bcker

$foo Perl-MagazinFrankfurt.pm

Selbstndiger Perl-Programmierer

MooseA postmodern object system for Perl 5

Warum Moose?

Vor Perl 5 gab es gar keine Objektorientierung in Perl

Objektorientierung ist also nichts natives in Perl

Dadurch ist vieles nicht so schn wie in anderen Sprachen

vieles muss hndisch gemacht werden

Warum Moose?

package Employee;

sub new { bless {} }

for my $attr (qw(name title)) { no strict; *$attr = sub { my $self = shift; $self->{ $attr } = shift if @_; return $self->{ $attr }; };}

Warum Moose?

package Employee;

sub new { bless {} }

sub name { my $self = shift; $self->{name} = shift if @_; return $self->{name};}

sub title { my $self = shift; $self->{title} = shift if @_; return $self->{title};}

Warum Moose?

class Employee attr_accessor :name attr_accessor :titleend

Warum Moose?

package Employee;use Moose;

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

Warum Moose?

Moose vereinfacht diese Dinge enorm

Fhrt zu wartbarem, lesbarem Perl-Code

Ein Vergleich...

Elch vs. Kamel ein Vergleich

MooseEine Einfhrung

Moose Eine Einfhrung

use Moose; use strict;

use warnings;

@ISA = qw(Moose::Object) unless @ISA;Liefert auch new

einige neue Schlsselwrter

Moose - Attribute

has ist Schlsselwort fr Attribute

has attributname => ( # # Eigenschaften des Attributs # );

Moose - Attribute

package Event;

use Moose;

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

no Moose;

1;

Moose - Attribute

package Event;

use Moose;

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

no Moose;

1;

use Event;

my $event = Event->new( name => 'FrOSCamp',);

print $event->name;

Moose - Attribute

Eigenschaftenis =>'ro' read only

'rw' read/write

isa =>Von welchem Datentyp ist das Attribut

default => Standardwert des Attributs

required => Muss es angegeben werden?

...

Moose - Attribute

has name => ( is => 'ro', required => 1,);

has orga => ( is => 'rw', isa => 'ArrayRef[Str]', default => sub{ [qw/Sandro Marcus/] },);

Moose - Attribute

has name => ( is => 'ro', required => 1,);

has orga => ( is => 'rw', isa => 'ArrayRef[Str]', default => sub{ [qw/Sandro Marcus/] },);

Man muss einen Namen beimObjekterzeugen angeben!

Moose - Attribute

has name => ( is => 'ro', required => 1,);

has orga => ( is => 'rw', isa => 'ArrayRef[Str]', default => sub{ [qw/Sandro Marcus/] },);

Hierfr gibt es sowohl getterals auch setter

Moose - Attribute

has name => ( is => 'ro', required => 1,);

has orga => ( is => 'rw', isa => 'ArrayRef[Str]', default => sub{ [qw/Sandro Marcus/] },);

Das Attribut ist eine Arrayreferenz,in der nur Strings vorkommendrfen.

Moose - Attribute

has name => ( is => 'ro', required => 1,);

has orga => ( is => 'rw', isa => 'ArrayRef[Str]', default => sub{ [qw/Sandro Marcus/] },);

Falls bei der Erzeugung des Objektskeine orga angegeben wird,ist das der Standardwert

Moose - Typen

has orga => ( is => 'rw', isa => 'ArrayRef[Str]', default => sub{ [qw/Sandro Marcus/] },);

Moose hat einige Builtin-Typen

Moose Typen

Moose Typen

aber man kann auch eigene Typen erstellen, fr vieles reicht es, den Klassennamen anzugeben

has start_date => ( is => 'rw', isa => 'DateTime',);

Moose Typen

aber man kann auch eigene Typen erstellen, fr vieles reicht es, den Klassennamen anzugeben

my $event = Event->new( name => 'FrOSCamp', start_date => DateTime->new( year => 2010, month => 9, day => 17, ),);

Moose Typen

use Moose::Util::TypeConstraints;

subtype 'TwitterMsg' => as 'Str' => where { length $_[0] ( is => 'rw', isa => 'ArrayRef[TwitterMsg]', auto_deref => 1,);

Moose Typen

use Moose::Util::TypeConstraints;

subtype 'TwitterMsg' => as 'Str' => where { length $_[0] ( is => 'rw', isa => 'ArrayRef[TwitterMsg]', auto_deref => 1,);

Ein neuer Datentyp mitNamen TwitterMsg

Moose Typen

use Moose::Util::TypeConstraints;

subtype 'TwitterMsg' => as 'Str' => where { length $_[0] ( is => 'rw', isa => 'ArrayRef[TwitterMsg]', auto_deref => 1,,);

mit Str als Basis

Moose Typen

use Moose::Util::TypeConstraints;

subtype 'TwitterMsg' => as 'Str' => where { length $_[0] ( is => 'rw', isa => 'ArrayRef[TwitterMsg]', auto_deref => 1,);

und der Bedingung,dass der String krzer als 140Zeichen oder genau 140 Zeichenlang ist

Moose Typen

$event->twitter( [ 'hallo', 'welt' ],);

print "\n" for $event->twitter;

Moose Typen

$event->twitter( [ 'hallo', 'welt', 'y' x 144 ],);

print "\n" for $event->twitter;

Attribute (twitter) does not pass the type constraint because: Validation failed for 'ArrayRef[TwitterMsg]'

Moose Typen

my $event = Event->new( name => 'FrOSCamp', start_date => '17.09.2010',);

Moose Typen

subtype 'DateTime' => as 'Object' => where { $_[0]->isa( 'DateTime' ) };

coerce 'DateTime' => from 'Str' => via { my %info; @info{qw/day month year/} = split /\./, $_; DateTime->new( %info ); };

has start_date => ( is => 'rw', isa => 'DateTime', coerce => 1,);

Moose Attribute

Man kann noch mehr mit den Attributen machen:Zustzliche Methoden delegieren

In Subklassen zustzlich erweitern

Moose - Methoden

Erstmal nichts besonderes wie bei Standard Perl 5 OO

sub send_cfp { my ($self,@recipients) = @_; for my $recipient ( @recipients ) { $self->send_email( $recipient, $self->cfp ); }}

Moose Methoden

aber man kann tolle Sachen drumherum machenCode vor der der Subroutine aufrufen

sub send_cfp { my ($self,@recipients) = @_; for my $recipient ( @recipients ) { $self->send_email( $recipient, $self->cfp ); }}

before send_cfp => sub { print "*vor* send_cfp\n";};

Moose Methoden

aber man kann tolle Sachen drumherum machenCode vor der der Subroutine aufrufen

sub send_cfp { my ($self,@recipients) = @_; for my $recipient ( @recipients ) { $self->send_email( $recipient, $self->cfp ); }}

before send_cfp => sub { print "*vor* send_cfp\n";};

Moose Methoden

Code nach der Subroutine ausfhren

sub send_cfp { my ($self,@recipients) = @_; for my $recipient ( @recipients ) { $self->send_email( $recipient, $self->cfp ); }}

after send_cfp => sub { print "*nach* send_cfp\n";};

Moose Methoden

Code nach der Subroutine ausfhren

sub send_cfp { my ($self,@recipients) = @_; for my $recipient ( @recipients ) { $self->send_email( $recipient, $self->cfp ); }}

after send_cfp => sub { print "*nach* send_cfp\n";};

Moose Methoden

Bei before und after hat man allerdings keinen Einfluss auf Parameter fr die Originalmethode oder deren Rckgabewert

Man bekommt bei before aber die Parameter bergeben

Moose Methoden

Code drumherum ausfhren

sub send_cfp { my ($self,@recipients) = @_; for my $recipient ( @recipients ) { $self->send_email( $recipient, $self->cfp ); }}

around send_cfp => sub { my ($self,$code,@param) = @_; print "*vor* send_cfp\n"; $self->$code( @params ); print "*nach* send_cfp\n";};

Moose Methoden

Code drumherum ausfhren

sub send_cfp { my ($self,@recipients) = @_; for my $recipient ( @recipients ) { $self->send_email( $recipient, $self->cfp ); }}

around send_cfp => sub { my ($self,$code,@param) = @_; print "*vor* send_cfp\n"; $self->$code( @params ); print "*nach* send_cfp\n";};

Moose Methoden

Noch mehr mglichaugment & inner

override & super

Moose Vererbung

Vererbung mit Schlsselwort 'extends'

package Person;

use Moose;

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

no Moose;

1;

package Attendee;

use Moose;

extends 'Person';

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

no Moose;

1;

Moose Vererbung

use Attendee;my $person = Attendee->new( name => 'renee', nr_attended => 3,);

print $person->name, ': ', $person->nr_attended;

Moose - Rollen

Moose untersttzt MehrfachvererbungAber wer will das?

Kann zu Problemen bei mehreren Klassen, die die gleiche Subroutine zur Verfgung stellen, fhren

Rollen

Moose Rollen

PersonAttendee

Moose Rollen

PersonAttendee

Speaker

Moose Rollen

PersonAttendee

Orga

Moose Rollen

PersonAttendee

Orga

Speaker

Moose Rollen

PersonAttendee

Orga

Speaker

Was, wenn eine Person Speaker und Orga ist?

Moose Rollen

PersonAttendee

Hier besser Rollen verwenden

SpeakerOrga

Moose Rollen

Rollen definieren ein VerhaltenSind wie Java Interfaces (safe) und mixins (useful)

Rollen fr kleine wiederverwendbare Verhalten verwenden

Ein paar ntzliche Rollen gibt es auch schon auf CPAN

Moose Rollen

Entweder direkt einer Klasse zuweisen

oder spter eine Rolle fr ein Objekt zuweisen

Moose Rollen

package OrgaAttendee;

use Moose;

extends 'Attendee';with 'Orga';

no Moose;

1;

Moose Rollen

package OrgaAttendee;

use Moose;

extends 'Attendee';with 'Orga';

no Moose;

1;

'OrgaAttendee' verwendet Rolle 'Orga'

Moose Rollen

use OrgaAttendee;

my $person = OrgaAttendee->new( name => 'sandro', area => 'everything',);

$person->is_responsible;

Moose Rollen

use Attendee;use Speaker;

my $person = Attendee->new( name => 'renee' );

Speaker->meta->apply( $person );$person->speak;

Moose Rollen

use Attendee;use Speaker;

my $person = Attendee->new( name => 'renee' );

Speaker->meta->apply( $person );$person->speak;

Rolle 'Speaker' wird demObjekt nachtrglichzugeordnet

Moose - Erweiterungen

Etliche Module im MooseX::*-NamensraumMooseX::Types (::UUID, ::URI, ::NetAddr::IP, ::XMLSchema)

MooseX::Role::Parameterized

MooseX::Singleton

MooseX::Declare

...

Moose ein Fazit

Weniger Code bei Verwendung von MooseWeniger Fehleranfllig

Bessere Wartbarkeit

Bessere Lesbarkeit

Die Hauptarbeit wird dem Programmierer abgenommen

Moose - Lesestoff

Moose::Cookbookhttp://search.cpan.org/dist/Moose/...

$foo Perl-MagazinAusgabe 4 Moose

Ausgabe 12 Elchtest (Moose)

Ab Ausgabe 15 Moose-Tutorial

Moose-Webseitehttp://moose.perl.org