> 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