[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Let's take a break.

Based on Richard Gabriel's feedback:

Your poem is fun. I liked your reference to mountains:
I did grow up in them, in a small valley in Switzerland.

You recommend that our OOPSLA paper not discuss the application of the 
Law of Demeter to CLOS at all.

I am sorry but I cannot follow this recommendation. We (the Demter team)
believe in what we are doing, we stand to it and we don't hesitate to publish 
it. CLOS has given us the unique opportunity to generalize our original message 
passing Law from one dynamic method selection argument to several dynamic method
selection arguments. This generalization has given us further insight
into the role of the Law and we can get the old formulation back
by specializing the number of dynamic method selection arguments to one.
Based on Lanning's message from Xerox:

You made an important point which was also acknowledged by Gabriel.
Here is our point of view which makes clear where we disagree.
Let's assume we have a (non-generic) function op-res which takes as 
first argument an operator of type
  Operator : AddSym | MulSym.
plus two other arguments which are numbers.
Function op-res returns the value of applying the operator to the
two numbers.  We have provided this function to our users and 
given them the interface for the function.

Some time later, we decide to make the function generic in its first
argument. Should we inform the users about this change? (By the way,
in CLOS we are forced to make it generic in all three arguments since
all three are required.) The users might have used this function op-res
inside other methods and if we make now the first argument generic
the user's code might suddenly violate the Law. Why should the user
know about the fact that the first argument is generic now? The reason
is extensibility! The user has now an easy way to extend the op-res
function to other types and that is very useful knowledge for the
future modification of the user's program. 

When the function is generic in its first argument, its implementation must
look like: (pardon the new Flavors notation; this discussion is relevant
not only to CLOS but also to generic function
systems with only one dynamic method-selection argument (such as new Flavors)):
  (defmethod (AddSym op-res) (e1 e2) ... )
  (defmethod (MulSym op-res) (e1 e2) ... )
If the user wants to extend the domain of op-res, he/she just adds
another method. If the function is not generic, this won't work.

Therefore, we view the number of method selection arguments of a function
as part of the interface of that function along with the typing information
and a formal or informal specification.

non-distinction as a contribution of CLOS, while we view the fact that
we can have several method selection arguments as one (among many) contributions
of CLOS. 

What about the violation of the Law when we go from non-generic to
generic? Lets consider the following classes:
(Pardon the Demeter notation which is explained in IEEE Computer, June 88)
  A = <x> Compound.
  Compound = "(" <op> Operator <args> List(PrefixExp) ")".
Consider the method:

  (defmethod (A bad-style) (e1 e2) (op-res (op x) e1 e2))

which is identical before and after the transition from non-generic to generic.

Why is method "bad-style" in bad-style after the transition? 
Since it is attached to A AND 
since it contains a dependency on the subparts of the Compound class.
If Compound changes to

  Compound = "(" <additive-op> Operator <args> List(PrefixExp) ")".

we have to modify the semantics of class A, although class A did not change:

  (defmethod (A :bad-style) (e1 e2) (op-res (additive-op x) e1 e2))

This violates the principle of modularity.
Why is "bad-style" in good-style before the transition? 
It is the prerogative of the Law that
it can accept certain constructs which are in bad shape. We want to
have a Law without exceptions which is easy to remember and to follow.
We don't want to restrict non generic function  calls since 
we don't want to upset the Lisp or C programmers. 

Based on Gregor Kiczales' feedback:
CLOS and C++: There is certainly a huge difference between CLOS and
C++ but with respect to the Law, CLOS and C++ are not that far apart:

In C++ also all arguments are used to determine which method (called 
a member function) to execute.

The difference is that in C++ the argument types (after the first) are 
used to determine the member function at compile-time. I.e., C++ uses
static method selection.  The first argument in a method of a derived class
is used for implicit case analysis at run-time. 

In other words:
CLOS supports implicit case analysis on all required arguments, while
C++ supports implicit case analysis only on the first argument.
Both C++ and CLOS support function overloading on all required arguments.

For C++ the message passing formulation of the Law is appropriate.
We view the compile-time method selection of C++ due to overloading
as syntactic sugar. We could always rename the methods by prefixing
their names with argument types to avoid the need of overloading.
But CLOS is inherently more powerful: it does true implicit case
analysis on all the method selection arguments.
Therefore we need for CLOS the generalization of the Law as proposed.

>Since it seems to be difficult to explain the law in netmail, I look
>forward to the presentation at OOPSLA.  Until then, I will wait and
I agree! Let's pick up the discussion again at or after OOPSLA '88
and I am convinced that most of you will be converted to
faithful followers of the Law.

Thank you very much for your contributions of technical ideas and poems.
The Demeter team looks forward to seeing you at OOPSLA '88.

-- Karl