From: Dave Rolsky Date: Fri, 19 Jun 2009 15:49:14 +0000 (-0500) Subject: Finished slides for advanced attributes section. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=5d57268450de0579773e5835629b68666fc4eb70;p=gitmo%2Fmoose-presentations.git Finished slides for advanced attributes section. Some tweaks for earlier slides. --- diff --git a/moose-class/slides/index.html b/moose-class/slides/index.html index 2ddbdc1..2acaf6c 100644 --- a/moose-class/slides/index.html +++ b/moose-class/slides/index.html @@ -884,14 +884,14 @@ use Moose;
  • Each call to extends resets your parents
  • -

    WRONG

    +

    Wrong

    package EvilEmployee;
     use Moose;
     extends 'Person';
     extends 'Thief';
    -

    RIGHT

    +

    Right

    package EvilEmployee;
     use Moose;
    @@ -2363,6 +2363,50 @@ extends 'Report';
     
     
     
    +

    Method Modifiers Summary

    + +
      +
    • Use before and after for ... +
        +
      • logging
      • +
      • pre- or post-validation
      • +
      • to add behavior to generated methods
      • +
      +
    • +
    • These two modifiers cannot change parameters or return values
    • +
    +
    + +
    +

    Method Modifiers Summary

    + +
      +
    • Use around to ... +
        +
      • alter parameters passed to the original method
      • +
      • alter the return value of the original method
      • +
      • not call the original method at all (or call a different method)
      • +
      +
    • +
    +
    + +
    +

    Method Modifiers Summary

    + +
      +
    • When using modifiers in a role, require the modified method
    • +
    • Use augment and inner to invert the normal subclassing flow ... +
        +
      • Least- to most-specific (parents to children)
      • +
      • Build in "insertability" (stick more stuff in the "middle")
      • +
      +
    • +
    • Always call inner in the most specific subclass to allow for future extension
    • +
    +
    + +

    Questions?

    @@ -2375,6 +2419,356 @@ extends 'Report'; Iterate til this passes all its tests
    +
    +

    Part 5: Types

    +
    + +
    +

    Part 6: Advanced Attributes

    +
    + +
    +

    Weak References

    + +
      +
    • A weak reference lets you avoid circular references
    • +
    • Weak references do not increase the reference count
    • +
    +
    + +
    +

    Circular Reference Illustrated

    + +
    my $foo = {};
    +my $bar = { foo => $foo };
    +$foo->{bar} = $bar;
    + +
      +
    • Neither $foo nor $bar go out of scope
      + (until the program exits)
    • +
    +
    + +
    +

    Weakening Circular References

    + +
    use Scalar::Util qw( weaken );
    +
    +my $foo = {};
    +my $bar = { foo => $foo };
    +$foo->{bar} = $bar;
    +weaken $foo->{bar}
    + +
      +
    • When $bar goes out of scope, $foo->{bar} becomes undef
    • +
    +
    + +
    +

    Circular References in Attributes

    + +
    package Person;
    +use Moose;
    +
    +has name   => ( is => 'ro' );
    +has friend => ( is => 'rw' );
    +
    +my $alice = Person->new( name => 'Alice' );
    +my $bob   = Person->new( name => 'Bob' );
    +$bob->friend($alice);
    +$alice->friend($bob);
    +
    + +
    +

    The Fix

    + +
    package Person;
    +use Moose;
    +
    +has name   => ( is => 'ro' );
    +has friend => ( is => 'rw', weak_ref => 1 );
    +
    +my $alice = Person->new( name => 'Alice' );
    +my $bob   = Person->new( name => 'Bob' );
    +$bob->friend($alice);
    +$alice->friend($bob);
    +
    + +
    +

    Under the Hood

    + +
      +
    • A weak_ref attribute calls weaken ... +
        +
      • during object construction
      • +
      • when the attribute is set via a writer
      • +
      +
    • +
    +
    + +
    +

    Triggers

    + +
      +
    • A code reference run after an attribute is set
    • +
    • Like an after modifier, but makes intentions clearer
    • +
    + +

    Gross

    + +
    after salary_level => {
    +    my $self = shift;
    +    return unless @_;
    +    $self->clear_salary;
    +};
    +
    + +
    +

    Use a Trigger Instead

    + +

    Cleaner

    + +
    has salary_level => (
    +    is      => 'rw',
    +    trigger => sub { $_[0]->clear_salary },
    +);
    +
    + +
    +

    Delegation

    + +
      +
    • Attributes can be objects
    • +
    • Delegation transparently calls methods on those objects
    • +
    +
    + +
    +

    Delegation Examples

    + +
    package Person;
    +
    +has lungs => (
    +    is      => 'ro',
    +    isa     => 'Lungs',
    +    handles => [ 'inhale', 'exhale' ],
    +);
    + +
      +
    • Creates $person->inhale and ->exhale methods
    • +
    • Internally calls $person->lungs->inhale
    • +
    +
    + +
    +

    Why Delegation?

    + +
      +
    • Reduce the number of classes exposed
    • +
    • Re-arrange class internals -
      + turn a method into an attribute with delegation
    • +
    • Provide convenenience methods
    • +
    +
    + +
    +

    Moose's handles Parameter

    + +
      +
    • Accepts many arguments ... +
        +
      • Array reference - list of methods to delegate as-is
      • +
      • Hash reference - map of method names
      • +
      • Regex - delegates all matching methods
      • +
      • Role name - delegates all methods in the role
      • +
      • Sub reference - does something complicated ;)
      • +
      +
    • +
    +
    + +
    +

    Array Reference

    + +
      +
    • Takes each method name and creates a simple delegation from the delegating class to the delegatee attribute
    • +
    +
    + +
    +

    Hash Reference

    + +
      +
    • Mapping of names in the delegating class to the delegatee class
    • +
    + +
    package Person;
    +use Moose;
    +
    +has account => (
    +    is      => 'ro',
    +    isa     => 'BankAccount',
    +    handles => {
    +        receive_money => 'deposit',
    +        give_money    => 'withdraw',
    +    },
    +);
    +
    + +
    +

    Hash Reference Detailed

    + +
        handles => {
    +        receive_money => 'deposit',
    +        give_money    => 'withdraw',
    +    },
    + +
      +
    • $person->receive_money = $person->account->deposit
    • +
    • $person->give_money = $person->account->withdraw
    • +
    +
    + +
    +

    Regex

    + +
    package Person;
    +use Moose;
    +
    +has name => (
    +    is      => 'ro',
    +    isa     => 'Name',
    +    handles => qr/.*/,
    +);
    + +
      +
    • Creates a delegation for every method in the Name class
    • +
    • Excludes meta and methods inherited from Moose::Object
    • +
    +
    + +
    +

    Role Name

    + +
    package Auditor;
    +use Moose::Role;
    +
    +sub record_change  { ... }
    +sub change_history { ... }
    +
    +package Account;
    +use Moose;
    +
    +has history => (
    +    is      => 'ro',
    +    does    => 'Auditor',
    +    handles => 'Auditor',
    +);
    +
    + +
    +

    Role Name Detailed

    + +
      +
    • Account gets delegate methods for each method in the Auditor role +
        +
      • record_history
      • +
      • change_history
      • +
      +
    • +
    +
    + +
    +

    Traits and Metaclasses

    + +
      +
    • The ultimate in customization
    • +
    • Per attribute metaclasses
    • +
    • Per attribute roles applied to the attribute metaclass
    • +
    • Change the meta-level behavior
    • +
    +
    + +
    +

    Traits and Metaclasses

    + +
      +
    • The default metaclass is Moose::Meta::Attribute
    • +
    • Controls accessor generation, defaults, delegation, etc.
    • +
    • Adding a role to this metaclass (or replacing it) allows for infinite customization
    • +
    +
    + +
    +

    Traits and Metaclasses

    + +
      +
    • Can add/alter/remove attribute parameter (from has)
    • +
    • Can change behavior of created attribute
    • +
    +
    + +
    +

    Simple Trait Example

    + +
    package Person;
    +use Moose;
    +use MooseX::LabeledAttributes;
    +
    +has ssn => (
    +    traits => [ 'Labeled' ],
    +    is     => 'ro',
    +    isa    => 'Str',
    +    label  => 'Social Security Number',
    +);
    +
    +print Person->meta
    +            ->get_attribute('ssn')->label;
    +
    + +
    +

    Simple Metaclass Example

    + +
    package Person;
    +use Moose;
    +use MooseX::LabeledAttributes;
    +
    +has ssn => (
    +    metaclass =>
    +        'MooseX::Meta::Attribute::Labeled',
    +    is        => 'ro',
    +    isa       => 'Str',
    +    label     => 'Social Security Number',
    +);
    +
    +print Person->meta
    +            ->get_attribute('ssn')->label;
    +
    + +
    +

    Traits vs Metaclass

    + +
      +
    • Can apply any mix of traits to an attribute
    • +
    • But just one metaclass
    • +
    • Traits (aka roles) can cooperate
    • +
    • Metaclasses require you to pick just one
    • +
    +
    + +
    +

    Advanced Attributes Summary

    + +
      +
    • Use weak_ref to avoid circular references
    • +
    • Use trigger to do an action post-attribute write
    • +
    • Use delegations to hide "internal" objects
    • +
    • Traits and metaclasses let you extend Moose's core attribute features
    • +
    +
    + diff --git a/moose-class/slides/ui/custom.css b/moose-class/slides/ui/custom.css index 1ae314f..0651329 100644 --- a/moose-class/slides/ui/custom.css +++ b/moose-class/slides/ui/custom.css @@ -76,6 +76,10 @@ img.for-slide { font-size: 33%; } +.slide pre.medium { + font-size: 80%; +} + .slide table.side-by-side tr { vertical-align: top; }