[squeak-dev] Re: How about... something completely different? (Re:
Re: On traits composition)
Andreas Raab
andreas.raab at gmx.de
Wed Dec 9 03:50:29 UTC 2009
Josh Gargus wrote:
> Ted and Ian at VPRI recently wrote short notes on this topic:
> http://www.vpri.org/pdf/m2009014_membrane.pdf (Ted)
> http://www.vpri.org/pdf/m2009007_COLA_kern.pdf (Ian)
Oh boy, you asked for it :-) Ted's paper reminds me a lot of some of the
earliest discussions with Alan that came straight out of Macromedia
Director - I always liked how you could just drag and drop behaviors
onto an object and they would "just work" (incl. state and interactions
with other behaviors). The other big motivation for me as was to deal
with the problems that arise from the "fat class object" idea - i.e.,
the how to structure the (necessary) complexity for something as
powerful as a general end-user scriptable, graphical, composable object
without ending up like class Morph.
Tweak was my first (and unfortunately last) shot at it. One thing that
came straight out of the earlier discussion was that I realized that in
order to hide complexity I needed to encapsulate it, i.e., create fully
fledged self-contained entities (objects). In Tweak the result can be
seen for example when looking at players and their (costume) aspects.
They're kinda like the Morph equivalent but where Morph stuffs all of
the "extra logic" straight into class Morph itself (look at the
implementors of Morph>>color: or Morph>>borderWidth:) Tweak pushed this
stuff out into the aspects so that the method looks like:
CPlayer>>color: aColor
"The color is owned by the fill aspect"
^fill color: aColor
CPlayer>>borderWidth: aNumber
"The border width is owned by the border aspect"
^border width: aNumber
It worked by the aspects knowing the players they were owned by and
interacting with them as needed (i.e., CFill>>color: would eventually
call the player's invalidation method to cause a redraw).
I still think that's a really great idea to structure complexity for
several reasons. First of all, contrary to traits and other MI solutions
you have *objects*, self-contained entities with encapsulated internal
state and behavior.
Secondly, by defining the interface between the parts you get a clearer
separation of concerns between them, with clearly defined external and
internal interfaces (i.e., try finding the methods relating to fill
stuff in Morph, then go and try to find those that are part of the
public interface).
Third, this mechanism also gives you the "many versions of self" that
the delegation discussions usually end up with by way of being able to
decide whether to say "owner borderWidth: 2" or "self width: 2" from the
aspect (the former being overridable by all subclasses of CPlayer; the
latter defining this as a more private matter that can only be
reimplemented by aspects of the same form).
And of course such aspects can be composed the same way so it's turtles
all the way down. Lastly, boilerplate like the above is trivial to
automate and to fold into a class definition syntax.
However, there is one major gotcha in this. It's that you need to design
your entities differently. You can no longer assume that a class is
completely self-contained (i.e., the class as an idea), but rather that
it will have numerous collaborators that are equally important (which is
more along the lines of the resulting object being a cell). This implies
different design approaches and some of the rules of good OO design have
limited applicability, for example the general rule of thumb that an
owned object shouldn't know its owner, or the law of diameter. In a
design like here, you would absolutely expect a Rectangle aspect to know
the "owner" which gets notified about the change when you call the
#left: method on it.
To come full circle here, to me the problem with traits (really, any
form of MI used for code composition) is that the end result is *always*
something that looks like class Morph - complexity in a single
centralized place, all messed up with renames, aliasing, exclusion. From
my perspective there's no way around that problem as long as we're not
starting to introduce internal structure. That would be objects.
Cheers,
- Andreas
More information about the Squeak-dev
mailing list
|