---------------------------------------------------------------------------- Subject: Re: (OTUG) Law of Demeter ??? From: bradapp@enteract.com To: otug@rational.com (Object Technology user's group) Date: Wed, 2 Apr 1997 11:01:09 -0600 (CST) nkirby@spss.com writes: > I've been reading Doug Lea's book on Concurrent Programming and on page > 219 he refers to "the law of Demeter, an OO programming guideline for > maintaining locality and modularity". I personally have never heard of > this law. Does anyone on this news group know it ? If so could you > please inform me what it is. The "Law of Demeter" refers to a paper that was published in IEEE Software in 1989. Lieberherr, Karl. J. and Holland, I. Assuring good style for object-oriented programs IEEE Software, September 1989, pp 38-48 There are also some other articles about the same time period 1988-89) in various issues of ACM SIGPLAN Notices, usually authored by one or more of Karl Lieberherr, Ian Holland, and Arthur Riel. For starters, Demeter is a research project at Northeastern University lead by Dr. Karl Lieberherr. I believe there is also work going toward a commercial implementation of the Demeter project (www.tendril.com). The URL for the Demeter project is: http://www.ccs.neu.edu/research/demeter/ There is also a "Law of Demeter" link from the Demeter home page (given above) at: http://www.ccs.neu.edu/home/lieber/LoD.html The Demeter method and project is about what Lieberherr calls "Adaptive Programming" (abbreviated AP). AP deals with specfying the connections between objects as loosely as possible (this is called "structure-shy" programming). The Demeter system and tools are all about "Adaptive" programming. It as an extension of OOP that attempts to wait to bind algorithms to data-structures until as late as possible. A special kind of language supported by the Demeter tools to work with other OOPLs, lets you write "adaptive" programs that try to express things like: starting from object A, go to object C via all objects with an attribute named "x". Thus, the precise details about going from A to Z to Q to P to M and then to C, are "distilled" into the above "traversal specification" which tries to represent the essence of what is really required at a more generic level. Hence, if your class hierarchy structure or network changes so that the exact path that was used for the above "access" (A -> Z -> Q -> P -> M -> C) now has changed to encompass new classes or more paths, the actual code for the algorithm or behavior doesnt need to change because the condition of A to C via "x" is still correct. The structure needs to be updated, but the method implementation does not. This is "Adaptive Programming", it makes your programs more flexible, and more resilient to change, and more adaptable to varying configurations of classes within a given domain. Lieberherr has written a book on Adaptive programming: Adaptive Object-Oriented Software: The Demeter Method with Propagation Patterns by Karl J. Lieberherr PWS Publishing Company, Boston, 1996, ISBN: 0-534-94602-X" The "Law of Demeter" (or LoD) as it is commonly called, is really more precisely "Law of Demeter for Functions/Methods" (LoD-F). It is a design-style rule for object-oriented programs. Its essence is the "principle of least knowledge" regarding the object instances used within a method. The idea is to assume as little as possible about the structure and properties of instances and their subparts. Thus, it is okay for me to request a service of an objects instance, but if I reach into that object to access another sub-object and request a service of that sub-object, I am assuming knowledge of the deeper structure of the original object that was made available to me. The Law of Demeter says that if I need to request a service of an objects sub-part, I should instead make the request of the object itself and let it propagate this request to all relevant sub-parts, thus the object is responsible for knowing its internal make-up instead of the method that uses it. Stated more formally, the Law of Demeter for functions says that: A method "M" of an object "O" should invoke *only* the the methods of the following kinds of objects: 1. itself 2. its parameters 3. any objects it creates/instantiates 4. its direct component objects The basic idea is to avoid invoking methods of an object that is returned by another method. When you do this, you are making some structural assumptions about the container object that may be likely to change. The container may later need to be modified to contain a different number of the contained objects, or it may end up being changed to contain another object which contains the original component object. Thus using the Law of Demeter (abbreviated as "LoD") you instead ask the container to invoke a method on its elements and return the result. The details of how the container propagates the message to its elements are encapsulated by the containing object. A side-effect of this is that if you conform to LoD, while it may quite likely increase the maintainability and "adaptiveness" of your software system. you also end up having to write *lots* of little wrapper methods to propagate methods calls to its components (which can add noticeable time and space overhead). There is also a "Law of Demeter for Adaptive Programs" (abbreviated LoD-AP). Which is a style guideline for how to form your traversal specification. I have also seen some discussion about a Law of Demeter for Strategies (which I believe is on-line at the LoD URL meniotned several paragraphs back). At present, the Demeter tools and method are the subject of many papers and workshops. Demeter tools have been implemented to work with C++, Java, Tcl/Tk, and Perl 5. There are also several design patterns for adaptive programming. The Demeter tools for Java make use of "adaptive visitors" objects which are AP analogs of the GoF "visitor" pattern. The visitor objects are responsible for carrying out the traversal specification. The adaptive visitors are a more seamless fit with OOPLs than a relational-ish graph-navigation-specification language. Before the adaptive visitor objects were used, Adaptive C++/Demeter programs looked kind of like SQL-style from-to statements and contraints with embedded C++ code (or vice versa). Now (with Java and adaptive visitors) they look more like a single language rather than two mixed together AP in general, and the Demeter method and tool, lift object-oriented programming to a higher level of abstraction by allowing the user to focus on the essential and stable classes and the invariants among their relationships. One uses a "class graph" of a system to indicate all the inheritance and containment relationships between objects in the system. The graph can be represented textually as a grammar. If the "grammar" is LL(1) (or can be reduced to an LL(1) grammar -- which is usually the case) then there are lots of nice properties it has that lets the Demeter tools determine and automate all sorts of nice things for you. Hence, the basic gist of it is that if you need to code a method that has to navigate (via other methods and/or objects) across several links and intermediate links to process information, then using the Demeter tools, you (the "adaptive programmer") rarely have to concern yourself with knowledge of any objects along the navigation path other than the source and destination classes/vertices and perhaps some (but not all) key intermediate objects/vertices. The Demeter tools can generate all the intermediate navigations from the class graph and your from-to spec (with optional contraints). Later, when your class graph evolves and changes, the code for the method you wrote doesn't need to be modified at all (since you specified it "adaptively" as a propagation pattern using succinct traversal specifications). All you usually need to do is just regenerate the traversal code with Demeter and then recompile. An interesting article that seems to be related to LoD is in the ROAD section of the November/December 1996 issue of JOOP (Volume 9, No. 7). It is entitled "Building reusable classes for frameworks" by Gary Brown and Peter Forte. The article doesnt actually make any mention of Demeter or LoD but it has a number of guidelines that I think are actually more detailed refinements or applications of LoD. They present a bunch of design/programming guidelines and rules for writing classes and class libraries to make them into reusable class frameworks (useable by client subclasses as well as "normal" clients). Some of the rules they propose are: 1. Whenever an object needs to request a service of some other external object, this external service request should be encapsulated in an internal non-public method of the object. This allows derived classes to override the service request with a more specialized one (it is also a use of the GoF Template pattern). 2. Whenever an object needs to instantiate some other externally associated object, it should do so using a non-public method to perform the instantiation. This allows derived classes to instantiate a more specialized object if needed. These two are just a sample of some of the "rules" mentioned in the article. Anyway, to me the authors seem to be extending the LoD with corollaries like: A *public* method M of a class C should invoke only its own public and private methods, and those of its superclasses. (Any non-public methods should obey LoD.) There are probably some other corollaries to LoD that can be implied from this article as well. -- Brad Appleton | http://www.enteract.com/~bradapp/ "And miles to go before I sleep." | 2500+ WWW links on CS & Sw-Eng Note: A new version of this document is under preparation