In den letzten zwei Monaten hatte ich im Umfeld der Software-Entwicklung sehr viel dieser “AHA”-Effekte. Da das Gehirn neue Erkenntnisse mit dem Ausschütten von Glückshormonen belohnt, war es eine sehr gute Zeit für mich. 🙂
Als heute morgen alle noch bei Kaffee in unserem Pausenraum sassen, habe ich ein speziellen Teil unseres Domain Modells an die dort hängende Tafel gemalt. Ich wollte allen mitteilen, auf welch schönes Design wir gestern für einen Teil unseres Domain Modells gekommen waren. Insbesondere wollte ich auch aufzeigen, wie elegant eine Lösung werden kann, wenn man sich an das Gesetzt von Demeter hält. Dabei haben Jan und ich nicht mal an das Gesetz gedacht, als wir die Schnittstellen definiert haben. Es ist sozusagen “einfach entstanden”.
Hier ein leicht abgeändertes Beispiel:
Wir haben also ein Interface welches aussagt, dass ein Typ welches dieses Interface implementiert eine Has-A-Beziehung zu Basket hat. Ein WithBasket-Object hat also immer einen Basket. Ausserdem kann ein Basket eine Menge (0 bis n ) Elemente beinhalten. Nun machen wir mal zwei Methoden hinzu:
Die Diskussion entbrannte nun an der Methode addElement(Element e)
in WithBasket. Eine Implementierung von WithBasket muss also diesen Aufruf an Basket delegieren. Und dieser Punkt war einigen Kollegen nicht geheuer bzw. wurde abgelehnt, u.a. mit der Begründung, dass ja der Typ WithBasket nicht für die Verwaltung von Elementen zuständig ist. Besser sei auf WithBasket eine Methode “public Basket getBasket()
” zu implementieren, void addElement(Element e)
wegzunehmen und der Benutzer von WithBasket kann dann auf dem Basket die gewünschten Operationen ausführen. In einem Client von WithBasket würde also folgender Code stehen:
myObjectWithBasket.getBasket().add(myElement);
Dies bricht das Gesetz von Demeter.
Nun habe ich in der Mittagspause nachgedacht und nach Beispielen aus dem realen Leben gesucht. Als Erstes ist mir ein Theaterbesuch in der ehemaligen DDR eingefallen. Dort habe ich mal Folgendes erlebt:
Vor der Garderobe des Theaters stand eine Angestellte des Theaters die offensichtlich für die Garderobe zuständig war. Als wir nun unsere Jacken abgeben wollten, zeigte sie mit dem Finger auf die Kleiderhaken und wir mussten nach hinten gehen und unsere Sachen selber aufhängen.
Es ist richtig, dass es nicht die Verantwortlichkeit der Garderobenfrau war, unsere Kleider die ganze Vorstellung lang zu halten. Trotzdem empfindet man dies doch als komisch. Ich bin jedes mal dankbar, wenn mir die Jacke abgenommen und an die Kleiderhaken gehängt wird. Dieses Muster findet man sehr oft vor. Ein weiteres Beispiel die die Essenbestellung im Restaurant. (Gast -> Bedienung -> Koch).
Ein weiters Beispiel ist die Rezeption im Technopark Zürich. Die Rezeption hat auch einen Kopierer und wenn man möchte, kann man dort auch Sachen kopieren lassen. Man gibt ein Blatt ab, die Frau an der Rezeption nimmt das Blatt, legt es auf den Kopierer und drückt den grünen Knopf. Es ist so viel angenehmer, als erst selbst hinter die Rezeption an den Kopierer gehen zu müssen. Was passiert aber, wenn ich den Kopierer viel besser bedienen kann, als die Frau an der Rezeption? Ich kenne das Teil und weiss, wie man die Graustufen einstellt und wie man verkleinert. In solch einem Fall wäre es eventuell doch nötig an den Kopierer heranzukommen.
Um wieder zum Basket-Beispiel zurückzukommen. Was macht man, wenn man nun Basket in einem GUI darstellen möchte und nur WithBasket hat?
Für die Darstellung von Basket breche ich nun die Kapselung. Nicht unbedingt 100% Law of Demeter aber pragmatisch. Oder?
Trotzdem stelle ich die wichtigen Operationen von Basket am WithBasket zur Verfügung, damit im Domain-Model immer über dieses gegangen werden kann. Und wenn ich getBasket weglassen kann, dann mache ich es auch. Schlussendlich entscheidet der fachliche Kontext in solch einem Fall.
Wie einfach die Unit-Tests dann auf einmal zu schreiben sind, kommt vielleicht ein anderes Mal. Heute bin ich zu müde…
Gute Nacht
One thought on “Gesetz von Demeter im Alltag”