Archiv der Kategorie: grasp

ScrumRechner Teil 6: Die Prozess/Ablauf-Sicht

Der Ablauf einer User-Interaktion zwischen den Schichten ist auf sehr abstrakter Ebene in folgendem Sequenzdiagramm dargestellt:

Ablauf-Sicht

Ablauf-Sicht

Schon auf dieser abstrakten Ebene stellt sich eine grundsätzliche Designfrage: Wer ist verantwortlich, aus den Tastendrücken eine Zahl zusammenzusetzen?

Das GRASP Controller Pattern definiert den Controller folgendermaßen:
Ein Controller ist das erste Objekt hinter der UI-Layer, das für die Verarbeitung der System-Events verantwortlich ist.
Zur Beantwortung der Frage, wo die Verantwortlichkeit zum Zusammensetzen der Zahl aus der Benutzereingabe stattfindet, ist eine Abwägung erforderlich: Ist das Zusammensetzen einer Zahl so kompliziert, dass es bereits einen (Sub-) Prozess des Systems darstellt? Wenn das der Fall ist, dann meldet die UI-Layer die einzelnen Ziffern an den Controller, und ermöglicht die Wiederverwendung dieser BusinessLogik für andere GUI-Technologien (in den UseCases gibt es einen Hinweis auf eine Portierung auf Mobiltelefone). Da es bei der Eingabe der StoryPoints nicht nur um natürliche Zahlen, sondern auch um Kommazahlen (die UseCases erwähnen halbe StoryPoints) geht, ist das Parsen der Zahlen hinreichend kompliziert, um einen Teil der BusinessLogik darzustellen und somit nicht in der View zu erledigen.

Scrum-Rechner Teil 5: Die logische Sicht als Teil des Konzepts

In diesem Beitrag wird die logische Sicht des Scrum-Rechners auf einer sehr abstrakten Ebene entwickelt. Die Anforderungen bestehen in den UseCases, von denen im Moment einer in Details untersucht wurde.
Die Frage, die mit der logischen Sicht beantwortet werden soll, ist: „Wie ist die Software konzeptuell organisiert?“. „Konzeptuell“ in diesem Zusammenhang bedeutet, dass nicht die Organisation in deploybaren Artefakten, sondern die logische Struktur untersucht wird. Detailfagen, die gestellt werden müssen, sind: „Welches sind die wichtigsten Schichten, Subsysteme, Packages, Frameworks, Interfaces und Klassen?“.

Traditionell ist eine Entkopplung der Darstellungsschicht von dem Rest des Systems gewünscht, um den „Impact of change“ bei neuen Anforderungen an die GUI (Designänderungen oder neue Technologien) gering zu halten. Während der traditionelle objektorientierte Weg besagt, dass jedes Objekt sich selbst darstellt (siehe GRASP: Information Expert), wird dieses Prinzip den nicht-funktionalen Anforderungen (hier: der Wartbarkeit) geopfert, und in View-Klassen ausgelagert (GRASP: Pure Fabrication). Microsoft bezeichnet die Trennung der View von dem Rest des Systems als „Document-View Architecture“.

Der UseCase beschreibt schon einige „Spielregeln“, nämlich die Abfolge Operand->Operator->Operand->…. Diese Regeln sollen von der Geschäftslogik (Durchführung der Berechnung) getrennt werden, sie werden also in einen Controller ausgelagert. Ergebnis wäre das Model-View-Controller-Pattern.

Wird für die bekannten Anwendungsfälle wirklich Model-View-Controller benötigt? Der UseCase „Daten eingeben“ erfordert zumindest keine Verbindung zwischen Modell und View. Im Zweifel gilt hier erst einmal: YAGNI. Statt MVC folgt der Entwurf in der logischen Sicht dem Model-View-Presenter Pattern.

logische Sicht des Scrum-Rechners

logische Sicht des Scrum-Rechners

GRASP Creator

Das GRASP Creator-Pattern gibt Antworten auf die Frage „Wer ist zuständig für die Erzeugung einer neuen Instanz einer bestimmten Klasse?“. Die Lösung soll folgende Eigenschaften besitzen:
– Lose Kopplung
– gute Verständlichkeit
– Kapselung
– Wiederverwendbarkeit

Das Creator-Pattern stellt einige Kriterien auf, die eine gute Lösung charakterisieren (auch hier darf man das Pattern nicht isoliert anwenden, sondern muß auch die anderen GRASP-Pattern berücksichtigen). Gegeben die Klassen A und B. A soll Instanzen von B erzeugen, wenn:
– A B enthält (Komposition oder Aggregation)
– A B verwaltet
– A B sehr eng benutzt
– A alle Informationen zur Erzeugung von B besitzt (Information Expert)
Je mehr dieser Kriterien zutreffen, desto deutlicher der Hinweis, das A Instanzen von B erzeugen soll.

Damit beantwortet das Creator-Pattern meiner Meinung nach auch folgende Frage (die zu Glaubenskriegen führen kann):
Wenn die Klasse A Instanzen von B erzeugt, und B eine obligatorische Kompositionsbeziehung zu C hat:

GRASP_creator
Eine Instanz von B muss immer eine Instanz von C enthalten, dies wird über den Konstruktor von B sichergestellt. Wenn A nun eine Instanz von B erzeugt, übergibt es dann als Konstruktor-Argument eine Instanz von C, oder aber alle einzelnen Informationen, die B zur Erzeugung von C benötigt?

Die Kriterien des Creator-Pattern liefern den Hinweis: Während die erste Lösung (A übergibt eine Instanz von C an den Konstuktor von B) lediglich den Punkt „besitzt alle Informationen, um C zu erzeugen“ erfüllt, deckt die andere Lösung alle Kriterien ab, und unterstützt somit die am Anfang dieses Texts genannten Eigenschaften der Lösung besser.

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.