Montag, 3. Juni 2013

Das Gesetz von Demeter

Göttin Demeter (Quelle: Wikipedia)
Das Gesetz von Demeter (engl. Law of Demeter, LoD) gehört heute zur Allgemeinbildung des Informatikers. Seine "Entdecker", Karl J. Lieberherr und Ian M. Holland, waren aus heutiger Sicht erstaunlich euphorisch über seine Bedeutsamkeit:
"Wann weist ein objektorientiertes Programm guten Stil auf? Existiert eine Formel oder Regel, der man folgen kann, um gute objektorientierte Programme zu schreiben? Welche Metrik können wir für ein objektorientiertes Programm anwenden, um herauszufinden, ob es gut ist? Was sind die Eigenschaften eines guten objektorientierten Programms? - Im vorliegenden Artikel schlagen wir ein einfaches Gesetz vor, das wir das Gesetz von Demeter nennen, von dem wir glauben, dass es diese Fragen beantwortet." [Lieberherr1989]
Mehr als 20 Jahre später darf geschmunzelt werden. Und doch kann das LoD aus einer Reihe von Gründen als ein Musterbeispiel für ein gelungenes Prinzip der Softwaretechnik gelten:
  • Nicht durch die häufig in diesem Zusammenhang zitierte Studie [Basili1996], die das LoD nicht einmal erwähnt, aber schließlich durch [Guo2011] wurde die Korrelation zwischen Verstößen gegen das Prinzip und erhöhten Fehlerquoten empirisch nachgewiesen.
  • Das LoD ist formal präzise ausgearbeitet und kann in vielen objektorientierten Programmiersprachen mittels statischer Codeanalyse-Werkzeuge überprüft werden. Für Java existiert bspw. eine Implementierung innerhalb des Standardwerkzeugs PMD.
  • Das LoD ist vergleichsweise einfach umsetzbar. Verstöße können sogar mittels eines Refaktorisierungswerkzeugs ("Hide Delegate"-Refactoring) weitgehend werkzeugunterstützt beseitigt werden, siehe [Berens2011].
  • Das LoD basiert auf zahlreichen weiteren bedeutsamen Prinzipien, darunter dem Geheimnisprinzip, dem Prinzip der losen Kopplung und dem Lokalitätsprinzip.
Nichtsdestoweniger ist das LoD keineswegs unumstritten. Einige Nachteile des Prinzips werden unten im entsprechenden Abschnitt des Katalogeintrags aufgeführt. 

Ausgangspunkt: Eine objektorientierte Strukturanomalie
Bereits in der Arbeit [Lopes1996], an der auch Lieberherr mitwirkte, wurde Folgendes als Strukturanomalie (engl. structural anomaly) beschrieben: Einzelne Methoden objektorientierter Programmiersprachen arbeiten typischerweise nicht nur auf den Daten eines Objektes, sondern auf den Daten mehrerer verschiedener Objekte. Eine Methode sammelt auf diese Weise ein vergleichsweise großes strukturelles Wissen über fremde Objekte an und schwächt damit das Geheimnisprinzip, das durch das objektorientierte Paradigma eigentlich gefördert werden sollte. Der Begriff der Anomalie soll diesen der Objektorientierung inhärenten Widerspruch hervorheben. 

Die Anomalie kann auch auf hörerer Ebene verdeutlicht werden: Struktur und Verhalten sind wesentliche Aspekte jeder Software. In der Objektorientierung gehen diese Aspekte insofern eine enge Beziehung ein, als Klassen sowohl die grundlegende Struktur einer Anwendung bestimmen als auch die Implementierung des Verhaltens in Form von Methoden in sich tragen. Grundsätzlich wäre es wünschenswert, rein strukturelle Änderungen völlig unabhängig von Änderungen des Verhaltens durchzuführen. Die beschriebene Anomalie zeigte jedoch, dass dies in objektorientiert entwickelten Systemen selten möglich war: Auf Grund des hohen Strukturwissens vieler Methoden führten Strukturänderungen auch häufig zu umfangreichen Methodenänderungen, obwohl das eigentliche funktionale Verhalten kaum betroffen war.

Mit dem LoD glaubte Lieberherr einige Jahre später eine Lösung für diese Probleme gefunden zu haben.

