liveBook · Manning

Law of Demeter

As explained in Software Design for Python Programmers

The Principle of Least Knowledge is a design principle that minimizes a class's knowledge of other classes' implementations and thereby reduces dependencies between classes.

The Law of Demeter, also called the Principle of Least Knowledge, minimizes dependencies by making a class know as little as possible about other classes’ implementations. Encapsulation hides changeable details behind public operations, so implementation changes do not propagate unnecessarily. section 5.1 section 4.2.2

Allow a method to call another object when the object is close to the method:

  • Call a method on an object aggregated by the current class. section 5.6
  • Call a method on an object passed as the current method’s argument. section 5.6
  • Call a method on an object instantiated by the current method. section 5.6
  • Avoid calling a method on an object returned by another object’s method; that creates a dependency on a farther-away class. section 5.6

Servicing an automobile

In the DemeterAuto example, maintain_auto() safely calls self._engine.replace_sparkplug() because Engine is an aggregated object and exposes the operation it owns. It also safely calls replace() on a passed plug or a newly created Sparkplug. By contrast, retrieving self._engine.sparkplug and then calling plug1.replace() reaches through Engine to its internal object and violates the law. Prefer Engine.replace_sparkplug() over exposing the sparkplug and its implementation. section 5.6

Listing 5.18 (Program 5.7 DemeterAuto): auto.py
class Sparkplug:
    def __init__(self, name):
        self._name = name

    def replace(self):
        print(f'Replaced sparkplug {self._name}')

class Engine:
    def __init__(self, sparkplug):
        self._sparkplug = sparkplug

    @property
    def sparkplug(self): return self._sparkplug

    def replace_sparkplug(self):
        self._sparkplug.replace()    #1

class DemeterAuto:
    def __init__(self, engine):
        self._engine = engine

    def service_sparkplug(self, plug):
        plug.replace()    #2

    def maintain_auto(self):
        self._engine.replace_sparkplug()    #3

        plug1 = self._engine.sparkplug
        plug1.replace()    #4

        plug2 = Sparkplug('plug2')
        plug2.replace()    #5

Compare compliant and noncompliant calls in the DemeterAuto, Engine, and Sparkplug implementation. section 5.6

How Software Design for Python Programmers covers it

How deep it goes
Defines four method-call rules and demonstrates their consequences, but stops short of formal metrics for coupling.
Examples
Uses Catalogue, Attributes, Book, DemeterAuto, Engine, and Sparkplug examples to contrast delegation with chained access.
What it assumes
Assumes basic classes, objects, methods, and instance variables while teaching coupling and implementation hiding through examples.
What you can do after
Evaluate method calls for problematic object reach-through and design narrower public operations that preserve implementation freedom.
How it connects
Connects encapsulation, loose coupling, delegation, and the Principle of Least Knowledge.

Also explained in

Compare how 2 books explain Law of Demeter →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Software Design for Python Programmers. The section links point to the parts of the book it draws on.