This introduction is intended to give the reader a general introduction to what Demeter is, its concepts and principles, and where to find more detailed information about the Law of Demeter (LoD), the Demeter method, the Demeter project, and Adaptive Programming (AP).
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. The URL for the Demeter project (its "home page" on the web) is http://www.ccs.neu.edu/research/demeter/. There is also a "Law of Demeter" link from the Demeter home page at http://www.ccs.neu.edu/home/lieber/LoD.html.
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 doesn't need to change because the condition of A to C via "x" is still correct. The structure needs to be updated, but not the method implementation.
This is "Adaptive Programming", it makes your programs more flexible, 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 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:
- itself
- its parameters
- any objects it creates/instantiates
- its direct component objects
The basic idea is to avoid invoking methods of a member object that is returned by another method. When you do this, you make 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. If the "returned" object isn't a subpart of the object whose method was invoked, nor of some other object, then it typically is not a violation of LoD to invoke a method of the returned object (particularly if the object was created by the invoking method).
Using the Law of Demeter ("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 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). This problem is addressed by the Demeter tools, which automate the solution.
There is also a "Law of Demeter for Adaptive Programs" (abbreviated LoD-AP). LoD-AP 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 mentioned several paragraphs back). I took a graduate course from Dr. Lieberherr on Demeter. My "term project" developed a Law of Demeter for wrappers (LoD-W) and for propagation patterns (LoD-PP), and devised a metric to indicate the relative "structure-shyness" of a propagation pattern. Anyone interested in a copy of this paper can send me email (its pretty "dry" reading IMHO). Dr. Lieberherr renamed my proposed LoD-W to LoD-AP and re-stated it slightly.
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 constraints 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 tools, lift object-oriented programming to a higher level of abstraction by allowing the user to focus on the essential classes in a network and the invariants among their relationships.
Hence, the 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 constraints). 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.
The Demeter method and tools address this deficiency. They let us use protocols that specify only the preconditions, postconditions, and invariants not only for a single object method, but also for the entire family of actors that collaborate to carry out the entire "logical operation". Demeter's "succinct traversal specifications" allow us to encode _only_ the source, destination, and key intermediate members (invariants) of an information access (non-trivial data-flow) without having to know about all the non-critical links in the chain. So when the non-critical links come and go (or otherwise "evolve") no manual effort is required to for us to adapt to this change. The traversal invariant still holds, and only the changes to the class graph need to be made. The same codification of behavior still works simply by re-compiling the program using the Demeter tools (no procedural changes were necessary).
The Demeter tools' syntax may seem a bit unsettling at first, but it allows you to get the same or greater functionality by assuming "less" information. The less you have to assume, the less you need to know and depend on. The less you have to know, the simpler things should be. And, of course, the fewer dependencies you have, the more maintainable, reusable, adaptable (and hence durable) your program will be.
So if you have a method that takes a "BigMac" as an argument and needs to access the seeds on the pickles, you don't have to know about the lettuce, onions, and sesame seed bun that are all "on route" to the pickle seeds (much less that there are 2 all beef patties lurking underneath all of that), all you need to know is that a path exists from the BigMac to its pickle seeds. You don't have to know what that path is or exactly how to traverse it, and you don't have to encode that path in your methods. That way when the burger later changes such that the pickles are now on top of the onions instead of the other way around, you don't have to care.
They present a bunch of design/programming guidelines and rules for writing classes and class libraries to make them into reusable class frameworks (usable by client subclasses as well as "normal" clients). Some of the rules they propose are:
These two are just a sample of some of the "rules" mentioned in the article. Anyway, to me at least, 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.