Katalogeintrag
Name, Kurzform Gesetz von Demeter
Synonyme
Law of Demeter (LoD),
Prinzip des schüchternen Codes,
Prinzip der Verschwiegenheit,
Principle of Least Knowledge
Beschreibung
Das Prinzip wird bereits in [Lieberherr1988] in zwei Formen präsentiert:
  • Objektform
  • Klassenform, wiederum unterschieden in
    • strikte Form
    • minimierende Form (engl. minimization version)
Die folgenden Beschreibungen der beiden Formen sind wörtlich aus der sehr guten Darstellung in [Berens2011] übernommen:

Objektform
Eine Methode M des Objekts O darf an ein Objekt P nur dann eine Nachricht schicken, wenn einer der folgenden Fälle gilt:
  • P und O sind identische Objekte
  • P wurde als Parameter der Methode M übergeben
  • P wurde innerhalb der Methode M erzeugt
  • P ist ein Attribut von O
  • P ist ein globales Objekt“
[Berens2011]

Strikte Klassenform
Eine Methode M der Klasse A darf an eine Klasse B nur dann Nachrichten schicken, wenn einer der folgender Fälle gilt:
  • A ist Subtyp von B
  • B ist der deklarierte Typ eines Parameters der Methode M
  • Instanzen von B werden innerhalb der Methode M erzeugt
  • B ist der deklarierte Typ einer Instanzvariablen von A
  • B ist der deklarierte Typ eines globalen Objekts“
[Berens2011]

Minimierende Klassenform
Gegenüber der strikten Klassenform sind zusätzlich folgende Zugriffe erlaubt:
  • Gilt eine Klasse bzw. deren Klasseninterface als stabil, so darf auf die Methoden dieser Klasse von überall her zugegri en werden.
  • Ist es aus Gründen des Laufzeitverhaltens erforderlich, dass auf Methoden von Klassen direkt zugegri ffen werden muss, obwohl diese Klasse nicht unter die obige De finition fällt, so kann auch hier eine Ausnahme gemacht werden.
  • Methoden zur Objekterzeugung“
[Berens2011]
Erläuterung
Eine bekannte Kurzform dieses Prinzips lautet:
Sprich nur mit deinen engsten Freunden!“ 
Ebensohäufig findet man die Verkürzung auf das Vermeiden der Verkettung von Methodenaufrufen vor. Beide Kurzformen können allenfalls als Merkstützen dienen.

Nicht selten sind auch vermischte Darstellungen der Objekt- und Klassenform anzutreffen. Der Anwender des Prinzips sollte sich dieser Feinheiten bewusst sein.

Grundsätzlich gilt: Die Grundidee des Prinzips drückt sich in der Objektform aus. Bei Zweifeln, ob eine gegebene Methode gegen das LoD verstößt, sollte die Objektform konsultiert werden.

Zur Unterscheidung zwischen Objekt- und Klassenform merkt [Berens2011] an:

Ob ein gegebener Programmcode die Objektform des Law of Demeter einhält, kann statisch nicht exakt geprüft werden. Als eine Annäherung an die Objektform kann die Klassenform angesehen werden, die zur Kompilierzeit statisch geprüft werden kann.“
Beispiel(e)
Als Beispiel kann hier die Darstellung des Hide Delegate-Refactorings aus [Berens2011] dienen.

Aus dem Methodenaufruf des Clients

server.getDelegate().doSomething()

wird so

server.doSomething()
Historie
Lieberherr und Kollegen beschäftigten sich Ende der 80er Jahre mit den Auswirkungen veränderlicher Klassenstrukturen. In den damals gängigen objektorientierten Programmiersprachen (in [Lieberherr1989] werden explizit C++, Common Lisp Object System, Eifffel, Flavors und Smalltalk-80 genannt) beobachteten sie die oben bereits beschriebene Strukturanomalie und suchten nach Möglichkeiten, systematisch mit kontinulierlichen Strukturänderungen umzugehen.

