On Mon, Oct 12, 2009 at 11:53 AM, Ovid <publiustemp-catal...@yahoo.com> wrote:
> --- On Mon, 12/10/09, Jesse Luehrs <d...@tozt.net> wrote:
>
>> From: Jesse Luehrs <d...@tozt.net>
>
>> Yeah, something like this would work:
>>
>>   package Thing;
>>   use Moose;
>>   has robot_arm => (
>>       is      => 'ro',
>>       isa     => 'RobotArm',
>>       default => sub {
>>           my $self = shift;
>>           return RobotArm->new(to_draw => $self);
>>       },
>>       handles => { draw_with_arm => 'draw' },
>>   );
>
> So instead of this:
>
>  package Thing;
>  use Moose;
>  with (
>    DoesRobot => { excludes => 'draw', aliases => { draw => 'draw_with_arm' } 
> },
>    'DoesDrawable'
>  );
>
> You recommend this:
>
>  package Thing;
>  use Moose;
>  has robot_arm => (
>    is      => 'ro',
>    isa     => 'RobotArm',
>    default => sub { RobotArm->new({ to_draw => shift }) },
>    handles => { draw_with_arm => 'draw' },
>  );
>
> This is interesting in a couple of ways.  Aside from the fact that we have 
> more scaffolding code we have to write, we no longer get our composition-time 
> safety from 'requires' which roles provide.  With delegation, if $self 
> doesn't provide the methods you need, you get your failures at runtime 
> instead of composition time.  This is a problem when delegation requires 
> bi-directional in the sending and receiving objects.

class RobotArm {

        has object => (
               isa => duck_type([qw(size, shape, color)]),
               init_arg => 'to_draw',
               required => 1,
        }

}

This doesn't happen at composition time but does happen at object
creation time. The problem is this metaphor is getting abused, and the
reality is "it depends" on your specific circumstances. If you want a
program to be provably correct at compilation time, perhaps it's time
to look at a language that focuses on that, like OCaml?

> Mind you, I'm not saying you're wrong.  I think this technique is fine if you 
> already have a RobotArm class handling this particular case.  I'm just toying 
> more and more with the idea of assembling classes out of role-based 
> components (something I'm not pushing for production, of course).  Separation 
> of concerns is important, but I want to hear more concrete wins of delegation 
> over role composition :)

You've got a chicken egg problem then. If you only use this when a
RobotArm already exists, you never write a RobotArm class because one
doesn't exist ...

More concrete examples other than the fact that roles don't even solve
the problem that started this thread? Look at the implementation of
MooseX::Storage which is a *real world* use case for what your asking.
the Storage role has an Engine delegate, this Engine delegate handles
the heavy lifting of the business logic dealing with serialization.
KiokuDB goes further by abstracting the concept of serialization out
of the Object itself and into a process that happens upon an object.
As an experiment why not try re-implementing MooseX::Storage using
*only* Roles? I'm fairly certain either you'll prove your point, or
find out quickly what we're nattering on about.

-Chris

Reply via email to