architecture blueprints - bilder.buecher.degien mit einzubeziehen, die inzwischen reif für die...
TRANSCRIPT
Daniel Liebhart, Guido Schmutz, Marcel Lattmann, MarkusHeinisch, Michael Könings, Mischa Kölliker, Perry Pakull, Peter
Welkenbach
Architecture BlueprintsEin Leitfaden zur Konstruktion von Softwaresystemen mit Java
Spring, .NET, ADF, Forms und SOA
ISBN-10: 3-446-41201-8ISBN-13: 978-3-446-41201-9
Vorwort
Weitere Informationen oder Bestellungen unterhttp://www.hanser.de/978-3-446-41201-9
sowie im Buchhandel
XI
Vorwort
Zur zweiten Auflage
Die zweite Auflage der Architecture Blueprints ist eine aktualisierte Überarbeitung
der Ersten, die erst vor kurzem – im Herbst 2006 – erschienen ist. Die Überarbeitung
hat sich aufgrund der großen Nachfrage ergeben, was uns sehr gefreut hat und wir
danken allen Lesern und Leserinnen dafür. Wir haben die Gelegenheit genutzt, um
neue Erfahrungen einfließen zu lassen und eine Reihe von Techniken und Technolo-
gien mit einzubeziehen, die inzwischen reif für die Praxis sind. Mit Marcel Lattmann
hat ein erfahrener Architekt das Autorenteam bereichert.
Die vorliegende Ausgabe ist vollständig überarbeitet worden. Die Architekturstan-
dards für die Technologien Java Spring, Microsoft .NET, Oracle ADF, Oracle Forms
und SOA wurden verfeinert und sind – wie wir hoffen – noch klarer und verständli-
cher dargestellt worden.
Das einführende Kapitel „Grundlegende Architekturkonzepte“ wurde von Mischa
Kölliker zur besseren Lesbarkeit gestrafft und umgestellt und in die Bereiche Domain
Layer, Persistence Layer und Presentation Layer aufgeteilt. Es beschreibt Pattern, Kon-
zepte und Designkriterien, die in der Praxis für Enterprise Architekturen relevant
sind. Der Review wurde von Guido Schmutz und Peter Welkenbach durchgeführt.
„Spring Framework Architecture Blueprint“ wurde von Guido Schmutz und Peter
Welkenbach ergänzt, die inzwischen zu diesem Thema ein eigenes Buch mit den
Titel „Spring 2.0 im Einsatz“ geschrieben haben. Die wichtigste Ergänzung befasst
sich mit dem Enterprise Middletier und seiner Realisierung. Mischa Kölliker hat den
Review übernommen.
Das Kapitel „Microsoft .NET Architecture Blueprint“ wurde von Marcel Lattmann und
Michael Könings komplett überarbeitet, um die neuen Technologien .NET 3.0 und
AJAX und deren Einsatz in der Praxis darzustellen und einen Ausblick auf die techno-
logische Entwicklung (LINQ und die nächste .NET Version), die in naher Zukunft re-
Vorwort
XII
levant sein könnte, zu präsentieren. Das Kapitel wurde von Christoph Pletz, Meinrad
Weiss und Markus Heinisch reviewed.
Das Kapitel „Oracle ADF Architecture Blueprint“ wurde von Markus Heinisch mit
Beispielen angereichert und mit einer Beschreibung von JHeadstart, einer Technolo-
gie zur produktiven Generierung von einfachen Anwendungen, ergänzt. Perry Pakull
war für den Review zuständig.
„Oracle Forms Architecture Blueprint“ hat Perry Pakull mit einem zusätzlichen Ab-
schnitt zu Thema Oracle Forms Konzepte erweitert. Außerdem hat er die Einsatzbe-
reiche, die Architektur und die verschiedenen Ausprägungen des Forms Clients ver-
feinert. Der Review wurde von Michael Könings und Daniel Liebhart durchgeführt.
Das Kapitel „SOA Blueprint“ wurde von Daniel Liebhart aufgrund der Tatsache, dass
sowohl die Hersteller also auch viele Unternehmen sehr viel Neues realisiert haben,
überarbeitet und erweitert. Neu sind die Bestandteile der einzelnen Ebenen einer
SOA und der Abschnitt SOA und BPM. Außerdem wurde der SOA Blueprint verfei-
nert und die SOA Modelle der großen Hersteller skizziert. Das Review hat Markus
Heinisch ausgeführt.
An dieser Stelle danken die Autoren allen Personen, die in irgendeiner Weise einen
Beitrag zur Überarbeitung dieses Buches geleistet haben. Neben den Reviewern wa-
ren das unter anderem Urban Lankes für die Initiative zur kompletten Überarbeitung,
Patrick Spieler für die AJAX Vorlage, Urs Meier für die Weiterentwicklung der Grund-
lagen zum Microsoft .NET Architecture Blueprint, Anton Rasch für den Input zum
Layering und Dirk Nachbar für den Input zum Sizing im Oracle Forms Architecture
Blueprint, Michael Beer für die Reflektionen zum Einführungskapitel und dem SOA-
Expertenrat und seinen Bloggern für die vielen Ideen und Inputs zum SOA Blueprint
und schließlich unseren Kollegen, Kolleginnen, Freunden, Freundinnen, Angehörigen
sowie dem Korrektor und den Verlagsmitarbeiterinnen für ihre Geduld.
Basel, Bern, Frankfurt, München, Stuttgart und Zürich im April 2007
Daniel Liebhart, Guido Schmutz, Marcel Lattmann, Markus Heinisch, Michael Könings, Mischa Kölliker, Perry Pakull und Peter Welkenbach
Vorwort
XIII
Vorwort der ersten Auflage
Architecture Blueprints sind Anleitungen und Orientierungshilfen für den Bau von
Individualsoftware. Dieses Buch definiert Architekturstandards für die Technologien
Java Spring, Microsoft .NET, Oracle ADF, Oracle Forms und SOA.
Wir haben dieses Buch geschrieben, weil es einem Bedürfnis entspricht, die Lücke
zwischen den Vorstellungen der großen Hersteller und den theoretischen Ansätzen
der reinen Lehre zu füllen. Wir leisten damit einen Beitrag, um die Qualität und Pro-
duktivität der Individualentwicklung zu erhöhen. Das Buch soll helfen, Softwaresys-
teme effizienter, qualitativ hoch stehend und kostengünstig zu erstellen, betreiben
und beurteilen.
Das Buch ist für IT-Professionals die Software entwickeln, für Architekten die Ge-
samtsysteme gestalten, für Manager und Projektleiter die den Einsatz verschiedener
Technologien beurteilen und für Systemadministratoren die Anwendungen betrei-
ben.
Jede Technologie ist in einem einzelnen Kapitel beschrieben. Jedes dieser Kapitel
kann für sich alleine gelesen werden. Der Leser und die Leserin finden in jedem Ka-
pitel einen Architecture Blueprint, dessen Bestandteile (Building Blocks) erklärt wer-
den. Zusätzlich haben wir unsere Erfahrungen beim Einsatz der jeweiligen Technolo-
gie reflektiert, als „Do’s“ und „Dont’s“ zusammengestellt und auf die Besonderheiten
hingewiesen.
Das einführende Kapitel „Grundlegende Architekturkonzepte“ wurde von Guido
Schmutz, Mischa Kölliker und Peter Welkenbach verfasst. Es beschreibt die konzep-
tionelle Basis der Architekturen, die in den nachfolgenden Kapiteln ausgeführt wer-
den.
Das Kapitel „Spring Framework Architecture Blueprint“ wurde ebenfalls von Guido
Schmutz, Mischa Kölliker und Peter Welkenbach verfasst. Sie stellen den Architek-
turstandard für das Java Spring Framework vor. Dieses Kapitel ist ausführlich gehal-
ten, da die Vielfalt der möglichen Frameworks und Komponenten im Bereich „Enter-
prise Applications“ mit Java einer genauen Betrachtung, Bewertung und Gewichtung
bedürfen.
„Microsoft .NET Architecture Blueprint“ wurde von Michael Könings geschrieben. Es
fasst das von Urs Meier, Christoph Pletz, Marcel Lattmann und Željko Savić entwi-
ckelte „Enterprise Application Programming“ Framework zusammen und beschreibt,
wie leistungsfähige betriebliche Anwendungen auf Basis der .NET Plattform gestaltet
werden.
„Oracle ADF Architecture Blueprint“ wurde von Markus Heinisch geschrieben. Er
fasst die Einsatzgebiete, die Stärken und die Schwächen von Oracle ADF als Enterprise
Framework zusammen. Besonders vertieft werden die Business Components, deren
Layering und Anwendungsregeln.
Vorwort
XIV
„Oracle Forms Architecture Blueprint“ hat Perry Pakull verfasst. Er zeigt auf, wie die
traditionelle 4 GL Technologie Oracle Forms als produktives Werkzeug für die Reali-
sierung moderner Multi-Tier Anwendungen eingesetzt werden kann. Unabhängig
vom Hersteller Oracle werden Upgradeszenarien, Sizingregeln und Layeringprinzi-
pien erläutert und vertieft.
„SOA Blueprint“ wurde von Daniel Liebhart geschrieben. Der SOA Blueprint zeigt
ein herstellerunabhängiges, pragmatisches Architekturmodell auf. Die möglichen Ska-
leneffekte für ein Unternehmen, der Einfluss auf eine IT Organisation und die Stärken
von SOA, in Bezug auf die Weiterverwendung bestehender Systeme, werden ausge-
führt.
Sämtliche Kapitel wurden im Teamwork von allen Autoren gemeinsam konzeptionell
entwickelt, intensiv diskutiert, teilweise verworfen, komplett überarbeitet und mehr-
fach reviewed.
An dieser Stelle danken die Autoren allen Personen, die in irgendeiner Weise einen
Beitrag zum Entstehen dieses Buches geleistet haben. Der Firma Trivadis AG dafür,
dass dieses Buch überhaupt möglich war. Anton Rasch und Dirk Jablonski für den
Review des Kapitels „Grundlegende Architekturkonzepte“ und des Kapitels „Spring
Framework Architecture Blueprint“. Marcel Lattmann und Željko Savić für den Re-
view des Kapitels Microsoft .NET Architecture Blueprint“ und im speziellen Željko
Savić für die Mithilfe bei der Überarbeitung dieses Kapitels und Urs Meier für den
reichhaltigen Input. Yves Caloz und Ulrich Vogel für den Review des Kapitels „Orac-
le ADF Architecture Blueprint“. Walter Müller und Stefan Jüssen für den Review des
Kapitels „Oracle Forms Architecture Blueprint“ und im speziellen Gudrun Pabst für
das Migrationsszenario. Fernand Hänggi für den Review des Kapitels „SOA Blue-
print“, Bettina Stucki für die Organisation unserer Workshops und schließlich unse-
ren Partnern und Freunden für Ihre Nachsicht.
Basel, Bern, Frankfurt, München, Stuttgart und Zürich im September 2006
Daniel Liebhart, Guido Schmutz, Markus Heinisch, Michael Könings, Mischa Kölliker, Perry Pakull und Peter Welkenbach
Vorwort
XV
Die Autoren
Daniel Liebhart ([email protected])
Daniel Liebhart verfügt über 20 Jahre Erfahrung in der IT und über 10 Jahre Erfahrung
im Management von IT-Dienstleistungen und Produktentwicklung. Seine Branchen-
und Fachkenntnisse umfassen die Konzeption, Architektur, Realisierung und Betrieb
komplexer und international betriebener Gesamtsysteme im Telekommunikations-,
Finanzdienstleistungs-, Logistik- und Industriebereich. Daniel Liebhart ist leidenschaft-
licher Informatiker, Träger mehrerer Auszeichnungen und Dozent für Softwarearchi-
tektur und Wirtschaftsinformatik an der Hochschule für Technik in Zürich.
Guido Schmutz ([email protected])
Guido Schmutz ist seit über 20 Jahren als Software Entwickler, IT-Berater, Chef-Ar-
chitekt, Trainer und Coach tätig. Als Leiter des Bereichs Application Development des
Trivadis Technologie Center verfasst er viele Fachpublikationen, entwickelt er IT-Stra-
tegien, Kurse und TechnoCircles und tritt als Sprecher auf internationalen Konferen-
zen auf. Guido Schmutz ist für die Innovation, Konzeption und Realisierung zahlrei-
cher DWH-, CRM-, CSM-, MIS- und EAI-Lösungen für internationale Finanzinstitute,
Pharmakonzerne, öffentliche Verwaltungen und Logistikunternehmen verantwortlich.
Seine Spezialgebiete sind Enterprise Architecture, Bitemporale Datenhaltung, Java
Persistenz und das Spring Framework.
Marcel Lattmann ([email protected])
Marcel Lattmann arbeitet als System Architekt, Senior Software Engineer und Haupt-
referent im Bereich Microsoft Enterprise Solutions. Er ist spezialisiert auf die Konzep-
tion, Beratung und Realisierung von CRM-, POS- und Forecasting-Lösungen für Fi-
nanzdienstleister, Pharmakonzerne und Industriebetriebe. Sein besonderes Interesse
gilt dem Corporate Knowledge Engineering, der Architektur von Libraries und Frame-
works und der Anwendung von Automated Software Testing and Verification Verfah-
ren. Als Technology Owner Microsoft Application Development des Trivadis Techno-
logie Center entwickelt er Kursunterlagen, Realisierungsszenarien und Consulting-
strategien für Konzerne, IT Dienstleister und Engineering Teams.
Markus Heinisch ([email protected])
Markus Heinisch ist Projektleiter, Architekt und Senior Consultant mit Schwerpunkt
Automobilindustrie, Halbleiterfertigung, Immobilienverwaltung und Verlagswesen.
Er verfügt über langjährige Erfahrung in der Software Produktenwicklung und war als
Chef-Architekt, Presales-Consultant und Manager für das Engineering und die Reali-
sierung von Basiskomponenten einer umfangreichen DMS-Suite für den Weltmarkt
verantwortlich. Seine technischen Schwerpunkte sind heute die Anwendungsent-
wicklung mit Oracle ADF, J2EE und modernen Web-Technologien. Markus Heinisch
ist Referent und Kursautor im Bereich Java und XML und prüft neue Technologien
und Produkte hinsichtlich ihrer Einsatzmöglichkeiten in Kundenprojekten.
Die Autoren
Vorwort
XVI
Michael Könings ([email protected])
Michael Könings arbeitet als Software Engineer, Architekt, Berater und Projektleiter
für die Pharmaindustrie und für internationale Finanzdienstleister. Er verfügt als Dip-
lom-Betriebswirt und Wirschaftsinformatiker über viele Jahre Erfahrung in der Kon-
zeption, Entwicklung und im Betrieb von Management Informationssystemen. Er war
lange als Kursautor, Trainer und Hauptreferent in den Bereichen Modellierung und
Design von relationalen Datenbanken tätig. Die Entwicklungstools Oracle Forms,
Reports, Designer hat er in zahlreichen Projekten eingesetzt. Michael Könings ist
Spezialist für die Entwicklung von Enterprise Solutions basierend auf der Microsoft
.NET Technologie und die Konzeption von Corporate Performance Management Sys-
temen.
Mischa Kölliker ([email protected])
Mischa Kölliker ist als Senior Architekt für die Konzeption, Gesamtarchitektur und
Qualitätsicherung in Kundenprojekten im Finanz- und Telekommunikations-Sektor
verantwortlich. Er verfügt über viele Jahre Erfahrung in der Realisierung und Projekt-
leitung in der Software Produktenwicklung eines Telekommunikation Network Ma-
nagement Systems. Er hat high-end Softwarelösungen für einen sehr großen Anwen-
derkreis analysiert, spezifiziert, umgesetzt und betrieben. Mischa Kölliker setzt sich
als Kursreferent und Autor von Fachpublikationen mit den Schwerpunkten Software-
Entwicklung nach CMM Qualitäts-Standard, Java Security, Spring Framework, Perfor-
mance Management und Data Warehouse Engineering auseinander.
Perry Pakull ([email protected])
Perry Pakull arbeitet seit Jahren als Software Eningeer, Berater, Trainer und Senior
Architekt im Bereich Oracle Application Development. Er hat 20 Jahre Erfahrung in
der Entwicklung und Betreuung betrieblicher Anwendungssoftware. Die Entwick-
lungstools Oracle Forms, Reports, Designer setzt er seit über 10 Jahren in zahlrei-
chen Projekten ein. Sein Spezialgebiet ist die Analyse und die Umsetzung von Busi-
nessprozessen für Pharmakonzerne, Automobilhersteller, Halbleiterproduzenten und
Großhandelsketten. Sein aktueller technischer Schwerpunkt sind Web Applikationen
im Oracle Forms und Oracle Java Umfeld, basierend auf der Oracle Application Ser-
ver Technologie. Perry Pakull ist als Autor von Kursunterlagen, Kursreferent für die
Themen PL/SQL, Oracle Portal und Oracle Application Server und als Projektverant-
wortlicher und Software Architekt für Produktionssteuerungs-, Warenwirtschafts- und
Prozessleitsysteme tätig.
Peter Welkenbach ([email protected])
Peter Welkenbach arbeitet als Berater, Senior Architekt und Trainer in den Bereichen
Requirement Engineering, Objektorientierte Methodik, Software Engineering und
Quality Management. Er hat über 20 Jahre Erfahrung in der Konzeption und Realisie-
rung komplexer Informationssysteme für Finanzinstitute, Automobilhersteller und
Pharmakonzerne. Er setzt sich seit 10 Jahren als Technologie-Evangelist mit der Java
Die Autoren
Vorwort
XVII
Technologie und dem Einsatz der entsprechenden Frameworks in Kundenprojekten
auseinander. Sein aktueller technischer Schwerpunkt ist das Model Driven Software
Development, UML, Aspect Oriented Programming, JSF, AJAX und Architecture De-
sign Methodology. Peter Welkenbach ist Kursautor, Verfasser zahlreicher Publikatio-
nen und Sprecher auf der JAX und internationalen Oracle Konferenzen. Er setzt Spring
seit dessen Erscheinen im Sommer 2003 in vielen Kundenprojekten ein.
Die Autoren
Daniel Liebhart, Guido Schmutz, Marcel Lattmann, MarkusHeinisch, Michael Könings, Mischa Kölliker, Perry Pakull, Peter
Welkenbach
Architecture BlueprintsEin Leitfaden zur Konstruktion von Softwaresystemen mit Java
Spring, .NET, ADF, Forms und SOA
ISBN-10: 3-446-41201-8ISBN-13: 978-3-446-41201-9
Leseprobe
Weitere Informationen oder Bestellungen unterhttp://www.hanser.de/978-3-446-41201-9
sowie im Buchhandel
1
1 1 Grundlegende Architekturkonzepte
In diesem Kapitel stellen wir einige theoretische Grundlagen guten Software-Entwurfs
aus heutiger Sicht vor. Diese Konzepte lassen sich mit allen modernen Plattformen
und Frameworks ähnlich gut umsetzen (wenn auch nicht immer in vollem Umfang)
und können als State of the Art des modernen Applikationsdesigns gelten. Design-
Guidelines werden mit Design Patterns beschrieben.
Dies ist kein Buch für Anfänger. Wir gehen daher davon aus, dass dem Leser die
grundlegenden Design-Patterns und -Prinzipien bekannt sind und auch eine Layered
Architecture kein Fremdwort ist. Deshalb wollen wir Sie als Leser nicht mit einer
bloßen Auflistung von Patterns langweilen, sondern die wichtigsten Enterprise-Archi-
tektur-Patterns in ihrem natürlichen Umfeld beschreiben. Für einige der hier nicht
beschriebenen, aber trotzdem wichtigen Pattern und Prinzipien verweisen wir auf die
gängige Literatur zum Thema (Fowler, 2003), (Gamma et al., 1995), (Eilebrecht et al.,
2007).
Nach der Lektüre dieses grundlegenden Kapitels sollten dem Leser die wesentlichen
Architektur- und Design-Konzepte bekannt sein und ihm beim Lesen der weiteren
Kapitel zum besseren Verständnis dienen.
1.1 Enterprise Application Architecture Patterns
Ein Design Pattern ist ein existierendes Software-Konstrukt und gleichzeitig eine Re-
gel, die beschreibt wie und wann dieses zu erstellen ist. Die Beschreibung dieser
Kombination umfasst einen Namen und Erörterungen der Problemstellung und der
Lösung.
Design Patterns gehen ursprünglich auf den Architekten – nein: kein Software-Ar-
chitekt, sondern ein richtiger Häuserbauer – Christopher Alexander zurück, der in
seinem Buch „The Timeless Way of Building“ bauliche Maßnahmen, die sich wie-
derholten, in Form von Patterns beschrieb. Im Folgenden ein Beispiel einer solchen
Pattern-Beschreibung:
1 Grundlegende Architekturkonzepte
2
Pattern Name: “An architectural pattern example – Window Place.”
Problemkontext: “Everybody loves window seats, bay windows, and big windows
with low sills and comfortable chairs drawn up to them. … A room which does not
have a place like this seldom allows you to feel comfortable or perfectly at ease. …
If the room contains no window which is a ‘place’, a person in the room will be torn
between two forces:
He wants to sit down and be comfortable.
He is drawn toward the light.
Obviously, if the comfortable places – those places in the room where you most
want to sit – are away from the windows, there is no way of overcoming this conflict.
…”. Lösungskontext: “Therefore: In every room where you spend any length of time
during the day, make at least one window into a ‘ window place’.”
Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides (Gamma et al.,
1995) haben dieses Konzept dann Mitte der Neunziger auf die Softwareentwicklung
übertragen. Ihr Buch „Design Patterns – Elements of Reusable Object-Oriented De-
sign“ gilt als Basis für alle weiteren Beschreibungen von Design Patterns in der Soft-
wareentwicklung. Seitdem haben viele Autoren weitere Design Patterns für unter-
schiedliche Kontexte (z.B. Strukturpatterns, Refactoring-Patterns) und Programmier-
sprachen publiziert.
Die Hauptaufgabe von Design Patterns besteht in der Weitergabe und der Wieder-
verwendung von Erfahrung. Design Patterns beschreiben Best Practices und Lösun-
gen von erfahrenen Designern. Unterschiedliche Technologien und Programmier-
sprachen erlauben unterschiedliche Realisierungen einzelner Design Patterns. Viele
moderne Frameworks realisieren Design Patterns im Hintergrund und gestatten auch
unerfahrenen Programmieren, Anwendungen nach modernen Design-Richtlinien zu
erstellen.
In der Regel kann jedes Pattern einer bestimmten Schicht (Layer) zugeordnet werden,
z.B. dem User-Interface Layer oder dem Domain Layer. Das Pattern bietet dann eine
Lösung eines typischen Problems in diesem Layer. Im Folgenden stellen wir einige zen-
trale Design Patterns im Kontext des jeweiligen Layers kurz vor. Für tiefergehende
Erörterungen sei auf die Original-Literatur verwiesen bzw. auf Literatur, die die ein-
zelnen Patterns im Kontext konkreter Programmiersprachen darstellt (z.B. C#, Java).
1.2 Application und Domain Layer
Die zentralen Teile der meisten Enterprise-Applikationen sind der Application und
der Domain Layer. Hier sind die Business-Logik und die Verknüpfung von Domain-
Modulen zu Services angesiedelt.
Für die Organisation der Domänenlogik sieht Fowler (Fowler, 2003) drei verschiede-
ne Patterns vor: Transaction Script, Domain Model und Table Module.
1.2 Application und Domain Layer
3
Fowler beschreibt eine zusätzliche Möglichkeit, die Domänenlogik aufzutrennen,
indem er einen Service Layer über ein darunterliegendes Domain Model oder Table
Module legt. Diese wichtigen Pattern werden in den folgenden Abschnitten ausführ-
lich behandelt.
1.2.1 Transaction Script
Transaction Script
Das Transaction Script organisiert und unterteilt die Geschäftslogik in einzelne Prozedu-
ren, sodass jede Prozedur eine einzelne Anfrage vom Presentation Layer abdeckt.
Viele einfache Geschäftsapplikationen können als eine Serie von Einzeltransaktionen
angesehen werden. Dies gilt in hohem Maß für klassische Client/Server-Applikatio-
nen.
Jede Interaktion zwischen Client und Server enthält ein begrenztes Maß an (nicht all-
zu komplexer) Geschäftslogik. In den meisten Fällen handelt es sich hierbei um
simple Validierungen und Kalkulationen und betrifft nur wenige Entitäts-Typen (Ach-
tung: nicht „Einzelobjekte“!) pro Interaktion.
Transaction Script kapselt diese Logik pro Interaktion in einzelne Operationen und
kommuniziert direkt oder nur über einen schlanken Adapter mit einer relationalen
Datenbank. Jede Transaktion hat ihr eigenes Transaction Script. In vielen Fällen ent-
spricht ein Transaction Script einer Datenbank-Transaktion. Es gibt zwei Möglichkei-
ten, die Transaction-Script-Logik zu modularisieren:
Ein Transaction Script pro Operation einer Klasse
Ein Transaction Script pro Klasse (Command Pattern)
Beide haben Vor- und Nachteile. Beim generischen Command Pattern trägt jede
Operation den gleichen Namen (z.B. execute() ); der Klassenname sollte die Se-
mantik der Transaktion beschreiben. Beim anderen Ansatz beschreibt der Operati-
onsname hingegen die Semantik, womit sich Intention Revealing Interfaces realisie-
ren lassen. Das Command Pattern in Kombination mit Memento ist wichtig für Kom-
pensationen (Compensating Transaction), wie sie vor allem in einer SOA vorkom-
men.
Service
Ein Service fasst semantisch nahestehende Transaction Scripts als einzelne Service-
Methoden zusammen. Diese einzelnen Transaction Scripts delegieren dann an einen
Command und Memento realisierenden Helfer Service, der auch für Kompensationen
zuständig ist. Im Allgemeinen wird dies ein interner Teil des Application Service selbst
sein, um die Einfachheit in diesem Ansatz zu wahren.
Ein Applikations-Service realisiert in diesem Blueprint das Transaction Script Pattern.
Mehr zur Anwendung dieses Patterns folgt in Abschnitt 1.5.3.
1 Grundlegende Architekturkonzepte
4
User Interface
Application
Domain
Infrastructure
View
ApplicationService
ApplicationService
remoting
DTOAssembler
Persistence
DAOFactory Validator
Client Tier
Middle Tier
Abbildung 1.1 Transaction Script Architecture
1.2.2 Domain Model
Domain Model
Domain Model beschreibt ein Objektmodell der Problemdomäne, welches Verhalten
und Daten umfasst.
Das Modell setzt sich aus einem Netzwerk feingranularer Klassen zusammen. Jede
einzelne dieser Klassen repräsentiert ein wichtiges Objekt der Geschäftsdomäne.
Hierbei kann es sich um etwas so Großes wie einen Konzern oder aber um eine ein-
zelne Zeile einer Rechnung handeln.
Ein OO Domain Model ist einem relationalen Datenbankmodell sehr ähnlich, doch
kapselt es nicht nur Daten, sondern auch das den Daten zugeordnete Verhalten und
wird in Teilen nicht normalisiert sein, d.h., auch Listen und Maps als Attribute sind
enthalten. Außerdem unterscheidet es sich durch den Einsatz von Vererbung.
Fowler diskutiert hierzu zwei Variationen des Domain Model Patterns:
Simple Domain Model
Rich Domain Model
Simple Domain Model
Das Simple Domain Model entspricht fast 1:1 dem Datenbankmodell, wobei jede
Tabelle durch einen Domänen-Entitätstypen repräsentiert wird. Bei diesem Design
kommt man oft mit Active Record (Fowler, 2003) aus. Active Record implementiert
die Datenzugriffslogik direkt im Domänenobjekt. Der Einsatz dieses Patterns ist des-
1.2 Application und Domain Layer
5
User Interface
Application
Domain
Infrastructure
View
ApplicationService
ApplicationService
Remoting
DomainService
Aggregate
Entity ValueObject
Factory Repository
DTOFactory
Contract
Persistence
Domain Component
Client Tier
Middle Tier
Abbildung 1.2 Rich Domain Modell-Architektur
halb aus Gründen der Wartbarkeit nur bei ganz einfachen Modellen zu empfehlen.
Oftmals ist es besser, diese Arbeit einem Data Mapper (siehe Abschnitt 1.2.2.1)
zu überlassen, respektive einem Framework, das dieses Pattern implementiert (z.B.
iBaits, Hibernate). Der folgende Abschnitt beschreibt das Data Mapper Pattern in de-
taillierter Form.
Rich Domain Model
Das Rich Domain Model unterscheidet sich erheblich vom Datenbankmodell, u.a.
durch Anwendung diverser OO-Konzepte und Design Patterns (Vererbung, Strategy
Pattern, Command Pattern etc.). Bei diesem Ansatz ist die Verwendung eines Data
Mappers (siehe Abschnitt 1.2.2.1) unumgänglich, Active Record ist hier nicht mehr
das angemessene Design.
Das Rich Domain Model ist das zentrale Konzept des Domain Driven Designs. Die-
ses wird in Abschnitt 1.5 im Detail beschrieben.
1 Grundlegende Architekturkonzepte
6
1.2.2.1 Data Mapper
Data Mapper
Data Mapper definiert eine Schicht von Mappern, die Daten zwischen den Objekten
und der Datenbank transferiert, ohne dabei die Objekte und die Datenbank voneinander
und vom Mapper abhängig zu machen.
Person
- dateOfBirth: Date- firstName: String- lastName: String
+ getAddress() : Address
PersonMapper
+ delete() : void+ insert() : void+ update() : void
person_t
Abbildung 1.3 Data Mapper Pattern
Objekte und relationale Datenbanken weisen unterschiedliche Mechanismen auf,
um Daten zu strukturieren. Viele Konzepte der Objekt-Orientierung, wie Collections
und Vererbung, gibt es in der relationalen Datenbank nicht. Bei Objekt-Modellen mit
einem großen Anteil an Geschäftslogik und der Verwendung der objektorientierten
Konzepte werden das Objektmodell und das Datenmodell relativ unterschiedlich
aussehen und stimmen nicht 1:1 überein.
Trotzdem will man in der Lage sein, Daten zwischen den beiden Modellen zu trans-
ferieren – der Datentransfer kann daher sehr komplex werden.
Der Data Mapper ist eine Software-Schicht, die im Hauptspeicher befindliche Objek-
te von der Datenbank trennt. Seine Verantwortung liegt allein im Datentransfer zwi-
schen den Objekten und der Datenbank und damit der Isolation der beiden Schich-
ten. Mit dem Data Mapper benötigen die Objekte keine Kenntnis darüber, ob und
welche Datenbank vorhanden ist; sie brauchen keinen SQL Code abzusetzen und
müssen das Datenbank-Schema nicht kennen.
1.2.3 Table Module
Table Module
Table Module beschreibt eine einzelne Instanz (Singleton), die die Geschäftslogik
für alle Zeilen in einer Datenbanktabelle oder View kapselt.
Ein Problem des Domain Model ist der so genannte Impedance-Mismatch: Die Abbil-
dungsproblematik zwischen objektorientiertem Domain Model und relationalem Da-
tenbankmodell.
Ein Table Module organisiert die Geschäftslogik in einer Klasse pro Datenbanktabelle
(oder View). Der primäre Unterschied zum Domain Model liegt hierbei in der Ob-
jekt-Identität und Objekt-Multiplizität.
Betrachten wir ein typisches Master-Detail-Szenario mit einer Liste von n Einzel-
positionen, die einem Auftrag zugeordnet sind.
1.2 Application und Domain Layer
7
Während beim Domain Model der Auftrag ein Objekt ist, mit n Referenzen auf die n
Einzelpositions-Objekte, kommt das Table Module mit einem (Listen-)Objekt aus, das
alle Einzelpositionen kapselt. Im Domain Model hat jede Einzelposition eine eindeu-
tige Objekt-Identität, über die es angesprochen werden kann. Im Table Module ist
nur das Listenobjekt bekannt, die Einzelpositionen sind hinsichtlich ihres Zugriffs
anonym. Zum Auffinden eines einzelnen Positionsobjektes in der Liste muss eine ID
(meist der PK der Datenbank) oder der Listenindex bekannt sein.
User Interface
Application
Domain
Infrastructure
View
ApplicationService
ApplicationService
Remoting
DTOAssembler
Persistence
Table Module Validator
Client Tier
Middle Tier
Abbildung 1.4 Table Module-Architektur
Oft ist ein Table Module genau einer Tabelle zugeordnet und kapselt die Operatio-
nen auf diesen Daten.
Das Table Module Pattern verwendet für die Datenzugriffslogik die beiden Pattern
Table Data Gateway und Row Data Gateway. Diese werden in den folgenden Ab-
schnitten im Detail beschrieben.
1.2.3.1 Table Data Gateway
Table Data Gateway
Ein Objekt, das als Gateway (Fowler, 2003) zu einer Datenbanktabelle auftritt.
Eine einzige Instanz behandelt alle Rows einer Tabelle (1 Instanz/n Rows).
Die Vermischung von SQL und Applikations-Logik kann mehrere Probleme verursa-
chen. Viele Entwickler sind es nicht gewohnt, SQL zu schreiben, und beherrschen
diese Aufgabe möglicherweise nicht besonders gut. Zudem sollen die SQL State-
ments möglichst unabhängig vom Code bleiben, damit man sie auch nachträglich
einfach anpassen kann.
1 Grundlegende Architekturkonzepte
8
«Table Data Gateway»PersonGateway
+ delete(long) : void+ findById(long) : Person+ findByName(String) : void+ insert(String, String, Date) : void+ update(long, String, String, Date) : void
person_t
Abbildung 1.5 Table Data Gateway Pattern
Ein Table Data Gateway enthält alle notwendigen SQL-Befehle für eine bestimmte
Tabelle oder View: Selects, Inserts, Updates und Deletes. Abbildung 1.5 zeigt, wie
die SQL-Befehle als Methoden zur Verfügung gestellt werden. Der gesamte Code ruft
die Methoden des Table Data Gateway auf, um mit der Datenbank zu interagieren.
Abbildung 1.6 zeigt das Pattern in Aktion.
user
:View :TableDataGateway :Database:Persistence :TableModule
search(Criteria)
findByCriteria(Criteria)findByCriteria(Criteria)
select
ResultSet
RowSet
apply domain logic(RowSet)
render
Rendered RowSet data
modified RowSet
validate(RowSet)
save (RowSet)
save(RowSet)
insert/update
Abbildung 1.6 Interaktionen mit Table Data Gateway und Table Module
1.2.3.2 Row Data Gateway
Row Data Gateway
Row Data Gateway ist ein Objekt, das als Gateway (Fowler, 2003) zu einem
einzelnen Tabellenrecord auftritt. Es handelt sich um eine Instanz, die jeweils
einen Tabellenrecord betrifft (1 Instanz / 1 Row).
1.2 Application und Domain Layer
9
Das Problem ist die Abbildung des OO Domänen-Modells auf das Datenbankmo-
dell. Beim Konzept des Row Data Gateway wird jede Klasse des Domänen-Modells
durch eine separate Tabelle in der Datenbank repräsentiert. D.h. im Umkehrschluss:
Jede Zeile in der Datenbanktabelle entspricht genau einer Instanz der durch die Ta-
belle repräsentierten Klasse. Die Zugriffsmechanismen werden durch das Konzept
des Row Data Gateway realisiert. Es wird ein Objekt erzeugt, das als Gateway auftritt
und eine Zeile repräsentiert.
PersonFinder
+ findById(long) : Person+ findByLastName(String) : Person[]
«Row Data Gateway»PersonGatew ay
- dateOfBirth: Date- firstName: String- lastName: String
+ delete() : void+ insert() : void+ update() : void
person_t
Abbildung 1.7 Row Data Gateway Pattern
Ein Row Data Gateway erzeugt Objekte, die genauso aussehen wie die Records in
der Datenbank, können aber mit den regulären Mechanismen der Programmierspra-
che bearbeitet werden. Alle Details des Datenzugriffs sind hinter dieser Schnittstelle
verborgen.
1.2.4 Service Layer
Service Layer
Der Service Layer definiert Applikations-Grenzen mit einem Layer von Einzel-Services,
die zusammen ein Set an verfügbaren Operationen aus Sicht des Clients bereitstellen.
Cockburn (Cockburn, 1998) bezeichnet dieses Pattern auch als Application Bounda-
ry.
Der Service Layer koordiniert bei jeder ausgeführten Operation gleichzeitig die Sys-
temantwort (Applikationsantwort) sowie Transaktionen und kapselt die Geschäftslo-
gik der Applikation nach außen ab.
Der Vorteil des Service Layers liegt in der Möglichkeit, unterschiedlichen Clients ein
einheitliches Set an Geschäftsoperationen anzubieten und die Applikationsantwort
für jede Operation einheitlich zu koordinieren.
1 Grundlegende Architekturkonzepte
10
Service Layer wird nicht benötigt, wenn nur eine einzige Art von Client (z.B. ein
Web-Frontend) vorliegt und die realisierten Use Cases keine komplexen Transaktio-
nen mit mehreren Ressourcen verlangen. In solch einfachen Szenarien kann der Page
Controller (Fowler, 2003) die Rolle des Service Layer übernehmen.
Die Service-Operationen ergeben sich im Wesentlichen aus den Use Cases der Ap-
plikation. Bei einfachen CRUD (Create-, Read-, Update-, Delete-) Use Cases ergibt
sich eine 1:1-Abbildung auf die Service Layer-Operationen.
Es gibt zwei Designstrategien, um den Service Layer-Pattern zu implementieren:
Domain Façade
Operation Script
Domain Façade
Der Service Layer wird als dünne Façade über einem Domain Model implementiert.
Hierbei implementieren die Klassen der Façade keinerlei Geschäftslogik; diese wird
im Domain-Modell realisiert. Die Façade des Service Layers entkoppelt Domain Mo-
del und Präsentation und definiert so die Interaktionsmöglichkeiten der Applikation
mit dem Domain Layer, der ja auch von anderen Applikationen genutzt werden
kann.
Operation Script
Hierbei wird der Service Layer durch eine Anzahl Klassen realisiert, die auch eine
gewisse Applikations-Geschäftslogik beinhalten, jedoch die Domänen-Geschäftslogik
an einen Domain Layer delegieren. Auf diese Weise wird ein Design umgesetzt, das
verschiedene Autoren (z.B. Fowler, 2003) bevorzugen:
Trennung der Geschäftslogik in Applikationslogik und Domänenlogik (siehe auch
den Abschnitt zu Domain Driven Design in Abschnitt 1.5 und dabei speziell zu Ser-
vices in Abschnitt 1.5.2.3).
Die den Clients zur Verfügung gestellten Operationen werden als Scripts implemen-
tiert, wobei diese ihrer logischen Zusammengehörigkeit nach in Klassen gruppiert
werden, die dann den Applikations-Service bilden. Typischerweise findet man in sol-
chen Architekturen Klassen mit Namen wie „BookingService“ (gruppiert die Scripts
für den „Booking“ UseCase). Ein Service Layer besteht dann aus diesen Applikations-
Service-Klassen. Diese sollten sich idealerweise von einem Layer Supertype (Fowler,
2003) ableiten.
Bei der Implementation eines Service Layers werden weitere wichtige Pattern ver-
wendet, die wir in den folgenden Abschnitten beschreiben.
1.2 Application und Domain Layer
11
1.2.4.1 Remote Façade
Remote Façade
Die Remote Façade fasst mehrere Operationen auf feingranularen Objekten zusammen
und steigert damit die Effizienz in der Netzwerk-Kommunikation.
In einem objektorientierten System mit komplexer Geschäftslogik wird man viele
feingranulare Objekte vorfinden, mit vielen Interaktionen zwischen den Objekten
und dadurch auch sehr vielen Methodenaufrufen. Das ist richtig so und auch kein
Problem, solange man sich in einem Adressraum befindet. Dies ändert sich aber
schlagartig bei Aufrufen zwischen Prozessen. Remote-Aufrufe sind viel teurer, weil es
dafür auch viel mehr zu leisten gilt: Daten müssen serialisiert, Security geprüft, Pake-
te verschickt und durchs Netzwerk geroutet werden.
«Remote Facade»PersonFacade
+ getPersonDto() : Person+ setPerson(PersonDto) : void
«Domain Object»Person
- dateOfBirth: date- familiyName: String- firstName: String- middleName: String- prefix: String- suffix: String
Abbildung 1.8 Remote Façade Pattern
Inter-Prozess Aufrufe sind um Faktoren langsamer als In-Prozess-Aufrufe – selbst
dann, wenn sich beide Prozesse auf der gleichen Maschine befinden.
Daher muss jedes Remote-Objekt über eine grobgranulare Schnittstelle verfügen, die
die Anzahl notwendiger Aufrufe auf ein Minimum reduziert. Dies hat nicht nur Aus-
wirkungen auf die Methodenaufrufe selbst, sondern auch auf die Objekte. Statt eine
Person und ihre Adressen getrennt zu behandeln, definiert man eine Methode, wel-
che Person und welche Adressen zusammen in einem Aufruf modifiziert werden (ei-
ne so genannte Remote Façade).
Eine Remote Façade ist eine grobgranulare Façade (Gamma 1994) über ein Netz von
feingranularen Objekten. Keines der feingranularen Objekte besitzt ein Remote Inter-
face, und die Remote Façade enthält keine Geschäftslogik. Alles, was die Remote
Façade tut, ist das Übersetzen von grobgranularen Methoden auf die unterliegenden
feingranularen Objekte.
1.2.4.2 Data Transfer Object (DTO)
Data Transfer Object
Das DTO ist ein Datenbehälterobjekt, das die Daten zwischen Layern und Prozessen
überträgt, um – vor allem zwischen physikalischen Tiers – die Anzahl von Methoden-
aufrufen zu minimieren und die Applikationsteile zu entkoppeln.
DTOs sind spezielle Ausprägungen des Value Object Patterns.
1 Grundlegende Architekturkonzepte
12
DTOs müssen serialisierbar sein und orientieren sich vom Design her an der Applika-
tion und nicht an der Domäne. Ein Domain Model kann von unterschiedlichen Ap-
plikationen genutzt werden. Die Applikationen selbst beinhalten jedoch eine unter-
schiedliche Applikationslogik und unterschiedliche Anforderungen an die Präsentati-
on der Daten.
Nehmen wir das hypothetisches Domain Model (Abbildung 1.9) als Beispiel.
Person
- age: int- dob: Date- fi rstName: String- lastName: String- salary: double
Address
- city: String- street: String- zip: String
Abbildung 1.9 Ein hypothetisches Domain Model
Zwei Applikationen benötigen die Logik in diesem Domänen-Modell, die im Zu-
sammenhang mit DTOs jedoch keine Rolle spielt.
Applikation A benötigt das folgende DTO für Personen-Daten, damit diese auf einem
GUI erfasst werden können:
PersonDto
- age: int- firstName: String- lastName: String
Abbildung 1.10 Ein mögliches DTO für Personendaten
Applikation B zeigt an den folgenden Daten Interesse und definiert das DTO für Per-
sonendaten anders. (Selbstverständlich könnten die DTOs auch komplexere, ge-
schachtelte Objektstrukturen darstellen, doch wir vereinfachen hier aus Gründen der
Übersichtlichkeit.)
PersonDto
- ci ty: String- firstName: String- lastName: String
Abbildung 1.11 Ein weiteres mögliches DTO für Personendaten
In diesen beiden einfachen Fällen wäre es kein Problem, den Code für die DTOs von
Hand zu erstellen. Wichtiger und umfangreicher ist jedoch der Code zum Erzeugen
der DTO-Objekte, zum Befüllen dieser und zum Konvertieren von Datentypen (vor
allem bei Web-Anwendungen). Auch diese Aufgabe ließe sich für zwei Applikatio-
nen mit nur diesen beiden DTOs problemlos bewältigen.
Geht man jedoch davon aus, dass sich Anforderungen der beiden Applikationen än-
dern können, und nicht nur ein PersonDto, sondern noch viele weitere benötigt
werden, und kommen evtl. weitere Applikationen hinzu, so wird die Pflege der not-
1.2 Application und Domain Layer
13
wendigen DTOs schnell müßig und lästig. Es müssen Wege gefunden werden, um
die Anforderungen im DTO-Lifecycle möglichst flexibel und effizient zu lösen.
Das Grundproblem besteht darin, zwei Modelle (Domänen-Modell und Applikati-
ons-Modell) aufeinander abzubilden. Dies ist eine Anforderung, die man für Persis-
tenzfragen schon gelöst hat, indem man sog. Mapper (Fowler, 2003) einführt. Solche
DTO-Mapping-Frameworks können eine geeignete Lösung für das beschriebene
Problem darstellen.
DTO-Mapping-Frameworks arbeiten, ähnlich den O/R-Mappern, mit Metadaten, die
Quell- und Zielstrukturen inklusive der notwendigen Typkonvertierungen beschrei-
ben. Eine Laufzeitumgebung nutzt diese Informationen anschließend, um DTO-
Instanzen zu erzeugen, sie mit entsprechend konvertierten Daten aus einer Daten-
quelle oder eine Zieldatenstruktur mit konvertierten Daten aus einem DTO heraus zu
befüllen.
Im Falle der Kopplung zweier Komponenten (oder Services) können durch die Ein-
führung von DTOs zwei Ziele erreicht werden:
Record-Data, ermöglicht einen grobgranularen Operations-Aufruf (wichtig vor al-
lem für Remote-Calls zur Verringerung der Netzlast), d.h. viele feingranulare Auf-
rufe werden zu einem einzigen grobgranularen reduziert. Die Folge: Reduzierung
der Remote-Methodenaufrufe
Beide Services kennen einander nicht und sind somit voneinander unabhängig.
Sie hängen nur vom DTO ab (Einführung einer Indirektion zwischen beiden Ser-
vices).
1.2.4.3 Assembler
Assembler
Ein Assembler nimmt mehrere feingranulare Objekte entgegen und erstellt daraus
ein grobgranulares Datentransfer-Objekt.
Person
- firstName: String- lastName: String
Address
- city: String- street: String- zip: String
PersonDto
- ci ty: String- firstName: String- lastName: String- street: String- zip: String
+ fromXml(String) : void+ toXml() : String
PersonAssembler
«create»
«use»
«use»
1
*
Abbildung 1.12 Assembler zur Erstellung grobgranularer DTO-Objekte
1 Grundlegende Architekturkonzepte
14
1.3 Persistence Layer
Die primäre Aufgabe des Persistence Layers ist es, Objekte in eine (meist relationale)
Datenbank zu speichern und von dort zu lesen. Die meisten der in diesem Kapitel
besprochenen Patterns befassen sich mit dieser Aufgabe. Normalerweise implemen-
tiert man diese Pattern in einer Applikation nicht selbst, sondern überlässt diese Auf-
gabe einem O/R-Mapper wie Hibernate. Trotzdem muss man die von diesen Map-
pern verwendeten Pattern kennen, um sie richtig einsetzen zu können. Im größeren
Kontext verwenden vor allem die in den Abschnitten 1.2.2.1 (Data Mapper), 1.2.3.1
(Table Data Gateway) und 1.2.3.2 (Row Data Gateway) beschriebenen Pattern diese
Mapping-Technologien.
Oft ist der Persistence Layer das Nadelöhr einer Enterprise Applikation. Deshalb sind
hier Techniken wie Caching und Lazy Loading wichtig. Während man das Low-
Level-Caching eher der Datenbank überlassen sollte, erfordern die anspruchsvolleren
Caching-Technologien meist tieferes Know-how hinsichtlich der Applikationslogik.
Der Persistence Layer ist also oft der falsche Platz für Caching. Dem Thema Lazy Loa-
ding widmet sich ein eigenes Unterkapitel.
Ähnlich gelagert ist das Problem des Locking und der Concurrency. Obwohl Fehler,
die durch paralleles Bearbeiten derselben Ressource auftreten, meist in der Applika-
tion (resp. durch den Benutzer) aufgelöst werden müssen, können die grundlegenden
Techniken dazu im Persistence Layer implementiert werden. Diese sind in den Ab-
schnitten 1.3.8 und 1.3.9 beschrieben.
1.3.1 Foreign Key Mapping
Foreign Key Mapping
Foreign Key Mapping bildet eine Assoziation zwischen Objekten auf Foreign Key
Referenzen zwischen Tabellen ab.
Objekte können sich direkt über Objekt-Referenzen referenzieren. Wenn diese Ob-
jekte in der Datenbank gespeichert werden, sollen diese Beziehungen natürlich auch
mit gespeichert werden. Dabei können nicht einfach die Werte der Beziehungen in
die Datenbank geschrieben werden, da diese Laufzeit-Referenzen des entsprechen-
den Programms sind. Eine zusätzliche Schwierigkeit entsteht dadurch, dass ein Ob-
jekt auch Collections von Referenzen auf andere Objekte halten kann. Solch eine
Struktur missachtet die erste Normalform einer relationalen Datenbank.
Ein Foreign Key Mapping bildet eine Objekt-Referenz auf einen Foreign Key in der
Datenbank ab.
1.3 Persistence Layer
15
Person
- dateOfBirth: Date- fi rstName: String- lastName: String
Address
- ci ty: String- street: String- zipCode: String
person_t
«column»*PK ID: NUMBER(8,2) FIRST_NAME: VARCHAR(50) LAST_NAME: VARCHAR(50) DATE_OF_BIRTH: DATE
«PK»+ PK_person_t(NUMBER)
address_t
«column»*PK ID: NUMBER(8,2) STREET: VARCHAR(50) FK PERSON_ID: NUMBER(8,2) CITY: VARCHAR(50)
«FK»+ FK_ADR_PERS(NUMBER)
«PK»+ PK_address_t(NUMBER)
+FK_ADR_PERS
0..*1
1 *
Abbildung 1.13 Foreign Key Mapping
1.3.2 Association Table Mapping
Association Table Mapping
Association Table Mapping speichert eine Assoziation als zusätzliche Tabelle mit
Foreign Key-Referenzen auf die beiden Tabellen, welche durch die Assoziation
verbunden werden.
Employee Project
employee_t
«column»*pfK ID: NUMBER(8,2)
«FK»+ FK_EMPLOYEE(NUMBER)
«PK»+ PK_employee_t(NUMBER)
project_t
«column»*PK ID: NUMBER(8,2)
«PK»+ PK_project_t(NUMBER)
employee_project_t
«column»*PK EMPLOYEE_ID: NUMBER(8,2)*pfK PROJECT_ID: NUMBER(8,2)
«FK»+ FK_PROJECT(NUMBER)
«PK»+ PK_employee_project_t(NUMBER, NUMBER)
+FK_PROJECT
0..* 1
+FK_EMPLOYEE
0..* 1
0..*
+member
0..*
Abbildung 1.14 Association Table Mapping Pattern
Objekte können Multi-value-Attribute einfach über Collections behandeln. Relationa-
le Datenbanken kennen dies nicht und beschränken sich auf Single-value-Columns.
Wenn man eine 1:n-Assoziation auf die Datenbank abbilden will, kann dies über Fo-
reign Key Mapping geschehen, indem ein Foreign Key auf der 1:-Seite verwendet
1 Grundlegende Architekturkonzepte
16
wird. Bei einer n:m-Assoziation ist dies nicht möglich, da auf keiner Seite der Bezie-
hung ein einzelner Wert steht.
Die Antwort ist die klassische Lösung, die man im Datenbank-Umfeld bereits seit
Jahren kennt und anwendet: es wird eine zusätzliche Tabelle benutzt, um die Bezie-
hung zu speichern. Mit dem Association Table Mapping Pattern können die Multi-
value-Attribute auf diese Link-Tabelle abgebildet werden.
1.3.3 Single Table Inheritance
Single Table Inheritance
Single Table Inheritance repräsentiert eine Klassen-Vererbungshierarchie als einzelne
Tabelle, die Columns für alle Attribute der einzelnen Klassen enthält.
person_t
«column» DESCRIPTION: FIRST_NAME: LAST_NAME: DATE_OF_BIRTH: ORG_NAME: FOUNDATION_DATE:
Party
- description: String
Person
- dateOfBirth: Date- firstName: String- lastName: String
Organisation
- name: String
Company
- foundationDate: Date
Abbildung 1.15 Single Table Inheritance
Single Table Inheritance ist eine Möglichkeit, Attribute einer Vererbungshierarchie
auf Tabellen einer relationalen Datenbank zu mappen. Die Alternativen dazu sind
Class Table Inheritance (Abschnitt 1.3.4) und Concrete Table Inheritance (Abschnitt
1.3.5).
Die Stärken von Single Table Inheritance:
Es gibt nur eine Tabelle in der Datenbank.
Um Daten zu laden, benötigt man keine Joins.
Refactoring von Attributen nach oben oder unten in der Hierarchie im Domain
Model hat keine Auswirkungen auf die Datenbank.
1.3 Persistence Layer
17
Die Schwächen von Single Table Inheritance:
Columns sind manchmal relevant und manchmal nicht, was zu Unklarheiten füh-
ren kann, wenn die Tabellen direkt angesprochen werden.
Die einzelne Tabelle kann zu groß werden, mit vielen Indizes und häufigem Lo-
cking, was zu Performanceproblemen führen kann.
Da es nur einen einzigen Namensraum für Columns gibt, muss sichergestellt
werden, dass nicht fälschlicherweise die gleiche Column für mehrere Attribute
verwendet wird.
1.3.4 Class Table Inheritance
Class Table Inheritance
Class Table Inheritance repräsentiert eine Klassen-Vererbungshierarchie mit einer
Tabelle pro Klasse.
Company
- foundationDate: Date
Organisation
- name: String
Party
- description: String
Person
- dateOfBirth: Date- fi rstName: String- lastName: String
party_t
«column» DESCRIPTION:
person_t
«column» FIRST_NAME: LAST_NAME: DATE_OF_BIRTH:
organisation_t
«column» NAME:
company_t
«column» FOUNDATION_DATE:
Abbildung 1.16 Class Table Inheritance
Class Table Inheritance ist eine Möglichkeit, Attribute einer Vererbungshierarchie auf
Tabellen einer relationalen Datenbank zu mappen. Die Alternativen dazu sind Single
Table Inheritance (Abschnitt 1.3.3) und Concrete Table Inheritance (Abschnitt 1.3.5).
Die Stärken von Class Table Inheritance:
Alle Columns sind für jede Row relevant und daher einfacher zu verstehen.
Die Beziehung zwischen dem Domain Model und der Datenbank sind „straight-
forward“.
1 Grundlegende Architekturkonzepte
18
Die Schwächen von Class Table Inheritance:
Es müssen mehrere Tabellen gelesen werden, um ein einzelnes Objekt zu laden,
was einen Join oder mehrere einzelne Queries bedeutet.
Refactoring von Attributen nach oben oder unten in der Hierarchie im Domain
Model hat Auswirkungen auf die Datenbank-Tabellen.
Die Tabellen der Supertypen können zum Flaschenhals werden, da auf sie sehr
oft zugegriffen wird.
Der hohe Normalisierungsgrad kann die Tabellenstruktur schwierig für Ad-hoc-
Queries machen.
Dieses Pattern wird oft auch als Leaf Table Inheritance bezeichnet.
1.3.5 Concrete Table Inheritance
Concrete Table Inheritance
Concrete Table Inheritance repräsentiert eine Klassen-Vererbungshierarchie mit einer
Tabelle pro konkreter Klasse in der Hierarchie.
Company
- foundationDate: Date
Organisation
- name: String
Party
- description: String
Person
- dateOfBirth: Date- firstName: String- lastName: String
person_t
«column» DESCRIPTION: FIRST_NAME: LAST_NAME: DATE_OF_BIRTH:
company_t
«column» DESCRIPTION: NAME: FOUNDATION_DATE:
organisation_t
«column» DESCRIPTION: NAME:
Abbildung 1.17 Concrete Table Inheritance
Concrete Table Inheritance ist eine Möglichkeit, Attribute einer Vererbungshierarchie
auf Tabellen einer relationalen Datenbank zu mappen. Die Alternativen dazu sind
Single Table Inheritance (Abschnitt 1.3.3) und Class Table Inheritance (Abschnitt1.3.4).
Die Stärken von Concrete Table Inheritance:
Jede Tabelle ist unabhängig und hat keine irrelevante Columns.
Join-Operationen sind nicht erforderlich, wenn nur Daten von einem konkreten
Domain Object notwendig sind.
1.3 Persistence Layer
19
Auf jede Tabelle wird nur zugegriffen, wenn die dazugehörige Klasse bearbeitet
wird, was die Datenbank-Last verteilen kann.
Die Schwächen von Concrete Table Inheritance:
Primary Keys sind nicht leicht zu handhaben.
Wenn das Objekt-Modell refactored wird und Attribute in den Domänen-Klassen
nach oben oder unten in der Hierarchie verschoben werden, hat dies Auswirkun-
gen auf mehrere Tabellen.
1.3.6 Lazy Load
Lazy Load
Lazy Load ist ein Objekt, das nicht alle benötigten Daten enthält, aber weiß,
wie es diese nachladen kann.
a customer the database
Client
getOrders
[orders not loaded]:
load orders
:orders
Abbildung 1.18 Lazy Load Pattern
Es gibt vier grundsätzlich verschiedene Varianten von Lazy Load.
Lazy Initialization: Verwendet einen speziellen Marker-Wert (normalerweise
null), um zu signalisieren, dass der Wert noch nicht geladen ist. Jeder Zugriff auf
den Wert prüft zuerst gegen den Marker-Wert und lädt den Wert nötigenfalls.
Virtual Proxy: Ein Stellvertreter-Objekt, welches dasselbe Interface wie das Origi-
nalobjekt implementiert. Ruft man zum ersten Mal eine Methode über diesen
Proxy auf, wird im Hintergrund das eigentliche Objekt geladen und der Aufruf an
dieses delegiert.
Value Holder: Ein Objekt mit einer getValue Methode, die von den Clients ver-
wendet wird, um an das eigentliche Objekt heranzukommen. Ruft man zum ers-
ten Mal getValue auf, wird im Hintergrund das eigentliche Objekt geladen und
als Return-Wert von getValue zurückgegeben.
Ghost: Ist bereits das eigentliche Objekt, aber noch ohne geladene Daten. Wird
eine Methode auf dem Ghost erstmals aufgerufen, lädt der Ghost die gesamten
Daten in seine Attribute nach.
1 Grundlegende Architekturkonzepte
20
1.3.7 Query Object
Query Object
Das Query Object repräsentiert Datenbank-Abfragen.
:Query
:Criteria
- field: = "numberOfDependents"- operator: = ">"- value: = 0
:Criteria
- field: = "lastName"- operator: = "="- value: = "muster"
Abbildung 1.19 Query Object
Ein Query Object ist ein Interpreter (Gamma, 1995), das heißt eine Struktur von Ob-
jekten, die sich selbst als SQL Query repräsentieren können. Man kann diese Query
erstellen, indem anstelle von Tabellen und Columns mit Klassen und Attributen ge-
arbeitet wird. Damit können diese Queries unabhängig vom Datenbank-Schema ge-
schrieben werden. Änderungen am Datenbank-Schema lassen sich an einer zentralen
Stelle durchführen.
1.3.8 Optimistic Offline Lock
Optimistic Offline Lock
Der Optimistic Offline Lock behandelt Konflikte zwischen nebenläufigen Geschäfts-
transaktionen, indem ein Konflikt bemerkt und die Transaktion zurückgerollt wird.
Das Optimistic Offline Lock Pattern prüft, bevor eine Datenbank-Änderung durchge-
führt wird, ob die Daten in der Datenbank noch dieselben sind wie zum Zeitpunkt
des Lesens. Nur wenn dies der Fall ist, können die Daten geschrieben werden.
Die meist eingesetzte Implementierung des Optimistic Offline Lock verwendet eine
zusätzlich zu den Daten geführte, bei jeder Änderung eines Datensatzes erhöhte Ver-
sionsnummer.
1.3 Persistence Layer
21
Business Transaction
database
Client1 Client2
getPerson('xyz')
:person, version=22
getPerson('xyz')
:person, version=22
edit person
edit person
update person 'xyz'
ok, version is now 23
update person 'xyz', version=22
failure: wrong person version
Abbildung 1.20 Optimistic Offline Lock
1.3.9 Pessimistic Offline Lock
Pessimistic Offline Lock
Der Pessimistic Offline Lock verhindert Konflikte zwischen nebenläufigen Geschäfts-
transaktionen, indem nur eine Geschäftstransaktion zur gleichen Zeit Zugriff auf eine
bestimmte Ressource hat.
Das Pessimistic Offline Lock Pattern verhindert Konflikte, indem diese gar nicht erst
zugelassen werden. Es zwingt die Geschäftstransaktionen dazu, einen Lock anzufor-
dern, bevor die Daten überhaupt verwendet werden können, also bereits beim Lesen
der Daten. D.h., für den Besitzer des Locks ist garantiert, dass das Speichern der Än-
derungen möglich ist und dass er keine Änderungen einer anderen Transaktion un-
gewollt überschreibt,
Die Verwendung des Pessimistic Offline Lock ist angebracht, wenn die Chance eines
Konfliktes zwischen nebenläufigen Sessions hoch ist oder aber die Kosten eines Kon-
fliktes zu hoch sind. Es gilt zu beachten, dass das Pessimistic Offline Lock Pattern ei-
ne Ergänzung zum Optimistic Offline Lock Pattern ist und nur dann verwendet wer-
den soll, wenn es wirklich notwendig ist. In jedem anderen Fall ist Optimistic Offline
Lock die bessere Lösung.
1 Grundlegende Architekturkonzepte
22
business transaction
Client1 Client2
database
getPerson('xyz')
:person 'xyz'
getPerson('xyz')
error: person locked
edit person
update person 'xyz'
ok
Abbildung 1.21 Pessimistic Offline Lock
1.4 Presentation Layer
Man stelle sich eine Benutzeroberfläche mit einem Eingabefeld und zwei Anzeige-
feldern vor. Im Eingabefeld (vom imaginären Typ TextInputField) kann eine Zahlen-
eingabe vorgenommen werden. Dieser Wert wird als „Actual Value“ bezeichnet. Ein
geänderter Wert wird anschließend von der Applikation mit einem Wert verglichen,
der in einem der beiden Anzeigefelder (ebenfalls vom Typ TextInputField, der hier
als Read-Only konfiguriert sein soll) angezeigt und als „Target Value“ bezeichnet
wird.
Nach einer auf fachlichen Anforderungen basierenden Kalkulation finden Sie im wei-
teren Anzeigefeld den sog. „Calculated Value“. Den fachlichen Regeln entsprechend
wird der kalkulierte Wert einer von drei Kategorien (bad, good, excellent) zugewie-
sen und damit bestimmt, ob er grün, gelb oder rot angezeigt wird.
Je nach Design Pattern erfolgen die einzelnen Schritte in unterschiedlichen Kompo-
nenten der Präsentationsschicht, wie im Folgenden dargestellt.
1.4.1 Forms und Controls
Hierbei handelt es sich laut Fowler um klassische Client/Server-Applikationen, wie
sie in den 90er Jahren z.B. mit Visual Basic, Delphi oder Powerbuilder entwickelt
wurden und noch immer weit verbreitet sind.
Abbildung 1.22 zeigt die Bausteine für das einleitend genannte Beispiel.
1.4 Presentation Layer
23
Reading Form
«event observer»+ actualTextValueChanged() : void
TextInputField
- textColor: Color- textValue: String
«event sender»+ textValueChanged() : void
+calculatedValue
1
+targetValue
1
+actualValue
1 Abbildung 1.22 Forms und Controls – Bausteine
Die beteiligten Bausteine sind als „Reading Form“ und drei zugeordnete TextInput-
Fields zu identifizieren. Unter der „Reading Form“ verstehen wir die GUI-Kompo-
nente, auf der sich die drei Eingabefelder befinden (also typischerweise vom Typ Pa-
nel oder Ähnliches). Die drei TextFelder werden über die Variablen „calculatedVa-
lue“, „targetValue“ und „actualValue“ angesprochen. Die Logik wird über die „Rea-
ding Form“ gesteuert.
Bei den Daten im Datenmodell dieses Design Patterns handelt es sich um klassische
Record Sets – sie sind also meist eine relationale Datenrepräsentation.
Eine typische Kommunikation zwischen den Bausteinen ist in Abbildung 1.23 darge-
stellt: actualValue
:TextInputField
user
Reading Form targetValue:TextInputField
enter new value
textValueChanged
actualTextValueChanged
getTextValue
getTextValue
doCalculation
setTextValue(calculatedValue)
setTextColor
Abbildung 1.23 Forms und Controls – Kommunikation
Es ist deutlich erkennbar, dass die Kommunikation vom „Reading Form“ aus erfolgt.
Fowler charakterisiert diese Architektur durch folgende Eigenschaften:
Eine Form beschreibt das Layout der einzelnen Controls (hier TextInputFields).
Die Form fungiert als Observer für die auf ihr befindlichen Controls und stellt
Callback-Handler-Methoden zur Verfügung, um auf Control-Events reagieren zu
können.
1 Grundlegende Architekturkonzepte
24
Einfache Datenänderungen (1:1 Updates, Typwandlung) erfolgen durch einfaches
Databinding.
Komplexe Datenänderungen (Kalkulationen, Anzeigeoptionen, wie z.B. Farbe) er-
folgen über die Event-Handler-Methoden der Form.
1.4.2 Model View Controller (MVC)
Model View Controller
Model View Controller trennt die User-Interface-Logik in drei Rollen auf.
Beim MVC handelt es sich um das wahrscheinlich bekannteste aller Design Patterns.
Obwohl es in diversen Ausprägungen, die nicht dem Original entsprechen, umge-
setzt wird, bezeichnet man viele der Implementierungen als MVC.
Das klassische Model-View-Controller Pattern geht auf Smalltalk 80 zurück und kom-
muniziert wie in Abbildung 1.24 dargestellt. Controller und View haben in dieser
Version keine Abhängigkeiten untereinander. Sie kommunizieren indirekt, indem sie
auf Änderungen im Model reagieren. Beide realisieren das Observer Pattern.
Im Vergleich mit dem erstgenannten Pattern „Forms und Controls“ ist hervorzuhe-
ben, dass das ursprüngliche MVC mit objektorientierten Modellen arbeitet. Hierbei
wird als Modell-Baustein von einem objektorientierten Domain Model ausgegangen.
Controller
View
Model
«use»
«use»
Abbildung 1.24 Model View Controller – klassisch
In Abbildung 1.25 ist die Kommunikation im klassischen MVC unter Smalltalk darge-
stellt. Man beachte die indirekten Callbacks. Diese sind an der Übergabe der Aspekte
der GUI-Felder erkennnbar (#actual, #calculated) .
Viele in der Praxis eingesetzte Frameworks arbeiten jedoch wie in Abbildung 1.26.
Wie man unschwer erkennen kann, gibt es hier wesentlich mehr Abhängigkeiten der
Bausteine untereinander. Der Vorteil gegenüber der klassischen Version liegt in einer
einfacheren Umsetzung, da Bausteine direkt kommunizieren können und aufwendi-
ge Observer-Implementierungen und CallBack-Mechanismen entfallen. Dies liegt da-
ran, dass zumindest bei klassischer Programmierung (ohne AOP) Entkopplungen von
1.4 Presentation Layer
25
«Controller of InputField»actual :TextInputField
user
:Reading «View of InputField»actual :TextInputField
«View of InputField»calculated :TextInputField
change data
perform(#actual, 50)
update
perform(#actual)
update
perform(#calculated)
perform(#calculatedColor)
update
Abbildung 1.25 MVC Aufruf-Sequenz
Controller
Model
View
«change»
«inform change»
«use»
Abbildung 1.26 Model View Controller in der Praxis
Bausteinen zu einem Mehraufwand in der Implementierung führen. Auch mit AOP-
Mechanismen sind solche Konzepte oftmals unübersichtlich. Direkte Kommunikati-
on ist im Allgemeinen einfacher zu verstehen und zu programmieren. Deshalb ist es
wichtig, in solchen Situationen Frameworks zur Verfügung zu haben, welche die
Komplexität kapseln.
In Abbildung 1.27 auf der nächsten Seite ist eine konkrete Umsetzung in Java Swing
dargestellt.
Das entscheidende Konzept bei MVC war ein Design, das Fowler als „Separated Pre-
sentation“ bezeichnet. Dahinter verbirgt sich eine stringente Trennung von Domä-
nen-Objekten und Präsentationsobjekten mit Darstellungslogik. Domänen-Objekte
sollten keinerlei Abhängigkeiten zu Präsentationsobjekten aufweisen, sodass sie in
unterschiedlichen Präsentationsobjekten wiederverwendet werden können (z.B. Da-
ten einmal als Tabelle und einmal als Balkengrafik dargestellt).
1 Grundlegende Architekturkonzepte
26
JCheckBox
Change-Listener
ToggleButtonModel
inform
Rendering
Event-Handling
inform
CheckBoxUI
Abbildung 1.27 Swing JCheckBox
Diese Aufgabe des Controllers besteht darin, die Benutzereingaben entgegenzuneh-
men und über die anschließend auszuführenden Aktionen zu entscheiden.
Es ist wichtig zu verstehen, dass es nicht nur eine View und einen Controller gibt,
sondern diese mehrfach paarweise auftreten. Jedes GUI-Element besteht aus View
und Controller, welche auf einem gemeinsamen Model basieren.
1.4.3 Model View Presenter (MVP)
Bei Model View Presenter handelt es sich um ein Design, das zum ersten Mal bei
IBM 1990 erschien. Dieses Design-Konzept versucht, das Beste aus den beiden zu-
vor genannten Patterns (Forms und Controls, MVC) miteinander zu kombinieren.
Forms und Controls ist ein leicht zu verstehendes Design, welches eine gute Tren-
nung zwischen wiederverwendbaren GUI-Komponenten und der Applikationslogik
erlaubt. Allerdings fehlt ein Separated Presentation-Konzept. Dieses Design ist vor-
teilhaft für Client/Server-Anwendungen mit relationalem Daten-Handling.
Demgegenüber hat MVC ein ausgereiftes Separated Presentation-Konzept und war
von Beginn an für objektorientierte Domänen-Modelle konzipiert.
Model View Presenter versucht nun, für objektorientierte Umgebungen die Stärken
der beiden Patterns zu kombinieren.
Model View Presenter separiert nicht mehr View und Controller als distinkte, unab-
hängige Bausteine. Eine View in MVP definiert die Struktur der GUI-Komponenten.
Sie enthält keine Logik, wie auf User-Interaktionen zu reagieren ist. Dies ist Aufgabe
des Presenters. Ein wichtiges Konzept ist hierbei, dass jede Kommunikation (Upda-
tes) des Presenters mit dem Model über grobgranulare Commands realisiert wird,
was auch eine gute Basis für die Realisierung von Undo/Redo darstellt.
View(Anzeigecode)
Presenter(Präsentationslogik)
Model(Fachliche Daten)
liest / mutiert kennt
TextFeld, Button, etc. Abbildung 1.28 Model View Presenter
1.4 Presentation Layer
27
actual:TextInputField
User
:Presenter :Reading
alt color choosing
[category == bad]
[category == good]
[category == excellent]
:TextField
user changes value
actual.value changed
getValue
setActualValue
value changed
getCalculatedValue
getCalculationCategory
setTextColor(RED)
setTextColor(YELLOW)
setTextColor(GREEN)
Abbildung 1.29 Model View Presenter – Ablauf
Abbildung 1.29 veranschaulicht die typische Kommunikation dieses Patterns.
Der Presenter-Baustein realisiert das „Supervising Controller“-Pattern. Die einzelnen
GUI-Widgets delegieren User-Events an diesen. Der Presenter (Supervising Control-
ler) koordiniert Änderungen am Domain Model.
1.4.4 Presentation Model (auch Application Model)
Presentation Model
Das Presentation Model repräsentiert den Zustand und das Verhalten des GUIs
unabhängig von den verwendeten Controls.
Mit diesem Konzept kann eine weitere Flexibilität ins Design eingeführt werden.
Zwischen Präsentations-Bausteinen und Domänen-Modell wird ein weiterer Baustein
eingeführt. Dieser kapselt das „Presentation Model“. Die Idee dahinter ist die ge-
meinsame Vorhaltung von Präsentations-Status und -Verhalten unabhängig von den
eigentlichen GUI-Bausteinen im Präsentationslayer. D.h. hier werden Daten der Be-
nutzersteuerung zusammen mit Nutzdaten und dafür notwendige Methoden vor-
gehalten. Der wichtigste Vorteil dieses Patterns gegenüber anderen GUI-Pattern ist,
1 Grundlegende Architekturkonzepte
28
dass das GUI auf diese Weise unabhängig von den Controls getestet werden kann.
Da Test-Tools, welche die Benutzeroberfläche ansteuern, oft umständlich in der
Handhabung sind, wird so der automatisierte Test erheblich erleichtert.
Abbildung 1.30 veranschaulicht das Konzept. Das „Presentation Model“ vermittelt
zwischen View und Model und hält zusätzliche, der Darstellung auf dem GUI die-
nende Informationen vor.
Book Title
- formTitle: String- ti tle: String
«presentation model»Book
-/ formTitle: String = "BookTitle: " +...- ti tle: String
«domain mo...Book
- ti tle: String
title = model.getTitle()formTitle = model.getFormTitle()
+model 1
1
Abbildung 1.30 Presentation Model – Klassen
Das allgemeine Konzept lässt sich wie in Abbildung 1.31 darstellen.
View Controller
Presentation Modell
Domain Modell
«inform change»
«inform change»
Abbildung 1.31 Presentation Model – Konzept
In Java wird es zum Beispiel von JGoodies wie in Abbildung 1.32 umgesetzt.
1.4 Presentation Layer
29
View Controller
«presentation model»JComponent
SwingModel
«inform change»
«inform change»
Abbildung 1.32 Presentation Model in JGoodies
1.4.5 Page Controller
Page Controller
Der Page Controller nimmt den HTTP-Request für eine bestimmte Web-Seite
oder HTTP-Form-Aktion entgegen und steuert die Response.
Dieses Pattern wird in der reinen Form von Technologien verwendet, die relativ viel
Infrastruktur-Code generieren (z.B. ASP und JSP). Bewusst explizit einsetzen sollte
man dieses Pattern eher nicht, weil damit die Gefahr wächst, dass Code dupliziert
wird oder Sicherheitslücken eingebaut werden. Wenn möglich, sollte dem Front
Controller (siehe nächster Abschnitt 1.4.6) oder für komplexere Applikationen einem
der Patterns MVC, MVP, PM der Vorzug gegeben werden.
PageController 1
Function A
PageController 2
Function A
Function B Function B
View 1 View 2
PageController 1
Function A
PageController 2
Function A
Function B Function B
View 1 View 2
Abbildung 1.33 Page Controller pro Web-Seite
1 Grundlegende Architekturkonzepte
30
1.4.6 Front Controller
Front Controller
Der Front Controller nimmt den HTTP-Request für alle Web-Seiten einer Applikation
entgegen und steuert die Response.
Ein Problem bei komplexeren GUIs ist, dass oft die gleiche Funktionalität von allen/
vielen Views (Formularen, Web-Pages, …) umgesetzt werden muss. Beispiele hierfür
sind typischerweise Security, Validierung, Logging, Konvertierungen und Internatio-
nalisierung. Hierdurch kommt es zu redundanten Implementierungen.
Sinn eines Front Controllers ist es, diese potenziell redundanten Funktionalitäten
durch Einführung einer Zwischenschicht an einem Ort zu konzentrieren.
View 1
Function A
View 2
Function B
FrontController
View 1
Function A
View 2
Function B
FrontController
Abbildung 1.34 Front Controller
Der Front Controller nimmt die Anfragen der Views entgegen und leitet sie an die
eigentliche Implementierung weiter. Der Front Controller kann die Weiterverarbei-
tung an Page Controller delegieren.
1.5 Domain Driven Design
Domain Driven Design ist ein Kommunikationsmittel! Die Grundidee basiert auf
klassischem OO-Design und versucht, die Sprache der jeweiligen Fachdomäne ob-
jektorientiert abzubilden, um den Bruch zwischen fachlicher und technischer Be-
schreibung/Umsetzung möglichst gering zu halten.
Eine Minimierung dieses Bruchs bedeutet:
dass die Kommunikation zwischen Domain-Experten und Entwicklern wesentlich
vereinfacht wird;
dass die Anforderungen an die Software besser spezifiziert werden können;
dass die Software für nachfolgende Entwicklergenerationen verständlicher und
deshalb auch wartbarer ist.
1.5 Domain Driven Design
31
Weitere Vorteile des Domain Driven Designs:
dass die Geschäftslogik unabhängig vom Rest des Systems getestet werden kann;
dass sich die Geschäftslogik in verschiedenen Kontexten (Anwendungen) verwen-
den lässt.
Für das Domain Driven Design ist die Erstellung einer gemeinsamen Sprachbasis von
Fachabteilung und IT notwendig. Evans (Evans, 2004) nennt diese die „Ubiquitous
Language“, die universelle, allgegenwärtige Sprache. Deren Begriffe können in der
Analyse-Phase in einem Glossar gepflegt werden.
Die Umsetzung ins Software Design kann jedoch in unterschiedlicher Ausprägung
erfolgen. Je nach Anforderungen wird das Design eher prozedural oder objektorien-
tiert ausfallen. So repräsentieren die beiden in Abschnitt 1.2.1 und 1.2.2 bereits vor-
gestellten Patterns je eine dieser beiden Ausprägungen:
Transaction Script (prozedural)
Rich Domain Model (objektorientiert)
In seinem Buch „Domain-Driven Design“ [Evans, 2004] beschreibt Evans die in Ab-
bildung 1.35 dargestellten wesentlichen Bausteine als „Pattern Language“.
Model-DrivenDesign
Services
Entities
Repositories
Aggregates
Value Objects
FactoriesLayeredArchitecture
besc
hrei
beM
odel
lmit
beschreibe Modell mit
beschreibe Modell mit
suche mit suche mit
Wurzel von
verwalte und validiere mit
erzeuge miterzeuge mit
erzeuge mit
gekapselt in
isol
iere
die
Dom
äne
Model-DrivenDesign
Services
Entities
Repositories
Aggregates
Value Objects
FactoriesLayeredArchitecture
besc
hrei
beM
odel
lmit
beschreibe Modell mit
beschreibe Modell mit
suche mit suche mit
Wurzel von
verwalte und validiere mit
erzeuge miterzeuge mit
erzeuge mit
gekapselt in
isol
iere
die
Dom
äne
Abbildung 1.35 Navigationskarte der Bausteine für Domain Driven Design (Evans, 2004)
Diese Bausteine oder Patterns werden im Folgenden im Kontext ihres Ziels näher be-
schrieben.
1 Grundlegende Architekturkonzepte
32
1.5.1 Isoliere die Domäne
Die eigentlichen Geschäftsprozesse und die Geschäftslogik stellen in Softwaresyste-
men oft nur einen kleinen Ausschnitt des Gesamten dar. Große Teile des Codes be-
handeln die technische Infrastruktur und stellen Hilfsfunktionalität zur Verfügung,
enthalten jedoch keinerlei Geschäftslogik.
Kommen neue Entwickler hinzu oder muss das System erweitert werden, besteht das
Problem, die eigentliche Geschäftslogik enthaltenden Codeteile aus dem Ganzen
herauszusuchen.
Weil die Geschäftslogik-Module so schlecht vom Infrastruktur-Code isoliert sind, sind
auch entsprechende Unit-Tests nur schwer durchzuführen, was der Gesamt-Software-
qualität nicht gerade zuträglich ist.
Aus diesen Gründen ist die primäre Forderung des Domain Driven Design die Isolie-
rung der Geschäftslogik und der diese kapselnden Objekte von den Modellteilen, die
unterstützende technische Funktion haben.
Layered Architecture
Die Gesamtarchitektur gliedert sich in unterschiedliche Layer mit unterschiedlichem
Verantwortungsbereich. Je nach Applikation oder Gesamtsystem können weitere
Layer (im Vergleich zur Abbildung 1.36) hinzukommen.
Es ist wichtig, zwischen logischen Layern und physikalischen Tiers zu differenzieren.
Je nach technologischer Zielplattform, Wartungskriterien etc. können sich logische Lay-
User-Interface
Application
Domain
Infrastructure
User-Interface
Application
Domain
Infrastructure
Abbildung 1.36 Konzept einer Layered Architecture [Evans 2004]
1.5 Domain Driven Design
33
er auf dem gleichen physikalischen Tier befinden oder über physikalische Tiers hin-
weg verteilt sein. Erst ein konsequentes Design mittels Layering ermöglicht ein wart-
bares, verteiltes Deployment und den Betrieb von verteilten Systemen.
Innerhalb der einzelnen Layer können die Module einer starken Kohäsion unterlie-
gen. Zwischen einzelnen Layern wird eine weitestgehende Entkopplung angestrebt.
Es gilt, dass nur übergeordnete Layer von den darunter liegenden abhängig sein dür-
fen, also Referenzen zu dortigen Objekten enthalten dürfen, und nicht umgekehrt. Es
ist elementar, ein Layering zu finden, das die wichtigsten kohäsiven Designaspekte
voneinander isoliert und somit zu einer Entkopplung der darin enthaltenen Module
führt.
Es ergibt sich das Prinzip der Layered Architecture (Abbildung 1.36), egal, wie viele
Layer im speziellen Fall in Betracht zu ziehen sind.
Zentrales Prinzip der Layered Architecture
Jedes Element in einem Layer ist nur von Elementen desselben Layers oder eines
darunter liegenden Layers abhängig!
Eine Kommunikation mit darüber liegenden Schichten muss über eine Indirektion
erfolgen, um Abhängigkeiten zu vermeiden. Man tut also gut daran, gegen Interfaces
und nicht gegen konkrete Klassen zu implementieren.
Die vier in Abbildung 1.36 dargestellten Layer werden nach allgemeiner Ansicht ver-
schiedener Autoren als Basis angesehen. Obwohl verschiedene Variationen für unter-
schiedliche Anforderungsbereiche beschrieben werden, gilt, dass die Isolierung des
Domain Layers von den anderen Layern der entscheidende Faktor ist, der ein Do-
main Driven Design erst ermöglicht.
User Interface
(Presentation Layer)
Informationsanzeige für den Benutzer, Interpretation der Benutzerkommandos
Application Layer Schlanker Layer ohne Geschäftslogik.
Beschreibt bzw. koordiniert die Geschäftsprozesse und delegiert die eigentliche
Arbeit an Kollaborationen von Domänen-Objekten im darunter liegenden Layer.
Domain Layer
(Model Layer)
Repräsentiert die Konzepte der jeweiligen Problemdomäne.
Der aktuelle Zustand der Objekte der Problemdomäne wird hier verwaltet und
genutzt. Die Speicherung wird an die Infrastruktur delegiert.
Evans: „The Domain Layer is Where the Model Lives.“
Infrastructure Layer Stellt allgemeine, technische Services zur Unterstützung der darüber liegenden
Layer zur Verfügung: z.B.
– Messaging für den Application Layer
– Persistence für den Domain Layer
– Zeichnen von GUI-Controls für das User-Interface, z.B. Charts generieren
– Erstellung von Dateien zur Anzeige auf der Benutzeroberfläche,
z.B. PDFs, Charts, GIFs usw.
Dieser Layer kann auch Interaktionsmöglichkeiten der anderen Layer unter-
einander durch ein Architektur-Framework zur Verfügung stellen.
1 Grundlegende Architekturkonzepte
34
Bei klassischen Oracle-Applikationen mit PL/SQL werden die Layer vermischt. Auch
in solchen Fällen kann ein Refactoring zur Trennung der logischen Layer und somit
zu einer besseren Wartbarkeit führen.
1.5.2 Beschreibe das Modell durch Software
Primär beschreiben drei Patterns das Modell:
Entities
Value Objects
Services
Um Objekte den richtigen Patterns zuzuordnen, können nach Evans (Evans, 2004)
folgende Fragen dienen:
Repräsentiert das Objekt ein Ding mit einer eigenen Identität? Entity Eine eigene Identität bedeutet, dass das Objekt als einzelnes Individuum existie-
ren kann. Entity Ein Objekt ohne eigene Identität existiert immer nur im Kontext eines anderen
Objektes mit eigener Identität. Value Object Eine Identität ermöglicht die Suche nach einem Objekt in der Menge aller mögli-
chen Objekte.
Repräsentiert das Objekt ein Ding, welches einem Lebenszyklus unterworfen ist
und dabei unterschiedliche Status einnimmt? Entity, Service Repräsentiert das Objekt ein Ding, das evtl. in verschiedenen Implementierungen
oder Applikationen vorkommt? Entity, Service Repräsentiert das Objekt ein Attribut, das den Status von etwas anderem be-
schreibt und keine eigene Identität benötigt? Value Object Repräsentiert das Objekt einen dynamischen Aspekt der Problemdomäne, der ei-
ner Aktion oder einem Ablauf entspricht? Service Objekte mit eigener Identität werden durch Entities repräsentiert. Objekte, die über
keine eigene Identität verfügen und den Status anderer Objekte beschreiben, werden
durch Value Objects repräsentiert. Value Objects sind mit Strukturtypen oder Re-
cords vergleichbar.
Objekte, die dynamische Domänenaspekte beschreiben, werden durch Services re-
präsentiert. Services führen die Funktionalität auf Anforderung des Clients aus. Die
eigentliche Service-Funktionalität delegiert hierzu an die Funktionalität, die durch
Entities bereitgestellt wird. Service-Funktionalität beschreibt einen verbindenden Ab-
lauf, der die Entity-Funktionalität in definierter Art kombiniert und so einen Ge-
schäftsprozessschritt beschreibt.
1.5 Domain Driven Design
35
1.5.2.1 Entity (auch Reference Object)
Entities (Evans, 2004) oder Referenz-Objekte (Fowler, 2003) sind Konzepte innerhalb
der Anwendungsdomäne, die über eine definierte, innerhalb der Anwendungsdomä-
ne nicht veränderbare Identität verfügen. Zwei Entities sind gleich, wenn ihr Schlüs-
sel (Object-ID) identisch ist. Außerdem verfügen Entities über einen Lebenszyklus,
der durch ein Zustandsmodell präzise beschrieben werden kann. Entitätstypen sind
in den meisten Fällen persistent und werden in Datenbanken gespeichert.
Entities repräsentieren oft die Kernobjekte in einem Geschäftsbereich. So ist z.B. für
viele Bereiche das Konzept „Person“ essenziell und hat eine eindeutige Identität in
Form einer (wie auch immer gearteten) Personen-Kennnummer.
Anmerkung
Datenbankseitig wird die Eindeutigkeit eines Objektes durch einen Primary Key aus-
gedrückt. Dieser kann „selbsterklärend“ sein, sich durch geschäftsrelevante Attribute
oder aber durch Surrogate Keys ausdrücken. Datenbankseitige und applikationsseitige
Identität müssen nicht identisch sein. Das daraus resultierende Mapping ist eine typische
Herausforderung für Persistenzmechanismen und wird oftmals mit dem Pattern Identity
Map (Fowler, 2003) gelöst.
Siedersleben (Siedersleben, 2004) weist berechtigterweise darauf hin, dass in den
beiden amerikanischen Publikationen (Fowler, 2003) und (Evans, 2004) eine Unter-
scheidung zwischen Typ und einzelnem Objekt fehlt. Er empfiehlt, die Begriffe „Enti-
tät“ und „Entitätstyp“ zu verwenden.
«Entität»Person
«identifier»- id: Long
«Property»- firstName: String- lastName: String- zipCode: String- city: String- street: String
Abbildung 1.37 Ein Entitätstyp (Siedersleben, 2004)
Für das Konstrukt Value Object (siehe folgenden Abschnitt 1.5.2.2) schlägt er aus
dem gleichen Grund die Begriffe „Datentypobjekt“ und „Datentyp“ vor.
1.5.2.2 Value Object
Value Objects beschreiben den Status oder die Charakteristik eines anderen Objek-
tes. Sie verfügen über keine eigene Identität. Zwei Value-Objekte sind gleich, wenn
es eine feldweise Übereinstimmung zwischen ihnen gibt. Value-Objekte können
durch andere Value-Objekte zusammengesetzt sein, enthalten aber niemals Referen-
zen auf Entitäten.
1 Grundlegende Architekturkonzepte
36
Siedersleben unterscheidet vier wichtige Gruppen von Value-Objekten aus der Sicht
der Anwendung:
Klassiker – String, Datum, Währung, Intervall (kommen in fast jedem IT-System vor)
Minigrammatiken – URLs, Prüfziffertypen (also Zeichenketten, die speziellen Re-
geln folgen)
Aufzählungstypen – Farbe (z.B. Pantone-Farbpalette), Rating, Versicherungstarife,
Flughafencode etc.
Zusammengesetzte Datentypen – Adresse
Ein häufig angeführtes Beispiel für ein Value-Objekt ist die Adresse. In unserem Bei-
spiel soll die Entität „Person“ eine assoziierte Value-Objekt-Adresse haben. Das UML-
Diagramm in Abbildung 1.38 soll dies veranschaulichen.
«Entitätstyp»Person
«Identity»- Id: long
«Property»- fi rstName: String- lastName: String
«Datentyp»Address
«Property»- city: String- zip: String- street: String
+address
Abbildung 1.38 Entitätstyp und assoziierter Datentyp (Entity und assoziiertes Value-Objekt)
UML erlaubt, Standardmodellelemente mit zusätzlichen Metainformationen in Form
von Stereotypen zu versehen. Diese können im Modell genutzt werden, um Modell-
elemente z.B. als Entity oder Value Object zu kennzeichnen.
Im relationalen Modell würde man diese Struktur normalisieren und erhielte zwei
Datenbank-Entitäten: Person und Adresse. Die Assoziation zwischen beiden wird
über Foreign-Keys ermöglicht. Im relationalen Modell verfügt dann auch die Adress-
Datenbank-Entität über eine Identität in Form eines Primary Keys (genau wie Person).
Eine Art Value-Objekt ließe sich hier auch durch ein Nested Array darstellen.
Das gleiche Konzept kann auch auf der objektorientierten Ebene angewendet wer-
den.
Hier wird zum Ausdruck gebracht, dass ein Adress-Objekt nur im Kontext eines Per-
sonen-Objektes genutzt wird und deshalb keine eigene Identität in diesem Modell
benötigt. Dies bedeutet im Umkehrschluss, dass es für das Personenobjekt egal ist,
welche spezielle Instanz eines Adressobjektes verwendet wird. Wichtig ist allein der
Status des Adressobjekts, d.h. die Werte seiner Attribute.
Es ist zu beachten, dass dies in einem anderen Modell durchaus anders sein kann
und dort eine Adress-Identität notwendig ist. Siedersleben weist darauf hin, dass es
sich bei Adressen um einen bekannten Grenzfall handelt. In fast jedem System ist die
Adresse ein Datentyp und kein Entitätstyp. In einigen Verwaltungsapplikationen, z.B.
für Katasterämter, steht jedoch die Adresse als Entität im Mittelpunkt.
1.5 Domain Driven Design
37
In Java z.B. wird hingegen auch auf Value Objects per Referenz zugegriffen, d.h.,
mehrere Person-Objekte können das gleiche Address-Objekt referenzieren, ähnlich
wie im normalisierten Relationenmodell (s.o.).
Aus diesem Grund sollten Value-Objekte nicht änderbar (immutable) sein. Sehen wir
uns hierzu ein Beispiel an:
Zwei Personen haben die gleiche Adresse. Die Entity Person verfügt über eine Me-
thode setAddress(), die als Parameter ein Objekt vom Typ Address entgegen-
nimmt. Ändert man allerdings die Adresse in einem Personen-Objekt, erfolgt die Än-
derung automatisch auch bei allen anderen, das Address-Objekt referenzierenden
Personen-Objekten.
public class Address { private String zip, city, street; public Address(String zip, String city, String street) { this.zip = zip; this.city = city; this.street = street; } public void setStreet(String newStreet) { this.street = newStreet; } }
Eine Möglichkeit bei veränderbaren Objekten besteht darin, dass versehentlich der
Status anderer referenzierender Objekte geändert wird.
Urs :Person
lastName = WagnerfirstName = Urs
Marlis :Person
lastName = WagnerfirstName = Marl is
Home :Address
street = Utoquai 6city = Zürich
Abbildung 1.39 Zwei Personen-Objekte mit gemeinsam referenziertem Address-Objekt
Bei Immutable Value Objects wird dies durch das Design verhindert. Der Program-
mierer wird bei Änderung des Objektstatus gezwungen, ein neues Objekt zu erzeu-
gen. Somit kann auch kein anderes, abhängiges Objekt von der Änderung belangt
werden.
public class Address { private String zip, city, street; public Address(String zip, String city, String street) { this.zip = zip; this.city = city; this.street = street; } public Address changeStreet(String newStreet) { return new Address(this.zip, this.city, newStreet); } }
1 Grundlegende Architekturkonzepte
38
Urs :Person
lastName = Wagnerfi rstName = Urs
Marlis :Person
lastName = WagnerfirstName = Marl is
Home :Address
street = Utoquai 6ci ty = Zürich
NewHome :Address
street = Utoquai 6city = Zürich
Abbildung 1.40 Zwei Personen-Objekte mit eigenen Address-Objekten
1.5.2.3 Service
Manchmal ist es logischer, ein Verhalten (z.B. eine spezielle Prozesslogik) als eigen-
ständiges Konzept in einer Domain zu betrachten und nicht einem anderen Objekt
(Entity oder Value-Objekt) in der Domain zuzuweisen.
Solche Domänen-Objekte werden als Domain Services bezeichnet.
Services sind Operationen, die als Interfaces zur Verfügung gestellt werden und sepa-
rate Modellelemente ohne eigenen Zustand darstellen. Dies unterscheidet sie von
Entities und Value-Objekten, die über einen eigenen Zustand verfügen können und
deren Zustand durch die eigenen Operationen verändert werden kann.
Durch das Konzept der Zustandslosigkeit wird erreicht, dass jeder beliebige Client
ohne Rücksicht auf die individuelle Historie jede beliebige Instanz eines speziellen
Service nutzen kann.
Vom semantischen Standpunkt aus betrachtet, beschreiben Service-Operationen, was
sie für einen Client tun können, während Entity-Operationen intrinsisches Verhalten
(also für die Entität an sich) definieren.
Die Signaturen von Service-Operationen sollten Bestandteile der „Ubiquitous Langu-
age“ sein. Parameter und Resultate sind Domänen-Objekte.
Domänen Services sollten mit Bedacht designed werden und keinesfalls ein Verhal-
ten definieren, das eigentlich den Entity- oder Value-Objekten zuzuordnen ist.
Evans (Evans, 2004) gibt drei Charakteristika für gute Services an:
Die Funktionalität lässt sich durch ein Domänen-Objekt beschreiben, das sich
nicht als Entity- oder Value-Objekt ausdrücken lässt.
Das Interface lässt sich durch „Begriffe“ anderer Elemente des Domain Models
beschreiben.
Das Verhalten ist zustandslos (allerdings gibt es Ausnahmen).
Services können in allen logischen Architektur-Layern vorkommen. Im Infrastruktur
Layer ließe sich z.B. ein SendInfoService als Interface definieren, das den Zugriff auf
ein Mail-System kapselt.
1.5 Domain Driven Design
39
Die Trennung zwischen Infrastructure Services (im Infrastructure Layer) und Domain
Services (im Domain Layer) ist im Allgemeinen offensichtlich. Schwieriger ist es, die
Trennung zwischen Domain Services und Application Services zu treffen. Hierbei
können die folgenden Merkmale helfen (Evans, 2004):
Application Layer – verantwortlich für die Ordnung (Reihenfolge) in der Benach-
richtigung (Workflow, Aufruffolge). Stellt applikations- bzw. Use-Case-spezifische
DTOs zusammen und kommuniziert über diese mit dem User-Interface.
Domain Layer – verantwortlich für die Überwachung von Schwellenwerten (min,
max, Wertebereiche, Rules, …).
Der Application Service definiert also die konkreten Interaktionsmöglichkeiten und
stellt den Mittler zwischen Präsentationsschicht und Domain-Service(s) dar. Ein Ap-
plication Service realisiert in dieser Hinsicht das Façade-Pattern. Hier ist der richtige
Ort zur Definition von globalen Transaktionsklammern und zentralem Error-
Handling. Application Services sind spezifisch für eine bestimmte Anwendung und
kapseln dieses spezifische Verhalten. Ein Domain Service ist generisch und kann von
unterschiedlichen Anwendungen genutzt werden. Im Error-Handler wird entschie-
den, ob ein Fehler zu einer Kompensation führt (Compensation-Handler) oder eine an-
wendungsspezifische Exception ausgelöst wird. Zur Kompensationslogik gehört auch
die Möglichkeit eines Neuversuchs, z.B. nach einem Cluster-Failover-Ereignis.
User-Interface
Application
Domain
Infrastructure
ApplicationService
DomainService
InfrastructureService
User-Interface
Application
Domain
Infrastructure
ApplicationService
DomainService
InfrastructureService
Abbildung 1.41 Layer und Services
Die Behandlung von Exceptions und Fehlern wird in einem eigenen Baustein, dem
Service-ExceptionHandler, realisiert. Dieser ist für jeden Service spezifisch und wirkt
1 Grundlegende Architekturkonzepte
40
als Filter vor dem eigentlichen Service. Dieses Design bewirkt eine saubere Separa-
tion-Of-Concerns.
ApplicationService
Service_I
Contract
ServiceExceptionHandler
Service_I
CompensationRules
ExceptionHandlingRules
Abbildung 1.42 Application Service und Service-ExceptionHandler
1.5.2.4 Module (auch Package)
Modelle erzählen eine Geschichte, und die Module sind die einzelnen Kapitel der
Geschichte. Modulnamen sind Begriffe der „Ubiquitous Language“.
Es wird empfohlen, jeden Code, der zu einem konzeptionellen Objekt gehört, in ei-
nem eigenen Modul (oder Modulbaum) zu pflegen. Dieses Konzept steht jedoch oft
augenscheinlich orthogonal zur Modularisierung im Layer. So werden Codeteile ei-
nes konzeptionellen Objektes häufig in ihrem Layer gepflegt.
Diese Aufteilung erlaubt ein einfaches Verpacken aller zu einem Layer gehörenden
Artefakte in ein einzelnes physikalisches Modul (z.B. JAR-Datei). Bedenkt man, dass
sich Layer zur Laufzeit oftmals physikalisch auf getrennten Tiers wiederfinden, ist
dies ein nicht zu vernachlässigender Aspekt. Aus diesem Grund erscheint es ange-
bracht, eine Primär-Modularisierung nach den Applikationslayern vorzunehmen, in-
nerhalb von diesen aber jeweils die gleichen Modulnamen für ein und dasselbe kon-
zeptionelle Objekt zu verwenden:
Bei größeren Anwendungen kann es sinnvoll sein, für Subsysteme in einem Layer
nochmals eigene Artefakte (z.B. JAR-Dateien) zu definieren. Dadurch ergibt sich ein
„Grid“ mit horizontalen Layern und vertikalen Subsystemen. Ein Subsystem kann
durch die fachliche Gruppierung von Use Cases bestimmt werden.
1.5.2.5 Aggregate
Entitäten können andere Entitäten referenzieren und aggregieren. Sie können belie-
big komplexe Datentypen aggregieren. In solchen Objektbäumen existiert ein Wur-
zel-Objekt, über das die Kommunikation mit der Umgebung erfolgt. Der Zugriff von
„außen“ auf andere Objekte des Objektbaums muss vermieden und somit kontrol-
liert werden. Aus diesem Grund werden solche Objektbäume zu sog. Aggregaten zu-
sammengefasst. Diese sind vor allem logische Gebilde. Es kann sich (je nach Pro-
grammiersprache und deren Möglichkeiten) vom Design her jedoch als günstig erwei-
1.5 Domain Driven Design
41
PresentationLayer
ApplicationLayer
Service Layer
Application
Login
Login
Login
login.jsp
LoginAction.java
Login.java
conceptionell object <Login>
Abbildung 1.43 Module und Artefakte mit Layern als Primärmodell
sen, ein Aggregat als eigenständiges Konstrukt (Klasse) zu realisieren. Das UML-Ele-
ment Komponente lässt sich zur Beschreibung nutzen.
Aggregate definieren also klare Verantwortlichkeiten und Abgrenzungen. So wirkt
man Spaghetti-Design entgegen. Ein Aggregat definiert einen Cluster assoziierter Ob-
jekte, die als eine Einheit (im Sinne von Datenänderungen) behandelt werden sollen.
Aggregate können andere Aggregate umschließen.
«aggregate root»Car
Engine_IChassis_I
«aggregate root»chassis [1]
«Value Object»wheel [4]
«Value Object»tire [4]
«aggregate ro...engine [1]
:Mechanic
position
Abbildung 1.44 Geschachtelte Aggregate
Jedes Aggregat verfügt über eine von anderen Objekten/Komponenten (also von au-
ßerhalb des Aggregats) ansprechbare (referenzierbare) Wurzel und definiert eine Ag-
1 Grundlegende Architekturkonzepte
42
gregat-Grenze (Hüllkurve der aktuell zu referenzierenden Objekte). Die Grenze defi-
niert, welche Objekte in dem Kontext zum Aggregat gehören und welche nicht.
Die Wurzel ist ein separates Entity-Objekt, das in den Grenzen des Aggregats liegt.
Außerhalb des Aggregats lokalisierten Objekten ist es nur erlaubt, das Wurzel-Objekt
zu referenzieren, nicht aber weitere im Aggregat enthaltene Objekte. Das Wurzelob-
jekt fungiert also als Façade.
Die Objekte innerhalb eines Aggregats dürfen sich auch gegenseitig referenzieren.
Weitere Entitäten innerhalb eines Aggregats müssen nur innerhalb desselben eindeu-
tig sein (lokale Identität), da sie von außen nicht referenzierbar sind (und nur im Kon-
text eines Wurzelobjekts wirken).
Aggregate definieren den Scope, in dem Invarianten während der Lifecycle-Abschnit-
te zu behandeln sind.
Factories und Repositories operieren auf Aggregaten und kapseln die Lifecycle-Trans-
itionen des Objekts.
«root»Engine
«root»ChassisWheel
Position Tire*
4
4
Aggregate
Mechanic
2
3
1«root»
Car
Aggregate
4
Abbildung 1.45 Lokale und globale Identität und Objekt-Referenzen [Evans 2004]
1. Objekte außerhalb einer Aggregat-Grenze (hier Car) können die Aggregat-Wurzel
referenzieren oder eine Datenbank-Query mit der ID durchführen.
2. Objekte außerhalb einer Aggregat-Grenze (hier Car) können andere Objekte au-
ßerhalb der Aggregat-Grenze (hier Engine) referenzieren.
3. Objekte außerhalb einer Aggregat-Grenze (hier Car) dürfen keine Referenz auf
Objekte innerhalb der Aggregat-Grenze (hier z.B. Tire) vorhalten.
4. Außen liegende Objekte (hier Mechanic) können bei geschachtelten Aggregaten
nur auf die Root-Objekte (Car) des äußeren Aggregats zugreifen. Das äußere Root-
Objekt stellt Interfaces zum Zugriff auf die inneren Aggregate zur Verfügung.
1.5 Domain Driven Design
43
1.5.2.6 Factory
Komplexe Objekte und Objekt-Hierarchien (Aggregate) werden durch Factories neu
erstellt oder wiederhergestellt (aus Datenbankinformationen). Factories adressieren
also den Anfang eines Objekt-Lebenszyklus.
1.5.2.7 Repository
Ein Repository verwaltet ein Objekt von der Mitte bis Ende dessen Lifecycles. Es ist
verantwortlich für das Auffinden und Laden von persistenten Objekten und kapselt
die notwendigen Bausteine des Infrastructure Layers. Das Instanzieren der Objekte
delegiert ein Repository an eine Factory dieses Layers.
Repository implementiert das Registry Pattern (Fowler, 2003)
Anmerkung
Eigentlich gehören Factories und Repositories nicht zur Domäne. Sie stellen Hilfskonstruk-
te zur Verwaltung der eigentlichen Domänenobjekte dar und sind deshalb aus organisa-
torischen Gründen im Domänenlayer angesiedelt. Dieser Unterschied ist zu beachten!
1.5.2.8 Domain Component
Eine Domain Component ist ein Baustein, der eine bestimmte Business-Funktionalität
kapselt.
DomainService
Entity
ValueObject Repository
Factory BusinessRules
Configuration
Domain Component
Contract
Factory_I Repository_IBusiness_I
Service_I
Aggregate
DomainService
Entity
ValueObject Repository
Factory BusinessRules
Configuration
Domain Component
Contract
Factory_I Repository_IBusiness_I
Service_I
Aggregate
Abbildung 1.46 Domänen-Komponente als eigenständiges Artefakt
Eine Domänen-Komponente (Domain Component) kann unterschiedlich realisiert
werden. So lässt sich, wie in Abbildung 1.46 gezeigt, die Domänen-Komponente als
eigenes physikalisches Artefakt in Form einer selbstständigen Klasse realisieren, die
die entsprechenden Interfaces anbietet und alle Aufrufe an die Domänen-Bausteine
Entity, Value Object, Factory oder Repository delegiert. Hier dient die Domänen-Kom-
ponente als Delegator, der die eigentlichen Implementierungen kapselt. Diese Vari-
1 Grundlegende Architekturkonzepte
44
ante kann in größeren Umgebungen durch die zusätzliche Indirektion und explizite
Aggregation Vorteile in der Wartbarkeit und Konfigurierbarkeit bringen. Durch dieses
Design kann das Konstrukt „Domänen-Komponente“ von mehreren Domain Services
verwendet werden.
In Abbildung 1.47 erfolgt eine Aggregation direkt im Domain Service. Dadurch kann
das Konstrukt „Domänen-Komponente“ jedoch nicht von mehreren Domain Services
benutzt werden. Hier müssten die Services auf Services zugreifen.
Entity
ValueObject Repository
Factory BusinessRule
Configuration
Domain Component
DomainService
Service_I
Aggregate
Contract
Abbildung 1.47 Business-Komponente als Teil des Domain Service
Abbildung 1.48 zeigt alle besprochenen Komponenten in ihrem Gesamtzusammen-
hang.
User Interface
Application
Domain
Infrastructure
View
ApplicationService
ApplicationService
Remoting
DomainService
Aggregate
Entity ValueObject
Factory Repository
DTOFactory
Contract
Persistence
Domain Component
Client Tier
Middle Tier
Abbildung 1.48 Rich-Domain Modell-Architektur
1.5 Domain Driven Design
45
1.5.3 Organisation der Business-Logik
Nach heutigem Stand gibt es zwei weitläufig akzeptierte Methoden, die Geschäftslo-
gik zu organisieren: den prozeduralen und den objektorientierten Ansatz. Die mo-
derne Sicht erweitert den objektorientierten Ansatz noch zusätzlich um einen aspekt-
orientierten.
In Zukunft werden prozedurale und/oder objektorientierte Module vermehrt durch
Services gekapselt und in einem Service-orientierten Ansatz wieder verwendet.
1.5.3.1 Prozedurales Design
Oftmals ist ein objektorientierter Ansatz für die Business-Logik nicht nötig, insbeson-
dere auch dann, wenn die Business-Logik relativ einfach ist. Objektorientierung zeigt
ihre Stärken in der Beschreibung komplexer Zusammenhänge. Auch kann ein ob-
jektorientierter Ansatz unmöglich oder aufwändig sein, wenn z.B. kein Persistenz-
Framework zur Verfügung steht, das ein Mapping der Objekte auf die Datenbank-Ta-
bellen erlaubt.
In diesen Fällen eignet sich ein prozeduraler Ansatz eher. Eine prozedurale Möglich-
keit bezeichnet Fowler in seinem Standardwerk (Fowler, 2003) als Transaction Script
Pattern.
Transaction Script
Organisiert die Business-Logik mittels Prozeduren; jede Prozedur behandelt eine
einzelne Anfrage der Präsentations-Logik.
Diese Art des Designs der Geschäfts-Logik zentralisiert das Verhalten in den Service-
Klassen, die als einfache Objekte oder z.B. als EJB Session Beans realisiert werden
können und mit „unintelligenten“ Datenobjekten arbeiten, die kein oder kaum Ver-
halten aufweisen. Damit ist das Verhalten in einigen wenigen, relativ großen Klassen
enthalten, was die Schwierigkeit im Unterhalt und in der Wartung erhöht. Daher ist
dieser Ansatz nur für einfache Business-Logik geeignet.
Siehe auch Abschnitt 1.2.1.
Behavior
State/Data
Transaction Scripts
DataObjects
Behavior
State/Data
Transaction Scripts
DataObjects
Abbildung 1.49 Die Struktur des prozeduralen Entwurfs
1 Grundlegende Architekturkonzepte
46
Abbildung 1.49 zeigt die Struktur des prozeduralen Entwurfs: Große prozedurale
Klassen und viele kleine Datenobjekte (Row oder Table Gateways und keine Domain
Objects ohne Verhalten).
1.5.3.2 Objektorientiertes Design
Die Einfachheit des prozeduralen Ansatzes ist zwar verlockend, kann aber bei kom-
plexerer Business-Logik auch schnell zum Gegenteil führen: zu Logik, die sich nur
noch schlecht warten lässt.
Bei einem objektorientierten Design enthält die Business-Logik-Schicht ein Objekt-
modell – ein so genanntes Domain Model –, das ein Netzwerk von relativ kleinen
Klassen darstellt. Fowler (Fowler, 2003) spricht beim objektorientierten Ansatz für
die Entwicklung der Business-Logik vom Domain Model Pattern.
Rich Domain Model
Ein Objekt-Modell der Domäne, das sowohl Verhalten als auch Daten enthält.
Behavior
State/Data
Behavior
State/Data
Abbildung 1.50 Rich Domain Model – ein Objekt-Modell der Domäne, das sowohl Verhalten wie auch
Daten kapselt
1.5.3.3 Wann welchen Ansatz verwenden?
Die Vorteile des prozeduralen Ansatzes (Transaction Script) bestehen in seiner Ein-
fachheit. Die Organisation der Logik eignet sich gut für Applikationen mit geringer
Komplexität und enthält nur geringen Overhead sowohl bei der Performance als
auch im Verständnis. Je komplexer die Business-Logik wird, umso schwerer ist aller-
dings der prozedurale Ansatz in den Griff zu bekommen. Insbesondere besteht die
Gefahr, dass Logik unter den einzelnen Transaktionen dupliziert wird, weil doch je-
de Transaktion für ihre Business-Logik selbst verantwortlich ist.
Der prozedurale Ansatz ist vor allem bei datenorientierten Applikationen von Vorteil,
wenn es im Wesentlichen darum geht, Daten, die in einer relationalen Datenbank
1.6 Zusammenfassung
47
gespeichert sind, zu pflegen, ohne dass dabei komplexe, tabellenübergreifende In-
tegritätsprüfungen notwendig sind.
Die Vorteile des objektorientierten Ansatzes mit Hilfe eines Domain Models kom-
men voll zum Tragen, wenn das zu entwickelnde System auch ein entsprechend
komplexes Verhalten beinhaltet. Genau zu bestimmen, ab wann ein Domänen-
Modell Sinn ergibt, ist schwierig. Ein wichtiger Faktor, der dabei ebenfalls eine Rolle
spielt, ist die Frage, wie vertraut ein Entwicklungsteam im Umgang mit Domänen-
Objekten ist. Wobei die Antwort auf diese Frage natürlich keinen Einfluss auf die in-
härente Komplexität der Applikation hat und nur bei Aufwandschätzungen und der-
gleichen interessant ist.
1.6 Zusammenfassung
In den vorangehenden Abschnitten haben wir gezeigt, welche wesentlichen Design-
und Architektur-Patterns für eine moderne Software-Architektur notwendig sind.
Die vorgestellten Konzepte sind Technologie-unabhängige „Best Practices“, die sich
in den letzten Jahren in der Praxis bewährt haben. Sie bringen die Ideen weltweit
bekannter OO-Koryphäen auf den Punkt.
Was den Architektur-Blueprint angeht, so lassen sich – grob gesehen – drei Vor-
schläge für unterschiedliche Szenarien erkennen. Sie unterscheiden sich primär in
der Umsetzung der Geschäftslogik, die mehr prozedural oder verstärkt objektorien-
tiert entworfen werden kann. Je nach Ausprägung des einen oder anderen manifes-
tiert sich dies in einem der folgenden Patterns:
Transaction Script
Table Module
Domain Model
In den folgenden Abschnitten fassen wir die wichtigsten Eigenschaften dieser drei
Grundpatterns nochmals zusammen.
1.6.1 Transaction Script
Organisiert und unterteilt die Geschäftslogik in einzelne Prozeduren so, dass jede
Prozedur eine einzelne Anfrage vom Präsentationslayer abdeckt.
Viele einfache Geschäftsapplikationen können als Serie von Einzeltransaktionen an-
gesehen werden. Dies gilt in hohem Maß für klassische Client/Server-Applikationen.
Jede Interaktion zwischen Client und Server enthält ein begrenztes Maß an (nicht all-
zu komplexer) Geschäftslogik. In den meisten Fällen handelt es sich hierbei um
simple Validierungen und Kalkulationen.
Transaction Script kapselt diese Logik pro Interaktion in einzelne Operationen und
kommuniziert direkt oder über einen schlanken Adapter mit einer relationalen Da-
1 Grundlegende Architekturkonzepte
48
tenbank. Jede Transaktion hat ihr eigenes Transaction Script. In vielen Fällen ent-
spricht ein Transaction Script einer Datenbank-Transaktion.
In Abbildung 1.51 realisiert der Applikations-Service das Transaction Script Pattern.
User Interface
Application
Domain
Infrastructure
View
ApplicationService
ApplicationService
remoting
DTOAssembler
Persistence
DAOFactory Validator
Client Tier
Middle Tier
Abbildung 1.51 Transaction Script Architecture
1.6.2 Domain Model
Ein Objektmodell der Problemdomäne, welches Verhalten und Daten umfasst.
Das Modell setzt sich aus einem Netzwerk feingranularer Klassen zusammen. Jede
einzelne dieser Klassen repräsentiert ein wichtiges Objekt der Geschäftsdomäne.
Ein OO Domain Model ist einem relationalen Datenbankmodell sehr ähnlich, doch
kapselt es nicht nur Daten, sondern auch das den Daten zugeordnete Verhalten und
wird in Teilen nicht normalisiert sein, d.h., auch Listen und Maps als Attribute sind
enthalten. Außerdem unterscheidet es sich durch den Einsatz von Vererbung.
Fowler (Fowler, 2003) diskutiert hierzu zwei Variationen des Domain Model Pat-
terns:
Das Simple Domain Model entspricht fast 1:1 dem Datenbankmodell, wobei jede
Tabelle durch einen Domänen-Entitätstypen repräsentiert wird. Bei diesem Design
kommt man oft mit Active Records aus.
Das Rich Domain Model unterscheidet sich erheblich vom Datenbankmodell, u.a.
durch Anwendung diverser OO-Konzepte und Design Patterns (Vererbung, Strategy
Pattern, Command Pattern etc.). Bei diesem Ansatz ist die Verwendung eines Data
Mappers unumgänglich: Active Record ist hier nicht mehr das angemessene Design.
Das Rich Domain Model ist das zentrale Konzept des Domain Driven Design.
1.6 Zusammenfassung
49
User Interface
Application
Domain
Infrastructure
View
ApplicationService
ApplicationService
Remoting
DomainService
Aggregate
Entity ValueObject
Factory Repository
DTOFactory
Contract
Persistence
Domain Component
Client Tier
Middle Tier
Abbildung 1.52 Domain Model-Architektur
1.6.3 Table Module
Eine einzelne Instanz (Singleton), welche die Geschäftslogik für alle Zeilen in einer
Datenbanktabelle oder View kapselt.
Ein Problem des Domain Models ist der so genannte Impedance Mismatch, die Ab-
bildungsproblematik zwischen objektorientiertem Domain Model und relationalem
Datenbankmodell.
Ein Table Module organisiert die Geschäftslogik in einer Klasse pro Datenbanktabelle
(oder View). Der primäre Unterschied zum Domain Model liegt hierbei in der Ob-
jekt-Identität und Objekt-Multiplizität.
Oft ist ein Table Module genau einer Tabelle zugeordnet und kapselt die Operatio-
nen auf diesen Daten.
1 Grundlegende Architekturkonzepte
50
User Interface
Application
Domain
Infrastructure
View
ApplicationService
ApplicationService
Remoting
DTOAssembler
Persistence
Table Module Validator
Client Tier
Middle Tier
Abbildung 1.53 Table Module-Architektur
1.6.4 Wann welches Pattern wählen?
Wie wir also gesehen haben, stehen drei Patterns für die grobe Organisation der Ge-
schäftslogik zur Verfügung. Welches Pattern soll nun aber für welche Aufgabe ge-
wählt werden?
Effort to enhance
Domain Model
Complexity of Domain Logic
Transaction Script
Table Module
Effort to enhance
Domain Model
Complexity of Domain Logic
Transaction Script
Table Module
Abbildung 1.54 Beziehung zwischen der Komplexität der Geschäftslogik und dem Aufwand für Erweite-
rungen der unterschiedlichen Patterns
Es ist keine einfache Wahl, und die Komplexität stellt das wesentliche Kriterium der
abzubildenden Geschäftslogik dar. Abbildung 1.54 zeigt, wie Martin Fowler die drei
1.6 Zusammenfassung
51
Patterns in seinem Buch (Fowler, 2003) gegenüberstellt. Die X-Achse zeigt die Zu-
nahme der Komplexität der Geschäftslogik und die Y-Achse die Zunahme des Auf-
wands für Anpassungen/Erweiterungen.
Bei einfacher Geschäftslogik ist das Domain Model weniger attraktiv, weil der Over-
head im Domain Driven Design wegen der Einfachheit der Domäne nicht gewinn-
bringend ist. Wenn die Komplexität der Geschäftslogik jedoch steigt, erreichen die
beiden anderen Ansätze früher oder später ihre Grenzen, wo der Aufwand für das
Hinzufügen von neuen Anforderungen plötzlich exponentiell ansteigt.
Das Problem für den Architekten und Entwickler besteht nun darin, genau festzustel-
len, wo auf der X-Achse die zu entwickelnde Applikation liegt. Es ist nicht bekannt,
wie man die Komplexität der Geschäftslogik messen kann. In der Praxis benötigt man
daher die Hilfe von erfahrenen Software-Entwicklern, die die initialen Analysen und
Anforderungen sichten und dann eine möglichst gute Wahl aufgrund ihrer Erfahrung
treffen.
Zudem gibt es Faktoren, die die Kurven geringfügig ändern können. Für ein Team
mit Erfahrung in Domain Driven Design werden die initialen Kosten des Domain
Model Patterns geringer sein. Je besser das Team sich mit OO-Modellierung aus-
kennt, desto sinnvoller ist es, den Domain Model-Ansatz zu wählen.
Die Attraktivität des Table Module ist insbesondere davon abhängig, wie gut die Un-
terstützung für eine allgemeine Record Set-Struktur in der entsprechenden Umge-
bung ausfällt. Eine Umgebung wie .NET und Visual Studio, wo es viele Hilfsmittel
rund um Record Set-ähnliche Komponenten gibt, macht den Einsatz vom Table Mo-
dule Pattern viel attraktiver. Falls jedoch keine Werkzeug-Unterstützung für Record
Set existiert, ist der Einsatz des Table Module wenig sinnvoll.
Auch wenn mal eine Entscheidung getroffen wurde, bedeutet dies noch nicht, dass
dieselbe in Stein gemeißelt ist. Es kann jedoch sehr schwierig und kostenintensiv
werden, sie später zu ändern. Deshalb ist es ratsam, im Voraus die entsprechenden
Überlegungen anzustellen und zu entscheiden, welcher Weg zu gehen ist. Die Wahl
der Organisation der Geschäftslogik ist ein Architektur-Entscheid, den es für das ge-
samte System oder allenfalls Subsystem zu treffen gilt.
Falls später festgestellt wird, dass die falsche Entscheidung getroffen wurde, stellt es
normalerweise kein Problem dar, von einem Transaction Script-Ansatz auf einen
Domain-Model-Ansatz zu wechseln. Der Wechsel von einem Domain Model zurück
zum Transaction Script wird hingegen schwieriger und wenig gewinnbringend sein,
es sei denn, der Data Source Layer ließe sich dadurch wesentlich vereinfachen.
Die drei Patterns dürfen und können auch kombiniert eingesetzt werden. Gelegent-
lich kann es sinnvoll sein, einen Teil der Geschäftslogik mit Transaction Script zu
implementieren, während der Rest mit einem Table Module oder Domain Model-
Ansatz umgesetzt wird. Dies erhöht allerdings die Gesamtkomplexität des Systems
bzw. der Architektur und sollte daher nicht unnötig forciert werden.
1 Grundlegende Architekturkonzepte
52
1.6.5 Fazit
Die heute verfügbaren modernen Frameworks für die Applikationsentwicklung kap-
seln viele in diesem Kapitel vorgestellten Patterns und Konzepte und sind eine her-
vorragende Basis für eine State-of-the-Art-Software-Architektur.
In den nächsten Kapiteln stellen wir ausgewählte Frameworks für unterschiedliche
Plattformen vor und zeigen, wie sie die in diesem Kapitel vorgestellten Konzepte un-
terstützen.