Diese Bemühungen resultierten im Demeter-System, über das sie in [Lieberherr1989] schreiben:
Eines der wesentlichen Ziele des Demeter-Systems ist es, eine Umgebung zu entwickeln, welche die Evolution einer Klassenhierarchie vereinfacht. Eine solche Umgebung muss Werkzeuge bereitstellen, welche die einfache Aktualisierung existierender Software (der Methoden oder Operationen in dieser Klassenhierarchie) ermöglicht. Wir streben nach einer Umgebung, in der Software in kontinuierlicher Weise wachsen kann statt nur gelegentlichen Versionssprüngen zu unterliegen, welche unzweifelhaft zu umfangreichen Quellcodeänderungen führt.“
Dieses Streben nach einem kontinuierlichen Wachsen drückt sich auch im Bezug auf die Göttin Demeter aus, die für Fruchtbarkeit und Wachstum steht. Die Wahl des Namens erfolgte allerdings zunächst aus profaneren Gründen:
Das Demeter-Projekt benannten wir nach Demeter, da wir gerade an einer Hardware-Beschreibungssprache namens Zeus arbeiteten. Wir suchten nach einem Werkzeug, um die Implementierung von Zeus zu vereinfachen. Also suchten wir nach einem Namen, der zu Zeus in einer Beziehung stand, und wählten eine von Zeus' Schwestern: Demeter.“ [URL: What is Demeter?]
Neben dem Demeter-System resultierten die Bestrebungen in einer Art Programmierparadigma, das als „Adaptive Programmierung“ bezeichnet wurde. Das Demeter-System und die Adaptive Programmierung wurden in [Lieberherr1996] detailliert beschrieben.

Bis heute halten Lieberherr und Kollegen das LoD für einen wesentlichen Bestandteil des Demeter-Systems und der Adaptiven Programmierung. Durch die Umsetzung des LoD in statischen Codeanalyse-Werkzeugen ist es in seiner Klassenform heute für zahlreiche Programmiersprachen leicht prüfbar.
Art des Prinzips
  • Grundlegende Einteilung: Produktprinzip.
  • Technologiebezug: Spezifsch. (Objektorientierung).
  • Entwurfsgüte: Bausteineigenschaft.
  • Handlungsbezug: Erleichterung von Änderung und Verstehen.
  • Kognitionsbezug: Lokalisierung.
(Siehe Kategorisierung der Prinzipien.)
Grad der formalen Spezifikation Sehr hoch.
Vorteile
  • Einfach und teils automatisiert erkenn- und anwendbar.
  • Verankert in zahlreichen weiteren Prizipien.
  • Empirisch belegt.
Nachteile
  • Bei Einhaltung des LoD entsteht systematisch einer von zwei unerwünschten Nebeneffekten:
    • eine größere Anzahl von Methoden, oft lediglich zusätzliche Vermittlermethoden (dadurch Schwächung der [Kohäsion] der Klasse)
    • längere Parameterlisten einzelner Methoden (dadurch erschwerte Verständlichkeit)
  • Das Laufzeitverhalten kann sich verschlechtern.
  • [Knoernschild2001] schwächt das LoD durch das Argument ab, dass eine Methode, die ein Delegate-Objekt liefert, zu diesem Zweck einen Interface-Typen verwenden kann. Damit wird eine direkte Kopplung an eine tiefliegende Implementierung vermieden. Es ist allerdings anzumerken, dass durch dieses Vorgehen zwar die Kopplung reduziert wird, der Verstoß gegen Geheimnisprinzip und Lokalitätsprinzip jedoch bestehen bleibt.
Übergeordnete Prinzipien
Abgleitete Prinzipien -

Qualitätsmerkmale
(+) Änderbarkeit,
(+ [in der Regel]) Verständlichkeit,
(+) Komplexität
(-) Kohäsion
(- [gelegentlich]) Verständlichkeit


Quellen
[Berens2011] - Ein Refaktorisierungswerkzeug zur Umsetzung des Law of Demeter, Masterarbeit, Dietmar Berens (2011)
[Knoernschild2001] - Java Design: Objects, UML, and Process, Knoernschild, Kirk (2001)
[Lieberherr1988] - Object-oriented programming: an objective sense of style. In: Conference proceedings on Object-oriented programming systems, languages and applications. New York, NY, USA : ACM, 1988 (OOPSLA '88), Lieberherr, Karl J. ; Holland, Ian. ; Riel, A.:
[Lieberherr1989] - Assuring Good Style for Object-Oriented Programs, In: IEEE Software, September 1989, S. 38-48, Lieberherr, Karl J. ; Holland, Ian (1989)
[Lieberherr1996] - Adaptive Object-Oriented Software - The Demeter Method, Lieberherr, Karl (1996), als PDF unter http://www.ccs.neu.edu/research/demeter/book/aoos.PDF
[Lopes1996] - AP/S++: Case-study of a MOP for purposes of software evolution, Lopes, C.V., Lieberherr, Karl J. (1996)
[URL: What is Demeter?] - http://www.ccs.neu.edu/home/lieber/what-is-demeter.html, Übersetzung durch M. Kleine (2013)