Sunday, October 28, 2007

Patterns 4 - Domain Driven Design

Im vorläufig letzten Beitrag zu Patterns möchte ich einige Patterns aus dem Buch Domain Driven Design von Evans auflisten. Leider sind die Patterns nicht Online verfügbar, doch gehört dieses Buch sowieso zur Pflichtlektüre wenn mit Domain Model's gearbeitet wird. Wer es weniger theorietisch mag und sehe möchte wie sich das Arbeiten mit DDD 'anfühlt' dem sei Applying Domain-Driven-Design and Pattern von Nilson empfohlen.

Supple Design
Unter dieser Überschrift sind Patterns enthalten welche die Absicht und Wirkung von Code möglichst transparent darstellen lassen sollen. Idee ist dass die Struktur des Code die Funktionalität möglich klar darstellt.
  • Side-Effect-Free-Functions: Mit diesem Pattern können, auch in Kombination mit unveränderbaren 'Value Objects', einfach verständliche und testbare Funktionen realisiert werden. Für das Verständnis und das Testen müssen nur Inputparameter und der Resultatwert der Methode berücksichtigt werden da keine Seiteneffekte vorhanden sind. Weiter wird empfohlen Commands (Methoden welche beobachtbaren Zustand verändern) in sehr einfache Operationen zu gliedern welche keine Domäneninformationen retournieren.
  • Assertions: Im Code sollen Pre-/Postcondition und Invarianzen definiert werden. Damit sollen auch Seiteneffekte explizit spezifiziert werden damit für das Verständnis einer Methode nicht alle Ausführungspfade analysiert werden müssen.
  • Intention-Revealing Interfaces: Hier gehts es darum dass Klassen- und Methodenamen gefunden werden welche die Funktionalität und Verantwortlichkeit klar ausdrücken. Es sollte nicht nötigt sein dass daneben noch dokumentiert werden muss, unter welchen Umständen eine Klasse und Methode wie funktioniert. Auch sollten im Namen Begriffe aus der 'Ubiquitous Language' auftauchen.
  • Standalone Classes: Gelingt es eine völlig losgelöste Klasse, ohne Abhängigkeiten auf andere Klassen zu entwickeln, reduziert man die konzeptionelle Komplexität massgeblich. Lose Kopplung kann eingesetzt werden um die Komplexität von Code zu reduzieren.
  • Closure of Operations: Dieses Konzept hält uns an Operationen wie mathematische Operationen aufzubauen da diese ein einfaches Konzept ist. Dabei sollen Eingabeparameter und Rückgabwert vom gleichen Typ sein. Ein solches Interface ermöglicht das Zusammenbauen von komplexeren Operationen aus einfacheren Primitiven.
  • Specification: Ein Value Object welches als Predicate bestimmt ob ein anderes Objekt ein bestimmtes Kriterium erfüllt.
  • Ubiquitous Language: Dabei sollen Begriff und Konzepte aus der Problemdomäne von den Entwicklern übernommen werden. Diese Begriff und Konzepte haben ein starken Einfluss auf den Design und sind einer der wichtigsten Treiber für den Design.

Building Blocks
Hier haben wir Patterns welche unter DDD häufig vorkommen.

  • Layered Architecture: Schlägt vor im allg. eine Applikation in Presentation, Application, Domain und Infrastruktur Layer zu schichten. Dies ermöglicht einen ausdrucksstarken Domainlayer zu erhalten da dieser nicht mit Anzeige-, Speicher-oder Berechtigungsaufgaben usw. überladen wird.
  • Entities und Value Objects: Wichtige Konzepte zum Unterscheiden von Klassen mit Identitäten (z.B: eine Person mit einer ID) und Klassen deren Identität durch die Werte der Klasse bestimmt ist (z.B eine Farbe identifizierbar durch ihre RGB-Werten). Es wird empfohlen Value Objects als unveränderbare Klassen zu designen.
  • Modules: Gibt Anleitunng nach welchen Aspekten Code modularisiert werden sollten. Dabei sollte auf geringe Kopplung und hohe Kohäsion geachtet werden. Modulnamen sollten Teil der Ubiquitous Language werden. "If your model is telling a story, the Modules are chapters".
  • Services: Im allg. sollte für jeden Service gelten: 1.) Die Operation auf dem Service ist Teil des Domänenkonzept welches aber nicht als Entitiy oder Value Object ausgedrückt werden kann. 2.) Die Service-Schnittstelle nimmt Bezug auf das Domänenmodell. 3.) Die Operation ist zustandslos. Desweitern kann ein Service in verschiedenen Schichten realisiert werden (Application-, Domain-, Infrastructure-Service) wobei sich die Verantwortlichkeiten je nach Schicht stark unterscheiden können.
  • Factories: Erzeugt in einer Operation ein konsistentes Objekt oder Aggregate (Invarianzen müssen erfüllt sein). Dieses Pattern wird wichtig sobald ein Objekt nicht mehr mit einem einfachen Konstruktoraufruf erzeugt und in einen konsistenen Zustand überführt werden kann.
  • Repositories: Lädt Objekte oder Aggregates von einem tieferen Infrastrukturlayer in den Speicher (z.B von der Datenbank) und erzeugt die Illusion dass die Objekte immer im Speicher vorhanden sind. Repositories werden spezifisch für Klassen von Objekten und Aggregates realisiert und zeigen auf ihren Schnittstellen die Designentscheidung bezüglich Objektzugriff.
  • Aggregates: Damit werden eine Anzahl von Entities oder Value Objects logisch gruppiert um die Kopplung zwischen Teilen des Modells zu reduzieren. Pro Aggregate wird eine Klasse als Aggregate-Root definiert und der Zugriff auf das Aggregate darf nur noch über diesen Root erfolgen.
Strategic Design
Hier sind Patterns aufgelistet welche helfen in einem grösseren, komplexen System das Domänenmodell und verschiedene Teile davon herauszubilden.
  • Core Domain: Definiert die wichtigste Domain in einem Projekt. Für diese wird mit grosser Sorgfalt das Modell gefunden und ständig verfeinert. Jegliche Art von Entscheidungen können nun so gefällt werden dass es zuerst der Core Domain zu Gute kommt.
  • Generic Subdomain: Eine Subdomain ist nicht der Hauptgrund weshalb eine Software entwickelt wird, doch ist die Subdomain (z.B ein Zeitzonen-Modell) eine wichtige Unterstützung der Core Domain. Solche Domänen sollten aus der Core Domain gelöst werden um diese nicht unnötig komplex zu machen. Auch können Generic Subdomain häufiger als Core Domains wiederverwendet oder auch eingekauft werden. Vor und Nachteile beim Einkaufen von Sumdomänen sind in diesem Kapitel auch erläutert.
  • Domain Vision Statement: Schlägt vor dass die Coredomäne und ihr Wert zu Projektbeginn beschrieben wird um dem Entwicklungsteam eine gemeinsame Richtung zu geben.
  • Segregated Core: Beschreibt den Vorgang wie aus einem System ohne Core Domain eine solche gebildet werden kann.

Large-Scale Structure ist ein Kapitel in welche einige Patterns enthalten sind welche helfen ein Struktur für grosse Systeme zu finden.

Maintaining Model Integrity beschreibt Ansätze wie Modelle zwischen unterschiedlichen Systemen synchron gehalten werden oder wie mit den Unterschieden umgegangen werden kann.

No comments: