-
Bisher in dieser Serie:
-
DDD – Eine Einführung,
-
DDD – Allgegenwärtige / Universelle Sprache
In meinem Artikel “DDD – Eine Einführung” hatte ich versucht einen Überblick über Domain Driven Design und seine Auswirkungen zu geben. Leider fehlte dabei eine genaue Definition. Dies ist allerdings nicht einfach und ich bezweifle, ob es derzeit eine komplette und exakte Definition von DDD gibt. Die Beschreibungen auf Wikipedia scheinen mir unvollständig, da sie zu sehr auf den Aspekt des Objekt-Design abzielen. Auch im Buch selbst wird eher schwammig in das Thema eingeführt: Man bekommt schnell ein Gefühl für DDD und, mit Blick auf das Inhaltsverzeichnis, auch für den Umfang. Trotzdem fehlt eine präzise, umfassende Definition. Daher ist dieser Artikel sicherlich zunächst nur ein Versuch – ich maße mir keine Vollständigkeit an.
Der Grund dafür liegt, meiner Meinung nach, in der Tatsache begründet, dass DDD eigentlich vor allem eines ist: ein philosophischer Ansatz, wie Problemdomänen in Software implementiert werden sollten:
- Das Modell, und damit die Domäne, sind im Herzen unserer Software
Und "drumherum" bildet DDD damit eine Entwurfsmuster-Sprache, die uns ermöglicht darüber zu kommunizieren. Dies würde ich als eine Definition von Domain Driven Design und dessen Kern bezeichnen wollen (siehe auch David Laribee's Artikel dazu).
Worin liegt dies begründet und welche Auswirkungen hat dieser Ansatz für uns? Gehen wir also zurück zum Anfang. Zunächst dreht sich bei der Erstellung von Software alles um Modelle und Abstraktionen. Haben wir eine gegebene Domäne, so bauen wir zu einer Teilmenge daraus ein Modell, eine Abstraktion der Domäne. Die gesamte Domäne (wie eigentlich alles auf der Welt) ist natürlich zu groß, um sie vollständig zu modellieren. Wenn wir Software entwickeln, bauen wir also primär ein Modell einer Domäne.
Derzeit besteht unsere bester Weg zu Modularisierung und Abstraktion in der Nutzung von Objekt Orientierung. Damit liegt die Idee nahe, unser Modelle durch “nakte” Objekte zu implementieren - wie wir es in der Uni gelernt haben bevor wir über Datenbanken, Transaktionen und Infrastruktur nachdachten. Idealer weise gibt es zwischen Quelltext und Modell keine Unterschiede, also keine Übersetzungen. Im Artikel “DDD – Allgegenwärtige / Universelle Sprache” bin ich bereits darauf eingegangen, warum Eric Evans Übersetzungen als kritisch ansieht. Unser Modell ist also von der Domäne gesteuert.
Wenn wir nun ein Modell der Domäne erstellen, ergibt sich direkt die Frage: Wer kennt die Domäne? Die Architekten? Oder Software Analysten? Oder Entwickler? Wohl kaum. Erstere denken wohl eher an Entwicklung im großen Rahmen, letztere im sehr kleinen und Software-Analysten können wohl analysieren, aber kennen wohl nicht jede Problem-Domäne. Diejenigen, die eine Domäne am besten kennen sind aber direkt vor unseren Nasen: Der Kunde und seine Experten. Diese Idee sehen wir auch in anderen Bereichen, zB in den Agilen Prozessen. Im eXtreme Programming heißt das ganze “Customer On Site”. Da das Modell also keine verborgene Magie innerhalb der Software ist, sondern eine – für alle sichtbare – Abstraktion, ergibt sich die Grundlage des Domain Driven Design:
- Das Modell, und damit die Domäne, sind im Herzen unserer Software
Dies hat weitreichende Konsequenzen auf alle Bereiche, wie Anforderungen an die Architektur, Auswirkungen auf Objekt-Design, das Team, seine Prozesse, etc. Weil wir zum Beispiel dieses Modell kommunizieren müssen, sowohl intern als auch extern, liegt die Idee nahe, eine gemeinsame Sprache in allen Beriechen zu nutzen: angefangen bei der Kommunikation, über Dokumentation, Diagrammen bis hin zum Quelltext. Ideal ist es also, wenn sich die Sprache und damit das Modell im Quelltext manifestiert. Dann könnte man nur durch das Lesen des Quelltextes im Domänen-Modul eine Menge über die Domäne selbst lernen.
Zusammenfassend kann man also sagen, dass Domain Driven Design ein Ansatz zur Software-Entwicklung ist, der das Modell einer Problemdomäne ins Zentrum stellt. Kritik und Erweiterungen sind willkommen!
Nachtrag: Definitions-Absatz erweitert um die Idee der Pattern-Language.
Tags: ddd, domain driven design
Ein Vergleich der Patterns Table Module (DataSets,..), Transaction Scripts und Domain Model
Abseits meiner Beiträge zum Thema Domain Driven Design möchte ich hier die drei Ansätze zur Handhabung von Komplexität in Geschäftslogik aus Martin Fowler’s Buch “Patterns of Enterprise Application Architecture” vergleichen. Alle drei stellen Wege dar, eine Domäne zu modellieren, wenn auch die beiden ersten Ansätze stark zu prozeduraler Programmierung tendieren:
- Table Module Pattern (auch bekannt als DataSets in .NET)
- Transaction Scripts
- Domain Model Pattern
Fowler hat zum Vergleich eine ähnliche Grafik wie die folgende verwendet.
In der Grafik ist Komplexität gegenüber Aufwand gestellt. Die rote Linie steht für das Table Module Pattern, die blaue Linie steht für Transaction Scripts und die grüne Linie steht für das Domain Model Pattern. Die Idee der Grafik ist es zu zeigen, wie die drei Ansätze mit erhöhter Komplexität skalieren. Dabei kommt es nicht so sehr auf den exakten Verlauf an. Wichtiger ist es zu sehen, dass die Grafik recht gut dem gefühlten “Aufwand” entspricht, bei der Arbeit mit den Ansätzen: der Aufwand bei Transactions Scripts und Table Module (in .NET also DataSets) steigt rasant und macht zunehmende Komplexität kaum noch handhabbar. Aber auch das Domain Model Pattern lässt sich nicht unendlich lange nutzen, ohne ans eine Grenzen zu stoßen. Trotzdem liegt diese Grenze bedeutend höher, was das Pattern so attraktiv für komplexe Domänen macht. Zu große Komplexität kann durch Zerteilen der Domäne in verschiedene Modelle begegnet werden. Diese müssen dann aber genau abgegrenzt und integriert werden müssen – andernfalls wird man weniger Nutzen davon haben. Die passenden Stichwörter wären hier Bounded Context, Context Map und Core Domain [/End buzzword dropping].
Die Große Frage am Vergleich der 3 Ansätze ist natürlich: Wo liegen die Grenzen auf der Achse der Komplexität? Dazu müssten wir aber zunächst einmal Komplexität messen – dies können wir aber kaum. Pragmatisch gesehen muss hier die Erfahrung des Teams herhalten. Praktisch gesehen lohnt sich ein Domain Model sicherlich nicht für eine reine CRUD-Anwendung mit nur sehr simpler Validierung. Trotzdem greift wohl auch diese Einordnung zu kurz. Niemand kann schließlich genau vorhersagen, wie sich das Geschäft des Kunden weiterentwickelt oder ob aus einer kleinen Anwendung nicht plötzlich eine große wird – dafür scheinen zu viele “Prototypen” bisher immer noch am Leben. Es besteht somit die Gefahr eine Entscheidung zu früh zu treffen, obwohl man die Notwendigkeit für das Domain Model Pattern erst später begründen können wird. Es besteht aber auch die Gefahr, sich mit der Wahl von Transaction Scripts oder Table Modul die Möglichkeit zu verbauen, jemals zu einem reichhaltigen Domänenmodell zu gelangen. Denn laut Fowler ist genau dieser Übergang extrem aufwending und teuer – obwohl die Alternative (kein Redesign) keine wirkliche Alternative ist. Interessant wäre wohl zu experimentieren, ob ein Redesign vom Domain Model Pattern hin zu Transaction Scripts gut funktioniert. Mein Tipp wäre, dass sich dies wohl leichter realisieren lässt, als der Weg anders herum; schließlich sehen wir heute viele Prozedurale Implementierungen mit einem anemischen Domänenmodell.
Klar ist, dass das Table Module Pattern gerade wegen seiner breiten Werkzeug-Unterstützung im .NET Bereich eine sehr geringe Hürde für den Einstieg hat. Table Module und Transactions Scripts zerlegen die Domäne in ein prozedurales Modell und bestechen durch ihre Einfachheit - für einfache Kontexte! Leider ist dieser Umstand bisher wenig bis gar nicht kommuniziert worden. Offensichtlich ist aber die Idee des simplen Drag&Drop / RAD / … für die meisten gescheitert. Beim Table Module Pattern gibt es in der Regel ein Objekt, dass die Logik und Kommunikation für eine Datenbank-Tabelle übernimmt. Transaction Scripts manifestieren sich in der Regel in einem “dicken” Application / Service Layer (Fowler). Für jede Transaktion haben wir dann eine Service-Operation. Hiermit sollte dann auch klar sein, warum beide Ansätze Probleme mit duplizierter Logik, Copy&Paste-Smells und vor allem Seperation of Concerns haben. Beim Einsatz eines Domain Models ist die Service Schicht hingegen sehr dünn. Sie koordiniert nur verschiedene Aktionen auf dem Domänenmodell. Vor allem aber eignet sich die Service Schicht zur Beschreibung der Session- und Transaction-Scopes zur Datenbank-Verbindung (mehr dazu später in der DDD Serie).
Transaction Scripts und Table Module haben sicherlich geringere Anforderungen an die Erfahrung und das Abstraktionsvermögen eines Entwicklers. Domänenmodelle bieten dafür weitaus mehr Modularisierung und können so auch zu mehr Wiederverwendung führen. Je komplexer ein Modell wird, umso mehr scheint der Vorteil gegeben über Transaction Scripts und Table Module zu wiegen. Sicheres Einsatzgebiet sind somit auf jeden Fall jene Domänen, bei denen von Anfang an klar ist, dass die Komplexität jenseits von einfacherer Validierung (zB isolierte Validierung pro Feld) und CRUD liegt.
Am Schluss möchte ich noch zu Bedenken geben, dass vollständige Modularisierung mit OOP nicht möglich ist (siehe “Tyranny of the dominant decomposition”). Egal nach welchen Kriterien die Dekomposition der Anwendung von statten geht – es wird immer orthogonale, übergreifende Belange geben. Nach derzeitigem Stand der Forschung erreichen wir damit noch bessere Modularisierung nur durch den Einsatz von Aspekt-Orientierung. Meines Wissens ist aber weiterhin unklar, ob wir damit den “heiligen Gral” der Modularisierung erreichen. Vielleicht ist es am Ende auch egal und nur eine Frage des nötigen Pragmatismus.
Tags: ddd, domain driven design, domainmodel, dotnet, patterns
Nachdem Stefan Lieser in Blog und Maillingliste bereits grob berichtet hat, folgen hier nun noch die visuelle “Nachverfolgung” des ersten ALT.NET Treffens in Deutschland überhaupt.
Stattgefunden hat das ganze in der Teba in Köln, wo auch die Treffen der DNUG Köln ihre Heimat haben. Themen waren unter anderem:
- Mitarbeiter Motivation / Coaching in ALT.Net
- Messaging statt RPC, Publish Subscriber
- PostSharp erfüllt Obliviousness nicht
- Parallelität
Speziell zum Thema PostSharp und AOP-Obliviousness möchte ich noch den folgenden Link zum entsprechenden Paper nachreichen: Robert Filman, Daniel Friedman: “AOP is Quantification & Obliviousness”.
Nun ist es also raus: am 18. und 19. Oktober 2008 findet die .NET Open Space in Leipzig statt. Dabei bildet ALT.NET eines der drei Themenfelder und verspricht spannende Sessions. Ort der Veransaltung ist der Mediencampus Villa Ida. Ich werde auf jeden Fall teilnehmen und habe mich bereits registiert. Vielleicht kommt ja auch eine Session zu DDD oder AOSD zustande – ich würde mich drauf freuen ;-)