Jul 182008
 

Domain Driven Design ist spätestens seit dem gleichnamigem Buch von Eric Evans in die Ruhmeshallen der Buzzwords eingegangen. DDD reiht sich ein neben Test Driven Development (TDD), Feature Driven Development und Model Driven Development (MDD). Bei so vielen Drivern frag ich mich, ob wir irgendwann einmal ans Ziel kommen. Spass beiseite – aus meiner Sicht sind das alles Paradigmen, die ihre Berechtigung haben und sogar kombiniert eingesetzt werden sollten.

Domain Driven Design zielt in großen Teilen auf Domänenmodelle ab. Aus meiner Erfahrung verwenden Domänenmodelle, die wirklich etwas auf sich halten, eigene atomare Domänentypen und pfeiffen auf die direkte Verwendung von String, Integer und Co. Dieser Schritt bringt viele Vorteile mit sich, muss jedoch am zusätzlichen Aufwand für die Erstellung der zuzsätzlichen Klassen gemessen werden. Natürlich muss die Notwendigkeit von atomaren Domänentypen aufgrund des Mehraufwands durchdacht und gut begründet sein. Bei der architekturellen Betreuung eines Systems bin ich den Weg der atomaren Domänentypen gegangen und möchte in den folgenden Zeilen ein wenig mit Weisheit prahlen sowie zur Diskussion anregen.

Mein Kollege spricht Denglisch!

Das Domänenmodell (aka Domain Model) stellt einen ziemlich großen Teil des Herzens einer Unternehmensanwendung (aka Enterprise Application) dar. Die Applikation nutzt das Domänenmodell als Sicht auf die fachliche Datenwelt. Idealerweise führt ein durchdachtes Domänenmodell in der Applikation eine Terminologie ein, die auch Teil der Kommunikation zwischen Teammitgleidern wird. Als Beispiel stelle ich mir ein stark vereinfachtes Flugreservierungssystem vor, dass die Domänentypen “Flight”, “Seat”, “Itinerary” und “Customer” beinhaltet. Auch in einem deutschsprachigem Projektteam führt dieses Domänenmodell dazu, dass “Itinerary” statt “Flugschein” in die verbale Kommunikation einzieht. Dies vermeidet unnötige Missverständnisse und spart mit Sicherheit eine Menge Zeit im Laufe einer mehrmonatigen bis mehrjährigen Projektlaufzeit. Leider kann mir das keiner von unseren Controlling-Jungs aufschlüsseln!

Entitäten als reine Datenobjekte?

Die Architekturen vieler Systeme sehen vor, dass die Klassen des Domänenmodells in nahezu allen Schichten und Subsystemen der Applikation verwendet werden dürfen. In diesem Fall kann man das Domänenmodell einer Applikation als global bezeichnen. Daher stellen dessen Datentyp-Klassen den idealen Ort für mehrfach verwendete Logik dar. Dies folgt dem Prinzip “Wissen bei Daten”, welches besagt, dass essentielle Logik direkt dort im System untergebracht sein sollte, wo die von der Logik verwendeten Informationen gespeichert sind. Dies soll Redundanzen vermeiden, da es in einer umfangreichen Applikation sehr schwer ist, bereits bestehende Funktionalität zu lokalisieren und zu verwenden. Das Domänenmodell ist jedoch global referenzierbar und erster Anlaufpunkt für zentrale (relativ einfache) Logik, die keine komplexen fachlichen Prozesse abbildet.

In meiner Flugreservierung erstelle ich eine Methode “isSoldOut()::boolean” an der Entität “Flight”, welche über alle “Seats” des “Flight” iteriert und deren “available”-Attribut prüft. Die Methode “isSoldOut()”wird wahrscheinlich an mehreren Stellen im System verwendet. Eine Methode “Flight.book(Customer)” sollte es jedoch nicht geben, da diese mit Sicherheit einen komplexeren Prozess darstellt, der das Domänenmodell enorm vergrößert. Zudem wird eine derartige Methode möglicherweise Daten persistieren und auf externe Systeme zugreifen. Dies sollte aus meiner Erfahrung nicht Teil des zantralen Domänenmodells sein, sondern als Domain Service in der Business Layer (aka Domain Layer) realisiert sein und den zu buchenden Flug übergeben bekommen.

