Thursday, October 18, 2007

Patterns 3 - Enterprise Application Architecture

Wie der Titel dem geneigten Leser andeutet möchte ich in diesem Beitrag das Standardwerk Patterns of Enterprise Application Architecture, kurz EAP, von Martin Fowler zitieren. Im Gegensatz zu den GoF-Patterns aus meinem ersten Beitrag zu Patterns sind die EAP-Patterns recht spezifisch mit einer Anwendung verbunden. Im folgenden werde ich eine Auswahl von Patterns aus dem Buch auflisten indem ich die Zusammenfassung aus dem Buch pro Pattern zitieren und wo es für mein Verständis wichtig war habe ich noch Kommentare hinzugefügt. Für Details sei an das Buch verwiesen. Nicht erwähnte Patterns sind nicht weniger wichtig, doch haben sie in meinem Umfeld weniger Bedeutung da die Problemstellung nicht vorhanden ist oder ich diese bis heute durch ein Framework lösen lies.

Domain Logic Patterns
Domain Model: 'An object model of the domain that incorporates both behavior and data.' Wegen Domain Driven Design ist dieses Pattern für mich ein Muss.

Service Layer: 'Defines an application's boundary with a layer of services that establishes a set of available operations and coordinates the application's response in each operation.' Für den Service Layer gibt es die Variation 'Domain Facade' und 'Operation Script'. Da ich den Domain Model-Ansatz bevorzuge habe ich hier auch eine Bevorzugung für die 'Domain Facade'. Die Eigenschaften eines einzelnen Service hat Evans auch hier beschrieben.

Data Source Architectural Patterns
Active Record: 'An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.' Dieses Pattern kann zu einer Vereinfachung in der Implementation eines Domain Model führen indem die Datenbankstruktur und die Domain Model-Stuktur gleich gehalten werden.

Data Mapper: 'A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.' Im Gegensatz zum Active Record wird das Mapping hier in den Data Mapper ausgelagert. Der Data Mapper wird in der Regel nicht selbst implementiert da dies ein komplexes Unterfangen ist (z.B kann für ein objekte-relationales Mapping NHibernate verwendet werden). Auch wird ein Data Mapper oft zusammen mit einem Domain Model verwendet. (siehe auch Mapper)

OR Behavioral Patterns
Unit of Work: 'Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.' Unit of Work sollte in der Regel zusammen mit einem Data Mapper implementiert werden.

Identity Map: 'Ensures that each object gets loaded only once by keeping every loaded object in a map. Looks up objects using the map when referring to them. ' Identity Map muss im Zusammenhang mit einem Data Mapper implementiert werden.

Lazy Load: 'An object that doesn't contain all of the data you need but knows how to get it.' Wichtiges Pattern in Zusammenhang mit Data Mapper und Domain Model um zu steuern wann welche Daten von einer Datenquelle geladen werden.

OR Metadata Mapping Patterns
Query Object: 'An object that represents a database query.' Das Specification Pattern ist mit Query Object verwandt. Der Unterschied ist dass das Query Object auf technischer Ebene ein Query beschreibt. Das Specification Pattern selbst kann Begriffe aus der ubiquitous Language verwenden und bilden und ist Teil der Geschäftslogik.

Repository: 'Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects'. Ich war hier immer unsicher was der Unterschied zwischen einem Repository und einer Factory ist. Aber in Domain Driven Design von Evans wird klar definiert: 'The Factory makes new objects; the Repository finds old objects' und in Applying Domain-Driven Design and Patterns wird dargestellt dass das Repository für die Persistierung von neu erzeugten Objekten zuständig ist. Ein Repository befindet sich auf einer höheren Ebene als ein Data Mapper indem es Query Object oder Specifications auswertet und Objekte mit Hilfe eines Data Mapper erzeugt.

Web Presentation Patterns
Model View Controller: 'Splits user interface interaction into three distinct roles. (View, Controller, Model).' Siehe auch MVP unter welche das Pattern weiter verfeinert dargstellt wird.
Page Controller: 'An object that handles a request for a specific page or action on a Web site'. Ich sehe im Page Controller eine Anpassung des Model View Controller an das Web-Umfeld wo es die View einmal auf dem Client als HTML-Seite und einmal auf dem Server als Server-Seite gibt. Dies ist auf jeden Fall der Grund weshalb im Unterschied zum Model View Controller die View keine Abhängigkeit auf den Page Controller hat. Die clientseitige HTML-Seite hat nämlich eine Abhängigkeit auf den Page-Controller indem diese Web-Requests übermittelt.

