Law of Demeter

From CSSEMediaWiki
Revision as of 01:21, 8 October 2008 by Dominic Winkler (Talk | contribs)
Jump to: navigation, search

The Law of Demeter says that an object cannot request services from an object via a different object.

"More formally, the Law of Demeter for functions requires that a method M of an object O may only invoke the methods of the following kinds of objects:

  1. O itself
  2. M's parameters
  3. any objects created/instantiated within M
  4. O's direct component objects" --[Wikipedia]

A common (but certainly not the only) indicator of a violation of the law in some languages is more than one dot in a line of code, for example man.getTrousers().checkPocketContents().

Contents

Consequences

A violation of the Law of Demeter means that the caller object is dependant on the internal structure of the object it accesses. In the above example, if the Trousers class were to change (to say, Shorts, or perhaps a more abstract piece of clothing) the original caller would need to be updated.

Solution

The best solution is to write wrapper methods in the class to allow callers to ask that class for information about objects it contains. Unfortunately this may mean the class presents a very large public interface.

Example

Consider a simple graphics example. A 3D scene contains a number of point clouds (amongst other things which we'll ignore). Each PointCloud consists of a number of vertices. Here is the class diagram initially:

Demeter.png

In this design, if a Scene requires a PointCloud to be displayed it will need to get the list of vertices from the PointCloud first. Then it can display each vertex in turn. In this case, it should seem fairly obvious that something is wrong. In fact, the Law of Demeter has been violated, since the Scene obtains vertices through the PointCloud and calls their method. If the PointCloud were to change how it is composed, then Scene will most likely need to be modified (unless getVertices is modified to create a list from the new representation, but this could be messy). The solution in this case is fairly simple. PointCloud requires a display() method which displays each of its vertices. Scene can then simply call this method. The (slightly) modified version is shown below:

Demeter2.png

Example 2

This first design does not adhere to the Law of Demeter.

Carengine1.jpg

This is because to start the car you would have to execute the following line of code...

  car.getEngine().start()

The Law of Demeter states that generally more than one dot in a line of code is a sign that the law has been broken.


This design adheres to the Law of Demeter because the Car is handling the starting of itself (in the start() method) instead us having to specifically get the engine and tell it to start.

Carengine2.jpg


start()
{
    engine.start();
}

See also

Personal tools