[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Law of good style for CLOS
- To: commonloops.pa@Xerox.COM
- Subject: Law of good style for CLOS
- From: jrose@Sun.COM (John Rose)
- Date: Fri, 10 Jun 88 11:55:55 PDT
- In-reply-to: karl lieberherr's message <8806092123.AA12444@corwin.CCS.Northeastern.EDU>
- Redistributed: commonloops.pa
I am very interested in your feedback regarding the understandability
of our formulation of the Law of good style.
Ok, I'll bite.
Try a negative formulation. It seems like you are allowing
every kind of argument __except__ those that potentially break
abstraction boundaries. Classes local to the method are deemed
to drop their abstraction boundaries inside the method.
For me, the key illuminating comment on your Law was this:
The idea is that it is a bad strategy to put a dependency on the
C class into this method which is "attached to" A and Z.
This is a start at a negative formulation, which is why it helped
me. Then again, maybe I don't understand your Law at all.
How about this for a positive formulation:
Any slots used must be in one of the method's local classes.
A "local" class is one which is used as an argument selector.
That's approximately the rule of C++: You get privileged access
to a class, not to an instance.
You might want to go farther:
Any slot accesses used must be applied to objects whose
class is known. The principal (but not sole) means by
which an object's class is known is the argument class
specification (which is known to be enforced by method
selection).
I.e., you get privileged access to instances whose types are
declared and checked. Perhaps the mode of declaration is
restricted to method argument lists, perhaps not.
Note the emphasis on slots. Access to a slot through a generic
function is completely different from access through a slot
primitive. Only the latter type of access can break CLOS
abstraction boundaries.
A useful tool idea: Given a piece of code (e.g., a method),
automatically determine which classes it depends on knowing
the slots of. This would be done by class inference on arguments
to slot primitives.
General problem: When a representation changes, what pieces of
code need to be recompiled? Or possibly rewritten? It looks
like this Law is intended to keep these sets of code pieces
small and easily determinable. "Small" I think is a good goal;
"easily determinable" is not so important, if the tool of the
previous paragraph is available.
As an example of a less easily-determinable class representation
dependency, consider this code:
(DEFCLASS X () (X-SLOT))
(DEFCLASS Y () (Y-SLOT))
(TYPECASE MY-X-OR-Y
(X (SLOT-VALUE MY-X-OR-Y 'X-SLOT))
(Y (SLOT-VALUE MY-X-OR-Y 'Y-SLOT)))
It seems to me that this code is as semantically clean as the
equivalent formulation with methods:
(DEFMETHOD INSTEAD-OF-TYPECASE ((MY-X-OR-Y X))
(SLOT-VALUE MY-X-OR-Y 'X-SLOT))
(DEFMETHOD INSTEAD-OF-TYPECASE ((MY-X-OR-Y Y))
(SLOT-VALUE MY-X-OR-Y 'Y-SLOT))
The representation-dependency detection tool would find
both kinds of dependency on X and Y.
I think the TYPECASE formulation is better style, don't you?
-- John