> From: Luke Palmer [mailto:[EMAIL PROTECTED]
> 
> Austin Hastings writes:
> > Suppose that I have, for example:
> > 
> >   class Session {
> >     has @:messages;
> > 
> >     method clear_messages() {...}
> >     method add_message($msg) {...}
> >     method have_messages() {...}
> >     method get_messages() returns Array {... font color="black" ...}
> >   }
> > 
> > And suppose I add to it:
> > 
> >   class Session {
> >     has @:messages;
> > 
> >     method clear_messages() {...}
> >     method add_message($msg) {...}
> >     method have_messages() {...}
> >     method get_messages() returns Array {... font color="black" ...}
> > 
> >     has @:errors;
> > 
> >     method clear_errors() {...}
> >     method add_error($msg) {...}
> >     method have_errors() {...}
> >     method get_errors() returns Array {... font color="red" ...}
> >   }
> > 
> > So I realize that not only is the whole list-of-messages thing 
> > a packageable behavior (read: Role or Class) but that this particular 
> > behavior recurs within my class.
> 
> So what you want is a role whose names are private to the role, not the
> aggreagating class.  Well, I believe private (i.e. $:foo) variables do
> that anyway, so you can just abstract your messages out into a role and
> it will work fine.  But if you read on, I'll offer some unsolicited
> design advice.

Hmm. No. I want a role whose methods are available in the composing class, as shown. 
Variables (members) don't have roles: Roles (may) have variables.

Saying "class Session does MessageList" means that MessageList may impose member 
variables on Session, and will provide methods to Session. Roles are composition, not 
aggregation.

> > One solution is to compose member objects that implement this behavior:
> > 
> >   if ($my_object.messages.have_messages) {...}
> > 
> > But that sucks.
> 
> Why?  From a design perspective, that's the correct way to do it.  What
> if you have a routine that operates on message lists -- pruning them or
> somesuch.  If you do it by renaming the methods, you break any kind of
> future-proof code reuse that abstracting gets you in the first place.

You've got it backwards: saying $my_object.messages.have_messages is exposing the fact 
that the have_messages functionality is implemented via a member data item, instead of 
querying the $my_object directly.

> But I'll agree that:
> 
>     if $my_object.messages.have_messages {...}
> 
> Kinda sucks.  But you'll find that things that suck in this particular
> way can be solved by tersifying your method names.
> 
>     class MessageList {
>         method ready() {...}
>         method add($msg) {...}
>         method clear() {...}
>         method get() {...}
>     }
> 
> There's no reason to repeat _message on the end of each method when
> you're already in a class about messages.  And then you have:
> 
>     if $my_object.messages.ready {
>         say for $object.messages.get;
>     }
> 
> Which is quite more tolerable, IMO.
> 
> But this isn't an OO design list, it's a language design list.

And "how to make the names more readable" isn't "how to parameterize member/method 
names".

> 
> If it turns out that role private variables leak, I might suggest making
> a MessageList class as above, then making a role that knows how to turn
> a MessageList into a set of methods.  Then you'd pass the role the
> MessageList object which you instantiate yourself, and it would generate
> the methods for you.  That's kind of a kludge, but you're using roles
> for something they're not really intended for, so that's what you get.
> Keep in mind that there are plenty of other ways to do what you want;
> this is Perl, after all.

Hmm. Why is this not what roles are intended for? I have identified a packageable, 
reusable behavior that I want to insert into a class using some mechanism other than 
inheritance. I could have sworn that was the whole point of roles.

In this particular case, however, I've gone one step beyond and identified a "generic" 
behavior, that I'd like to implement multiple times with slightly different names.

=Austin

Reply via email to