View · Search · Index
No registered users in community xowiki
in last 10 minutes

Re: [Xotcl] Precedence Order

From: Scott Gargash <scottg_at_atc.creative.com>
Date: Wed, 30 Aug 2006 10:01:16 -0600

Uwe Zdun <uwe.zdun_at_wu-wien.ac.at> wrote on 08/29/2006 12:20:16 PM:

> well, why do you think the behavior breaks encapsulation?

When I extend Base with BaseMixin, I'm altering the interface to Base. I
can't safely alter the interface to Derived, because Base and BaseMixin
don't necessarily know about Derived. In fact, since Derived is
completely independent, it might not even exist when BaseMixin is defined.
In gerneral BaseMixin can't be defined to work correctly with all possible
derived classes, that set is open.

I believe when I add a mixin to Base I'm intercepting Base method
invocations. When Derived invokes "next", it's logically chaining to Base.
The Base may or may not have BaseMixin, but Derived shouldn't need to
know. With BaseMixin intecepting Derived methods, BaseMixin needs to be
made to work with Base & Derived. In practice, this seems like you can't
safely use a mixin on any class thats also used as a superclass since the
mixin will intercept any derived class's interface.

In practice, it's not possible to work with both. Assume BaseMixin is
intercepting a leaf method with a leaf method: if BaseMixin invokes 'next'
it will break Base and if it doesn't invoke 'next' it will break Derived.

The current behavior means I can't intercept a subset of the hierarchy, I
have to intercept the whole thing. That means I can't encapsulate the use
of a mixin; the mixin gets applied globally.


> Rather a
> behavior where mixin are not added in precedence before the class
> hierarchy, requires you to know about the interceptor and might break
> encapsulation. Consider you are omitting to use "next" in a method of
> Derived, for instance simply because this method exists nowhere else in
> the class hierarchy. If the mixin would be introduced after Derived, you

> would need to modify Derived to introduce a method of the same name on
> the mixin. If the mixin is always before the class hierarchy, as a base
> hierarchy developer you don't need to care for how a potential mixin is
> designed, because you can be sure once a call has reached your class,
> you can be sure, you cannot accidently introduce side-effects on mixins
> (maybe designed later by other developers).

To be clear, I agree that a mixin should take precedence over the class
it's mixed into. I don't think it should take precedence over classes
derived from the class it's mixed into. If I wanted to intercept method
invocations on Derived, I would add a mixin to Derived but my explicit
semantic is that I want to intercept methods on Base.



To ground this discussion a bit more in reality, my base class accesses
hardware (Device). I then have a AppDevice class derived from the Device
class that I use in my application. AppDevice will get a method, perform
some processing and then invoke Device (via 'next').

So from the app point of view I have:
AppDevice --> Device

For testing purposes I want to use a simulator. I created a DeviceSim
class that reads and writes a buffer instead of the HW. I don't want my
derived classes to know or care if it's using the simulator or the actual
device. In either case the classes define leaf methods; the methods don't
(and can't) chain.

In the test environment I want DeviceSim to intercept Device methods
("Device mixin add DeviceSim"):
AppDevice --> DeviceSim --> Device

But what I get is:
DeviceSim --> AppDevice --> Device

Since both Device and DeviceSim have leaf methods, adding DeviceSim as
mixin to Device breaks AppDevice. It's the documented behavior, but it
doesn't feel like the right behavior. The behavior I wanted (and what my
code expressed) was to intercept Device methods not AppDevice methods. I
don't see any way to limit interception to the subset of the hierarchy
that I want.

Is what I'm trying to do unreasonable? It feels like I'm using the
language features as intended, I just don't get the desired result.