Behaviors vs Modules

Anthony Hannan ajh18 at cornell.edu
Sun Feb 24 18:32:55 UTC 2002


Nathanael <n.schaerli at gmx.net> wrote:
> Two of the main reasons why I decided against allowing the use of
> "nested selectors" for now are:
> - Encapsulation: In a model where an object does not understand every
> selector, only the selectors defined in the class/superclass and the
> selectors in the used mixins are available for a certain object. Therefore,
> if a client calls 'obj morph.step', the client needs to assume that class of
> obj contains a mixin that specifies a method step. But such an assumption
> breaks with the concept that the concrete implementation of a certain class
> (i.e. whether a method is defined in the class itself or a certain mixin)
> should not matter to the clients.
> - Polymorphism: Let's assume that we have a class BankAccount that uses a
> mixin LockingPolicy to provide the behavior for a locking policy. Thus,
> there might be a call 'obj lockingPolicy.wait', to a instance obj of
> BankAccont. The problem here is that the effectively invoked method is
> pretty much hardcoded in the calling statement. This is bad, because we
> might want to change BankAccount so that it uses the mixin
> PessimisticLockingPolicy instead of LockingPolicy. However, this does not
> work because the caller explicitely specifies the target method.

The prefix does not designate which mixin to use it only designates
which protocol.  Many mixins can implement the same protocol.  So in
your example above, LockingPolicy and PessimisticLockingPolicy would
both implement the same lockingPolicy protocol, so the BankAccount can
change its mixin without changing its callers.  A protocol is just a set
of selectors, while a mixin is a set of methods.

> If I understood you right, the main differences between your proposal and my
> implementation is the fact that you want to make all the methods in the
> system available to all the objects. Although this makes total sense from a
> technical point of view, I'm afraid that this will decrease the readability
> and understandability of the code because it is hard to see what aspects and
> method a certain class is designed to provide. How should a programmer know
> whether he is supposed to send a certain message (e.g. 'morph.step') to a
> certain object? And even more important: How can a programmer avoid a
> certain message to be sent? He basically has to implement the excluded
> selectors as "self shouldNotImplement", right?
> From this point of view, I think that the approach with explicitely mixing
> the mixins into a class leads to entities that are much easier to understand.

You have a point but I think we can figure out which protocols are
applicable to a class just by seeing which selectors it overrides and
finding which mixins use those selectors.  If we can do this quick
enough in a tool, I think its better not to have to explicitly mixin
behaviors into classes.  When we are programming a message send we are
targeting a protocol and don't care about the class of the receiver.  It
would be nice to not have to worry about the possible classes of the
receiver to make sure they have the mixin.  It will just be automatic if
the class implements the required methods (usually just the accessors). 
Also, I don't think we have to worry about adding shouldNotImplements. 
subclassResponsibility is already the default behavior which is
equivalent to shouldNotImplement, and if the default behavior does
execute real code it won't hurt because eventually it will try to call
an accessor that is not implemented (subclassResponsibility).

Cheers,
Anthony



More information about the Squeak-dev mailing list