Archiv für den Monat: August 2011

Lose Kopplung (auf Klassenebene)

Kopplung existiert auf mehreren Ebenen von Software. Systeme können miteinander stark verwoben sein, Komponenten können von einander abhängen, und Klassen können in verschiedenen Beziehungen zueinander stehen. Kopplung beschreibt, wie stark ein Element zu anderen Elementen verbunden ist, sie benutzt oder sie kennt. Die Stärke der Bindung zwischen Elementen bestimmt:

  • Wie einfach die Elemente wiederverwendet werden können
  • Ob sich die Elemente unabhängig voneinander verändern lassen („change impact“)
  • Wie verständlich ein Element ohne Kenntnis anderer Elemente ist

Kopplung zwischen Klassen existiert und muss auch existieren, sie kann höchstens reduziert werden, um die oben aufgezählten Nachteile zu verhindern. Dafür muss verstanden werden, welche Kopplungsarten „eng“ (oder „stark“) sind, und welche „lose“. Das folgende Bild zeigt verschiedene Arten von Kopplung. Dabei sinkt der Kopplungsgrad von oben nach unten, eine Vererbung zwischen zwei Klassen ist eine stärkere Kopplung als eine Dependency.Lose Kopplung

Auf der rechten Seite des Bildes tauchen Interfaces auf, die Kopplung zu einem Interface ist schwächer als zu einer Klasse (da die Implementierung abstrahiert wird). Trotzdem ist es schwierig, die Kopplung zu Interfaces im Vergleich zur Kopplung zu Klassen zu bewerten, denn neben der Stärke der Bindung ist auch die Stabilität der Elemente zu berücksichtigen: Eine enge Kopplung zu stabilen Elementen führt zu wenig Problemen, eine lose Kopplung zu variablen Elementen kann problematischer sein. Fast jede Klasse in Java besitzt eine enge Kopplung zu java.lang.String, trotzdem führt das nicht zu Problemen, weil String eine stabile und verbreitete Klasse ist.

Lose Kopplung ist ebenfalls ein Pattern (GRASP: Low Coupling), es unterstützt Designentscheidungen, stellt aber das Ziel der losen Kopplung nicht über andere Ziele.

GRASP: Information Expert

Bei einer Diskussion mit Kollegen kam die Frage auf, welche Komponente für das Zählen der ungelesenen Nachrichten eines EMail-Postfachs zuständig ist. Speziell ging es dabei um eine App im Browser, die über einen Backend-Service auf ein EMail-Postfach zugreift. Folgendes Bild stellt eine vereinfachte Übersicht der vorhandenen Klassen dar:

Information Expert
Die Fragestellung („Wer ist für etwas zuständig?“) gibt bereits den Hinweis, dass hier GRASP (General Responsibility Assignment Software Patterns) weiterhelfen kann. Patterns bestehen aus fünf Abschnitten:
* Ein Name
* Eine (generalisierte) Problemstellung
* Eine Lösung / ein Ratschlag
* Eine Diskussion der Lösung
* Gegenanzeigen zur Verwedung des Patterns

Zurück zu dem Problem: „Wer zählt die ungelesenen Nachrichten eines EMail-Postfachs?“.Das Pattern „Information Expert“ gibt auf die Problemstellung „Welches Objekt soll für Aufgabe XYZ zuständig sein?“ den Ratschlag: „Das Objekt, welches alle nötigen Informationen zur Erfüllung der Aufgabe hat“. In unserem Beispiel besitzen die beiden verschiedenen EMail-Klassen (im Package „app“ und „backend“) zwar die Information, ob sie bereits gelesen wurden, allerdings besitzen sie keine Referenz auf alle Mails eines Postfachs. Also sollte laut „Information Expert“ das Zählen der ungelesenen Nachrichten nicht von den beiden EMail-Klassen (bzw. deren Instanzen) vorgenommen werden.

Die Klasse „EMailService“ liefert zu einer bestimmten PostfachID die ersten 50 EMails und hat keine permanente Referenz auf Postfächer. Interessanterweise wollten die meisten Kollegen die Zählfunktionalität hier einbauen. Wenn man sich aber den Zählalgorithmus an diese Stelle denkt (hole das Postfach XYZ, iteriere durch alle Emails und zähle die mit read = false), so sieht man, dass der Service mit den EMail-Objeten sprechen müsste. Das ist gegen das „Don’t talk to strangers“-Prinzip und hat Nachteile, wenn die EMail-Klasse verändert wird (da dann sowohl der EMailService, als auch die Inbox angepasst werden müssen).

Übrig bleiben die Klassen „EMailApp“ und „Inbox“. Jetzt sind genauere Anforderungen notwendig, um mit dem Information Expert Pattern hier eine Enscheidung treffen zu können. Sollen alle ungelesenen Nachrichten des gesamten Postfachs gezählt werden? Dann besitzt die „Inbox“ alle Informationen. Oder sollen nur die ungelesenen Nachrichten des angezeigten EMail-Postfachs (also der ersten 50 Nachrichten) gezählt werden? Dann besitzt die „EMailApp“ alle Informationen.

Das Information Expert Pattern gibt stets nur Ratschläge, die man nie isoliert betrachten sollte, sondern immer auch die anderen Pattern von GRASP konsultieren sollte. Geht man von dem Domainmodel aus, so stellt sich irgendwann die Frage: „Wer ist dafür zuständig, das Postfach darzustellen?“. Laut Information Expert zeichnet sich das Postfach selbst auf dem Bildschirm, schreibt und liest sich aus der Datenbank und hat auch sonst alle Aufgaben, für die es alle Informationen besitzt. Genau dafür gibt es aber andere GRASPs, die dem Ratschlag des Information Expert Patterns widersprechen (z.B. in diese Fall das „Pure Fabrication“ Pattern). Es darf also nie ein Pattern für sich alleine betrachtet werden.

Sehr gute Informationen zu GRASP gibt es in dem Buch „Applying UML and Patterns“ von „Craig Larman“, welches ich auch auf der Website Modellierung.net verlinkt habe.