Front Controller: 'A controller that handles all requests for a Web site'. Der Controller instanziert abhängig vom Request Commandos welche die weiteren Verarbeitungen vornehmen.

Template View: 'Renders information into HTML by embedding markers in an HTML page.' Das ist wie eine ASP-Serverseite.

Application Controller: 'A centralized point for handling screen navigation and the flow of an application'.

Distribution Patterns
Remote Facade: 'Provides a coarse-grained facade on fine-grained objects to improve efficiency over a network.' Wichtig ist, als Unterschied zum Service Layer, dass die Remote Facade grob-strukturierte Methoden aufweist.

Data Transfer Object: 'An object that carries data between processes in order to reduce the number of method calls.' Kann zusammen mit Remote Facade zur Datenübertragung verwendet werden. In .NET werden so oft DataSet's oder XML-Serialisierte Objekte als DTO über Webservices verwendet.

Offline Concurrency Patterns
Optimisitc Offline Lock: 'Prevents conflicts between concurrent business transactions by detecting a conflict and rolling back the transaction.'

Pessimistic Offline Lock: 'Prevents conflicts between concurrent business transactions by allowing only one business transaction at a time to access data.'

Coarse-Grained Lock: 'Locks a set of related objects with a single lock'. Damit verwaltet ein Optimisitc Offline Lock oder ein Pessimistic Offline Lock die Locks auf höherer Ebene (z.B: Aggregate) um den Lockingaufwand zu verringern und die Konsistenzsicherheit zu erhöhen.

Implicit Lock: 'Allows framework or layer supertype code to acquire offline locks.' Stellt sicher dass das Locking implizit ist und somit vom Client-Code weder vergessen noch umgangen werden kann.

Session State Patterns
Client Session State: 'Stores session state on the client.' Wird z.B von ASP.NET-Seiten als ViewState implementiert. Kann aber auch für alle Arten von Sessions verwendet werden.

Server Session State: 'Keeps the session state on a server system in a serialized form'. Wird z.B von ASP.NET-Seiten auf dem System.Web.HttpContext.Session -Property implementiert.

Database Session State: 'Stores session data as committed data in the database.' Kann bei ASP.NET via Konfiguration für den Server Session State eingeschaltet werden.

Base Patterns
Gateway: 'An object that encapsulates access to an external system or resource.' Vereinfacht ein komplexes externes Inteface und stellt evtl. die Basis zur Verfügung um einen Service Stub anlegen zu können. Noch ein paar Erklärungen: Ein Gateway wird für externe Komponenten geschrieben während eine Facade von einer externen Komponente zur Verfügung gestellt wird. Ein Adapter wiederum ist eine technische Möglichkeit wie ein Gateway umgesetzt werden kann.
Mapper: 'An object that sets up a communication between two independent objects.' Ist komplexer zu implementieren als ein Gateway. Der Mapper kann als Zwischenschicht gesehen werden welche die zwei angrenzenden Schichten aufeinander abbildet. Beide angrenzenden Schichten bleiben dabei unabhängig und nur der Mapper hat eine Abhängigkeit auf diese.

Layer Supertype: 'A type that acts as the supertype for all types in its layer.' Mag ich persönlich nicht da dadurch schnell das Single Responsibility Prinzip verletzt wird. (z.B Domain Model hat Subertype für Persistenz).

Separated Interface: 'Defines an interface in a separate package from its implementation.' Die Konfiguration der konkreten Instanz (welche das Interface implementiert) kann danach von einem dritten, von beiden Packages abhängigen Komponente oder per Plugin zur Laufzeit erfolgen.

Registry: 'A well-known object that other objects can use to find common objects and services.'

Plugin: 'Links classes during configuration rather than compilation.' Dafür gibts heute eine Anzahl Frameworks (z.B Spring.NET). Plugin wird häufig auch im Zusammenhang mit dem Dependency Inversion Principle und Separated Interface verwendet.

Service Stub: 'Removes dependence upon problematic services during testing.'

Record Set: 'An in-memory representation of tabular data.' = DataSet in .NET

No comments: