The Law of Demeter (LoD) and how it should be used 9/19/2018 SE/LoD Copyright, 1996 © Dale Carnegie & Associates, Inc.
Overview Law of Demeter Principle How it was used at Citibank, JPL etc. Recommendation Benefits Review of Benefits 9/19/2018 SE/LoD
Law of Demeter What is it: Style Rule for building object-oriented systems. Proposed by my research group: The Demeter Research Group in 1987, published in 1988. Covered in many major books on OO design and programming. 9/19/2018 SE/LoD
Law of Demeter Principle Each unit should only use a limited set of other units: only units “closely” related to the current unit. “Each unit should only talk to its friends.” “Don’t talk to strangers.” Main Motivation: Control information overload. We can only keep a limited set of items in short-term memory. 9/19/2018 SE/LoD
Law of Demeter FRIENDS 9/19/2018 SE/LoD
“closely related” 9/19/2018 SE/LoD
Application to OO Unit = method closely related = methods of class of this/self and other argument classes methods of immediate part classes (classes that are return types of methods of class of this/self) In the following we talk about this application of the Law of Demeter Principle to OO: example follows in a few slides. 9/19/2018 SE/LoD
Citibank Quote: Law of Demeter The Law of Demeter forms one of the cornerstones of the design approach of the Global Finance Application Architecture (quote from: Global Finance Application Architecture: Business Elements Analysis, Oct. 1991, Citibank confidential document) Widely used in big projects, for example, at JPL for the Mars exploration software. 9/19/2018 SE/LoD
Jet Propulsion Laboratory(JPL) Quote: Law of Demeter The Law of Demeter … has taken a firm hold in many areas of JPL. Major systems which have used LoD extensively include … Mars Pathfinder Software (begun in 1993). We are going to use LoD as a foundational software engineering principle for the X2000 Europa orbiter mission. 9/19/2018 SE/LoD
What others say about the Law of Demeter To get a better understanding Booch Rumbaugh 9/19/2018 SE/LoD
Booch and the Law of Demeter Context Chapter: Classes and Objects, Section: On Building Quality Classes and Objects, Subsection: Choosing Relationships 9/19/2018 SE/LoD
Booch and the Law of Demeter Quote: The basic effect of applying this Law is the creation of loosely coupled classes, whose implementation secrets are encapsulated. Such classes are fairly unencumbered, meaning that to understand the meaning of one class, you need not understand the details of many other classes. 9/19/2018 SE/LoD
Rumbaugh and the Law of Demeter Context Chapter: Programming Style, Section: Extensibility 9/19/2018 SE/LoD
Rumbaugh and the Law of Demeter Quote: Avoid traversing multiple links or methods. A method should have limited knowledge of an object model. A method must be able to traverse links to obtain its neighbors and must be able to call operations on them, but it should not traverse a second link from the neighbor to a third class. 9/19/2018 SE/LoD
Law of Demeter (alternative formulation) A method should have limited knowledge of an object model. Leads to another Demeter favorite: Use grammars to define both class structure and an application-specific language. See the Structure-Shy Object Pattern. 9/19/2018 SE/LoD
Agreement that LoD Good Idea How to follow LoD: good solutions exist but not widely known. Two approaches to following LoD: OO approach Adaptive approaches Traversal support APPC Demeter/Java 9/19/2018 SE/LoD
The Law of Demeter (cont.) Violation of the Law class A {public: void m(); P p(); B b; }; class B {public: C c; }; class C {public: void foo(); }; class P {public: Q q(); }; class Q {public: void bar(); }; void A::m() { this.b.c.foo(); this.p().q().bar();} 9/19/2018 SE/LoD
Violations: Dataflow Diagram 2:c foo() 1:b B C A 4:q() bar() 3:p() P Q 9/19/2018 SE/LoD
Adaptive Following of LoD void A::m() { (C) Traversal.long_get(this,”A->C”).foo(); (Q) Traversal.long_get(this,”A->Q”).bar();} this.b.c.foo(); this.p().q().bar();} // violation 9/19/2018 SE/LoD
OO Following of LoD m foo2 c foo() 1:b B C A 2:foo2() 4:bar2() bar2 3:p() q() P Q 9/19/2018 SE/LoD
Adaptive Following LoD C A FRIENDS a S X c b a:From S to A b:From S to B c:From S via X to C 9/19/2018 SE/LoD
Motivation OOAD Implementation --> Tangling Collab-1 C1 C4 C2 C3 C5 Z C1 C4 C2 C3 C5 Collab-4 Collab-2 Collab-3 C1 C2 C3 C4 C5 Object-oriented languages do not provide adequate constructs to capture collaborations between several classes. Has been recognized in different forms in the object-oriented community: OO accommodates the addition of new variants of data types better than procedural programming but, the opposite is true when new operations on existing data types are needed visitor pattern: the matter of concern -- definition of new operations on an existing object structure (aggregation is involved besides inheritance) several works complain the lack of constructs for expressing collaboration-based designs Implementation Collaboration -- a distinct (relatively independent aspect of an application that involves several participants, or roles roles played by application classes each class may play different roles in different collaborations each role embodies a separate aspect of the overall class behavior --> Tangling 9/19/2018 SE/LoD Collaboration-based design s Require to view oo applications in two different ways: (a) in terms of participants or types involved (b) in terms of the tasks or concerns of the design
What is the Problem? “OO technology has not met its expectations when applied to real business applications partly due to the fact that there is no place where to put higher-level operations which affect several objects. … if built into the classes involved, it is impossible to get an overview of the control flow. It is like reading a road map through a soda straw'’ [Lauesen, IEEE Software, April ‘98] 9/19/2018 SE/LoD
Recommendation I recommend that you use the Law of Demeter Principle in OO designs and programs and that the Law of Demeter be followed in an adaptive, collaboration-based style (Demeter style). 9/19/2018 SE/LoD
Benefits of following Law of Demeter in Demeter Style robustness to changes shorter programs design matches program more understandable code, intent in program partially automated evolution keep all benefits of OO technology improved productivity ideas can be used without tools Applicable to design and documentation of your current systems with immediate benefits. 9/19/2018 SE/LoD
Benefits Review Robustness to changes: Elimination of violations of LoD in OO style leads to many tiny methods. Statistics from (Wilde, Matthews, Huitt, 1993): More than half of the member functions and methods have fewer than two C++ statements or four Smalltalk lines of code. Those tiny methods will be generated. 9/19/2018 SE/LoD
Benefits Review Shorter programs : Tiny methods observed by Wilde et al. don’t have to be written and maintained. Programs get shorter. 9/19/2018 SE/LoD
Benefits Review Partially automated evolution: tiny traversal methods are automatically regenerated when structure changes. Programmer needs to test them. 9/19/2018 SE/LoD
Benefits Review Keep all benefits of OO technology: all code is written in plain Java with a traversal package added. You can use all good ideas of OO technology. 9/19/2018 SE/LoD
Benefits Review Improved productivity: Several testimonials. Example: Hewlett-Packard Printer Installation Software is written in Demeter Style using C++. Televised Demeter class with student in Vancouver, Canada, lead to prototype. Prototype was so successful that entire package was re-implemented. 9/19/2018 SE/LoD
Dangers if Law of Demeter Principle not followed adaptively OO programs might get as hard to maintain as procedural programs because structural information will be duplicated many times. Code will be tangled: hard to understand and to maintain. 9/19/2018 SE/LoD
Law of Demeter Style rule for OOP Goals promote good oo programming style minimize coupling between classes; precursor of structure-shyness minimize change propagation facilitate evolution 9/19/2018 AOO / Demeter
Formulation (class form) Inside method M of class C one should only call methods attached to (preferred supplier classes) the classes of the immediate subparts (computed or stored) of the current object the classes of the argument objects of M (including the class C itself) the classes of objects created by M 9/19/2018 AOO / Demeter
Metric: count number of violations of Law of Demeter class version can be easily implemented large number of violations is indicator of high maintenance costs class version allows situations which are against the spirit of the Law of Demeter 9/19/2018 AOO / Demeter
Preferred supplier objects of a method the immediate parts of this (computed or stored) the method’s argument objects (which includes this) the objects that are created directly in the method 9/19/2018 AOO / Demeter
Why object form is needed A = B D E. B = D. D = E. E = . class A { void f() { this.get_b().get_d().get_e(); } 9/19/2018 AOO / Demeter
Formulation (object form) Inside a method M we must only call methods of preferred supplier objects (for all executions of M). Expresses the spirit of the basic law and serves as a conceptual guideline for you to approximate. 9/19/2018 AOO / Demeter
Object Form A = B D E. B = D. D = E. E = . a1:A b1:B d1:D e1:E d2:D class A { void f() { this.get_b().get_d().get_e(); } e3:E not a preferred supplier object 9/19/2018 SE/LoD
Object Form A = B D E. B = D. D = E. E = . a1:A b1:B d2:D e2:E class A { void f() { this.get_b().get_d().get_e(); } e3:E is a preferred supplier object (through aliasing) 9/19/2018 SE/LoD
Still can go against the spirit! class A { void f() { g(this.get_b().get_d()); } void g(D d) {d.get_e();} satisfies object form of LoD but still violates the spirit. class A { void f() { this.get_b().get_d().get_e(); } 9/19/2018 SE/LoD
Context switch 9/19/2018 AOO / Demeter
Assuring Good Style for Object-Oriented Programs Lieberherr and Holland, 1989, IEEE Software Objective: To improve encapsulation and modularity with a new programming rule called “Law of Demeter”. Definitions: Supplier object/class Preferred supplier object/class Three Forms of the Law of Demeter Object Form Strict Class Form Minimization Class Form [Lieberherr and Holland, 1989]
[Lieberherr and Holland, 1989] Style for OO Programs Principles the Law uses Coupling Information hiding Information restriction Localization of information Structural induction Benefits of implementing the Law Maintainability Understandability Use of modularity Smaller modules Predictable message-passing patterns [Lieberherr and Holland, 1989]
Style for OO Programs (Continued) Example Demeter System™, Demeter Research Group at Northeastern University Extension of Parnas’ work Different method to achieve the same goals of maintainability and understandability Implements Parnas’ work on information hiding, and extends this method to include all classes (assumes all classes may be modified) Differentiates between information hiding and information restriction. [Lieberherr and Holland, 1989]
Context switch 9/19/2018 SE/LoD
Chapter 5 Bend or Break 9/19/2018 SE/LoD
Bend or Break Life does not stand still We need to make every effort to write code that is as loose – as flexible – as possible Reversability: how to make reversible decisions 9/19/2018 SE/LoD
Bend or Break Decoupling and the Law of Demeter Keep separate concepts separate Write less: good way to stay flexible Metaprogramming: how to move details out of the code completely Temporal Coupling: do not depend on absolute time 9/19/2018 SE/LoD
Bend or Break Just a view: decouple models from views. Blackboards: provide a meeting place where modules exchange data. 9/19/2018 SE/LoD
Decoupling and the Law of Demeter Writing shy code (see also Orthogonality and Design by Contract) 9/19/2018 SE/LoD
Use Join Point Terminology Makes checking amenable to a dynamic approach. Join point: point in the dynamic call graph (e.g. a call, an execution, a setting of a data member, a constructor call, etc.). 9/19/2018 SE/LoD
Kinds of join points A lexical join point is a site in the program text. A dynamic join point is an event in the execution of the program. Shadow is a function from dynamic to lexical join points, which maps a dynamic join point to its lexical shadow. 9/19/2018 SE/LoD
Style Rules as Predicates on Join Points Let (P) denote the set of lexical join points in a program P. Let [](P) denote the set of dynamic join points in an execution of P. For a dynamic join point J[d][](P), we define P(J[d]) to be the lexical join point corresponding to J[d], called the shadow of J[d]. 9/19/2018 SE/LoD
Join Point Predicates Let P2^P be a predicate on lexical join points in P. Let (P) 2^[](P) be a predicate on dynamic join points in the execution of P. 9/19/2018 SE/LoD
Object Form of LoD as dynamic join point predicate Definition OF-LoD: A OF-LoD join point is a method-call join point in which the target object is either: An instance variable of the "this" object. Constructed by the method. An argument of the method. Returned by a message sent to “this”. 9/19/2018 SE/LoD
Class Form of LoD as dynamic join point predicate Definition CF-LoD: A CF-LoD joinpoint is a method-call join-point, in which the target object’s class is either: The static type of an instance variable. The static type of a newly constructed object. The type of an argument of the method. The return type of a method of the class. 9/19/2018 SE/LoD
Lifting dynamic to lexical Given is a dynamic join point predicate (P). We define the associated lexical join point predicate P as follows: A lexical join point JlP in program P violates predicate P, if there exists an execution of P with a dynamic (P)-violation for some dynamic join point Jd such that the shadow of Jd is Jl. 9/19/2018 SE/LoD
Satisfaction per program A program P satisfies the dynamic join point predicate (P) for execution , if all dynamic join points in satisfy (P). A program P satisfies the lexical join point predicate P, if, for all executions of P, P satisfies (P). 9/19/2018 SE/LoD
Complexities of predicates Both the class and object form of the LoD are defined in terms of a dynamic join point predicate. To each of those dynamic join point predicates corresponds a lexical join point predicate. We have for satisfaction per program: Satisfy OF-dynamic for execution (polynomial), Satisfy CF-dynamic for execution (polynomial), Satisfy OF-lexical (undecidable) and Satisfy CF-lexical (polynomial) 9/19/2018 SE/LoD
Forms of LoD lifting lifting forms class (c) object (o) lexical(l) CF (polynomial) OF (undecidable) dynamic(d), AspectJ CF per exection (polynomial) OF per execution (polynomial) lifting lifting 9/19/2018 SE/LoD
Forms of LoD forms class (c) object (o) static(s), Prog. Anal. useful (c/s), simple definition useful (o/s), approximates o!! dynamic(d), AspectJ not useful (c/d), c/s instead most useful (o/d), 9/19/2018 SE/LoD
Old slides 9/19/2018 SE/LoD
Dynamic X-Violation X: a property on join points; e.g. OF-LoD. Definition X-Violation for method call: A method-call in P is a X-violation if there exists an execution of P where a join point corresponding to the method-call does not satisfy property X. 9/19/2018 SE/LoD
Satisfaction Definitions A program P satisfies X for execution E if for all method-calls in P, the corresponding join points of E satisfy property X. A program P satisfies X if for all executions of P for all method-calls in P the join points corresponding to the method-calls satisfy property X. 9/19/2018 SE/LoD
Object Form Violation OF-LoD-Violation: X = OF-LoD. An undecidable property. We go for proving statements of the form: program P satisfies style rule X for execution E. 9/19/2018 SE/LoD
Class Form Violation CF-Lod-Violation: X = CF-LoD. 9/19/2018 SE/LoD
Notes o/s: if an illegal message sending is possible assuming each decision taken both ways and each loop is executed 0 or more times. c/d: not interesting, because c/s. If dynamically: do o/d 9/19/2018 SE/LoD
Note The following: aFoo.getPart().getPart(). getBar().getBp().test(); Should not be allowed in a static method. Next follows a generalization of LoD to static methods (slide after next). Do you agree? 9/19/2018 SE/LoD
Object form for regular methods Within a method, messages can only be sent to the following objects: 1. A parameter of the method, including the enclosing object (this or self); 1.1. For pragmatic reasons: a global object; 2. An immediate part object (computed or stored): 2.1 An object that a method called on the enclosing object returns, including attributes of the enclosing object; 2.2 An element of a collection which is an attribute of the enclosing object; 3. An object created within the method. 9/19/2018 SE/LoD
Object form for static methods Within a static method, messages can only be sent to the following objects: 1. A parameter of the method, including the current class; 1.1. For pragmatic reasons: a global object; 2. An immediate static part object (computed or stored): 2.1 An object that a static method called on the current class returns, including static attributes of the current class; 2.2 An element of a collection which is a static attribute of the current class; 3. An object created within the method. 9/19/2018 SE/LoD