Hi, This (aspect solution) is exactly what I was looking for ! Thanks everyone for the comments, it was fun and I learned a lot.
Ynon On 10 February 2012 21:24, Jesse Luehrs <d...@tozt.net> wrote: > On Fri, Feb 10, 2012 at 02:06:24PM -0500, Chris Prather wrote: > > On Fri, Feb 10, 2012 at 12:27 PM, Ovid <curtis_ovid_...@yahoo.com> > wrote: > > > > > > > Of course, both Acme::Combat::Chipmunk and Acme::Combat::Normal > implement the desired role. With that, you can swap out abilities as needed. > > > > What if Joe is bitten by a Chipmunk *and* a Zombie? You'll need to > > carefully design your roles with composition in mind then. This is > > what stopped my first go at this problem using an Array trait. > > Right, this is the key point here. Roles are designed for composition > into classes, and have an interface that makes sense for that kind of > use case (where you can handle method conflicts and such when you're > actually writing the class). Runtime application to instances does work, > but only really works well for very simple cases where there aren't very > many things interacting. Once you start trying to model more complicated > things with roles, you will end up writing just as much (if not more) > code trying to force roles into the model that your system needs as you > would if you had just written that explicitly from the start (and it > will end up being more difficult to understand and maintain too). > > One alternative to having to hardcode specific aspect behavior into each > action is to make the aspects classes rather than roles, and have those > classes consume roles corresponding to the actions. For instance, you > could do something along these lines (note that this is effectively the > same sort of model as Dist::Zilla uses for plugins): > > package Acme::Combat; > use Moose; > > # ... > > sub attack { > my $self = shift; > for my $aspect ($self->aspects_with('Attack')) { > $aspect->attack_effects(@_); > } > } > > package Acme::Combat::Normal; > use Moose; > > with 'Acme::Combat::Aspect::Attack'; > > sub attack_effects { > my $self = shift; > my ($opponent) = @_; > $opponent->decrease_hp(2); > } > > This way, you can just swap out which aspects are attached to a given > class, and things will just work. The advantage here is that you're > explicitly determining what the composition behavior should be, so you > don't have to try to trick roles into doing what you want. > > -doy >