Es gibt Stimmen, die eine strikte Trennung von Daten und Logik fordern – dies ist meiner Meinung nach schlicht falsch. Wozu wurde die Objektorientiterung geboren, wenn nicht eben zur Kombination von Daten und Verhalten in Form von Objekten. Die Erstellung einer Util-Klasse für die Funktion “isSoldOut”, welcher ein Flight-Objekt übergeben werden muss, stellt die schlechtere Alternative dar. Durch die unzureichende Transparenz (Wo ist die Mehode “isSoldOut”) birgt die Util-Klasse das Risiko zur Entstehung von Redundanzen. Und das muss man Wissen: Redundanz ist die Pest für jeden Quellcode; die Copy-Paste-Vergehen sind die Raten, welche die Pest ins System tragen.

Atomare Datentypen für Entitätsattribute

Viele modernen Unternehmensapplikation basieren auf einer Architektur, die ein zentrales Domänenmodell vorsieht. In der Java-Welt sind derartige Architekturen aufgrund der Java Persistence API stark im Aufwind.

Klassen beschreiben komplexe Datentypen der Anwendungsdomäne, welche auch als Entitäten bezeichnet werden. Dieser Begriff entstammt wahrscheinlich der Terminologie von ERP-Diagrammen. Die Abgrenzung einer Entität gegenüber einer Value-Objekt-Klasse ist ein altes aber gelöstes Problem der philosophischen Informatik: Eine Entität dient weniger zum Transport von Daten als der Repräsentation eines Datenobjekts und verfügt daher über einen Identifikator (meist numerische ID). In den meisten Fällen repräsentiert ein komplexer Datentyp die Sicht auf eine Datenbanktabelle – ein Objekt des Datentyps repräsentiert eine Tabellenspalte bzw. Datensatz.

Während komplexe Datentypen im Domänenmodell keine Seltenheit sind, werden atomare Domänentypen weit weniger häufig eingesetzt. Jedes Attribut einer Domänen-Entität besitzt einen atomaren Datentyp. Atomar deshalb, weil dem Attribut nur ein Wert (Zeichenkette, Dezimalzahl, etc.) zugewiesen werden kann. Ohne Domänentypen als atomare Datentypen, werden die Standard-Datentypen der Programmiersprache verwendet (in Java: String, Integer, …). Im Gegensatz dazu kann jedoch ein atomarer Datentyp mit direkten fachlichen Bezug definiert werden.

Gegenüber dem Mehraufwand der Erstellung von einer Klasse für jeden atomaren Domänentyp sehe ich folgende Vorteile:

Typsicherheit
Methodenparameter können aufgrund der feineren Typisierung nur selten versehentlich vertauscht werden

Dokumenation
DieBeschreibung des fachlichen Datentyps erfolgt einmal an der Klasse des atomaren Domänentyps – Attribute von Entitäten sind in der Regel durch die feine Typisierung ausreichend dokumentiert. Hierdurch werden Redundanzen in der Dokumentation vermieden bei gleichzeitiger verbesserter Verständlichkeit des Quellcodes

Terminologie
Die Namen der Entitäten des Domänenmodells führen eine Projektsprache ein. Dies wird mit atomaren Domänentypen ausgeweitet. So heisst die Flugnummer nicht an einer Stelle flightId, an einer anderen Stelle flightNr und an einer weiteren flightNo.

Flexibilität
Eigene Klassen als fachliche atomare Datentypen erlauben die Anpassung von Sortierreihenfolge, Wertebereich, etc. Insgesamt lassen sich nachträglich Änderungen am System aufgrund dieser Flexibilität besser umsetzen. Zwischen konkretem Datentyp der Programmiersprache und den vielen Verwendungen des fachlichen Datentyps liegt die atomare Domänentyp-Klasse als Abstraktion.

Analyse
Zum Beispiel können in Eclipse alle Referenzen auf einen atomaren Domänentyp gefunden werden. So lassen sich schnell und zuverlässig die Auswirkungen geplanter Änderungen analysieren.

Konstanten
Häufig im Code verwendete Werte eines fachlichen Datentyps (zum Beispiel für Fallunterscheidungen) werden als Konstanten direkt in der Domänentyp-Klasse hinterlegt. Dies hilft ebenfalls Redundanzen zu vermeiden und die Analyse hinsichtlich konkreter Werte von fachlichen Domänentypen zu erleichtern.

Natürlich sind auch Mischformen aus der Verwendung von atomaren Domänentypen und einfachen Standard-Datentypen möglich. Die Attribute “firstName” und “lastName” eines “Customer” verwenden den String-Datentyp. Für das Attrbut “flighNr” von “Flight” wird ein neuer atomarer Domänentyp “FlightNr” eingeführt.

Im nächsten Teil zeige ich anhand konkretem Code, wie ich atomare Domänentypen mit Java sehe. Zudem werde ich auf das Handling mit Java Server Faces eingehen.

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>