Konzept: Design- und Implementierungsmechanismen
Ein Designmechanismus fügt dem konzeptionellen Analysemechanismus konkrete Details hinzu, braucht aber keine bestimmte Technologie.
Beziehungen
Hauptbeschreibung

Einführung in Design- und Implementierungsmechanismen

Ein Designmechanismus ist eine Präzisierung eines entsprechenden Analysemechanismus (siehe auch Konzept: Analysemechanismen). Ein Designmechanismus fügt dem konzeptionellen Analysemechanismus konkrete Details hinzu, braucht aber keine bestimmte Technologie, z. B. eine bestimmte Implementierung eines Anbieters eines objektorientiertes Datenbankmanagementsystems. Wie bei den Analysemechanismen kann ein Designmechanismus ein oder mehrere Muster instanzieren, in diesem Fall Architektur - oder Designmuster.

Ein Implementierungsmechanismus ist eine Konkretisierung eines entsprechenden Designmechanismus, der beispielsweise eine bestimmte Programmiersprache oder eine andere Implementierungstechnologie (z. B. ein Middleware-Produkt eines bestimmten Anbieters) verwendet. Ein Implementierungsmechanismus kann ein oder mehrere Idiome oder Implementierungsmuster instanzieren.

Beispiel: Merkmale von Designmechanismen

Schauen Sie sich den Analysemechanismus für Persistenz an:

  • Möglicherweise müssen viele (2.000) kleine Objekte (jeweils 200 Bytes) nur für ein paar Sekunden gespeichert werden.
  • Möglicherweise müssen mehrere sehr große Objekte für mehrere Monate permanent auf der Platte gespeichert werden, die nie aktualisiert werden, aber anspruchsvolle Abrufmethoden erfordern.

Diese Objekte erfordern unterschiedliche Persistenzunterstützung. Die folgenden Merkmale von Designmechanismen für Persistenzunterstützung können ermittelt werden:

  • Merkmale für Speicherung im Hauptspeicher:: für bis zu 1 Mb insgesamt (Größe x Volumen), sehr schneller Zugriff für Lesen, Schreiben, Aktualisieren
  • Merkmale für Flash-Karte: für bis zu 8 Mb, langsamer Zugriff beim Aktualisieren und Schreiben, mittelmäßiger Lesezugriff
  • Merkmale für Binärdatei: für 100 Kb bis 200 Mb, langsame Aktualisierung, langsamer Lese- und Schreibzugriff.
  • Merkmale für Datenbankmanagementsystem (DBMS): für 100 Kb und höher (praktisch keine Obergrenze), noch langsamerer Aktualisierungs-, Lese- und Schreibzugriff.

Diese Geschwindigkeiten sind nur im Vergleich mit der Speicherung im Hauptspeicher als 'langsam' zu bewerten. In manchen Umgebungen können die Zugriffszeiten natürlich durch die Verwendung von Caching verbessert werden.

Abbildung ist im Inhalt beschrieben.



Zuordnung zwischen Design- und Implementierungsmechanismen präzisieren

Zunächst ist die Zuordnung zwischen Designmechanismen und Implementierungsmechanismen wahrscheinlich suboptimal, reicht aber aus, um das Projekt in den Gang zu bringen, noch nicht bemerkte Risiken aufzudecken und weitere Untersuchungen und Auswertungen auszulösen. Mit Fortschreiten des Projekts und mit zunehmendem Wissen muss die Zuordnung präzisiert werden.

Gehen Sie bei der Präzisierung der Zuordnung von Design- und Implementierungsmechanismen iterativ vor und eliminieren Sie redundante Pfade, indem Sie sich von oben nach unten und von unten nach oben durch das Design arbeiten.

Design von oben nach unten durcharbeiten. Bei dieser Vorgehensweise, auch "Top-down" genannt, stellen neue und präzisierte Anwendungsfallrealisierungen durch die erforderlichen Analysemechanismen neue Anforderungen an die erforderlichen Designmechanismen. Solche neuen Anforderungen können zusätzliche Merkmale eines Designmechanismus aufdecken und möglicherweise eine Aufteilung zwischen Mechanismen erzwingen. Außerdem muss ein Kompromiss zwischen Systemkomplexität und Systemleistung gefunden werden:

  • Zu viele unterschiedliche Designmechanismen machen das System zu komplex.
  • Zu wenig Designmechanismen können bei manchen Implementierungsmechanismen, die bereits an ihre Grenzen gehen, Leistungsprobleme hervorrufen.

Design von unten nach oben durcharbeiten. Bei dieser Vorgehensweise, auch "Bottom-up" genannt, werden Sie bei der Untersuchung der verfügbaren Implementierungsmechanismen vielleicht Produkte finden, die mehrere Designmechanismen gleichzeitig befriedigen, aber eine gewisse Anpassung bzw. Neuaufteilung Ihrer Designmechanismen erfordern. Sie können die Anzahl der verwendeten Implementierungsmechanismen zwar verringern, aber wenn Sie zu wenig Implementierungsmechanismen haben, kann dies unter Umständen zu Leistungsproblemen führen.

Nachdem Sie sich entschieden haben, ein Datenbankmanagementsystem (DBMS) zum Speichern der Objekte der Klasse A zu verwenden, sind Sie möglicherweise versucht, alle Objekte im System in diesem DBMS zu speichern. Dies könnte sich als extrem ineffizient oder mühsam erweisen. Nicht alle Objekte, die Persistenz erfordern, müssen im DBMS gespeichert werden. Einige Objekte können persistent sein, werden aber möglicherweise häufig von der Anwendung und nur selten von anderen Anwendungen aufgerufen. In diesem Fall kann eine Hybridstrategie, in der das Objekt aus dem DBMS in den Hauptspeicher eingelesen und regelmäßig synchronisiert wird, die beste Lösung sein.

Beispiel

Ein Flug kann für schnelle Zugriffe im Hauptspeicher und für Langzeitpersistenz in einem DBMS gespeichert werden. Dies löst jedoch den Bedarf an einem Synchronisationsmechanismus aus.

Es ist nicht ungewöhnlich, einer Clientklasse mehrere Designmechanismen zuzuordnen, um unterschiedlichen Merkmalen gerecht zu werden.

Da Implementierungsmechanismen häufig als Pakete in Standardkomponenten (Betriebssysteme und Middleware-Produkte) bereitgestellt werden, müssen basierend auf Kosten, Impedanzabweichungen oder Stilvereinheitlichung gewisse Optimierungsarbeiten vorgenommen werden. Außerdem sind Mechanismen häufig voneinander abhängig, was eine klare Aufteilung von Services in Designmechanismen schwierig macht.

Beispiele

  • Der Benachrichtigungsmechanismus kann auf den Mechanismen für Interprozesskommunikation basieren.

  • Der Fehlerprotokollierungsmechanismus kann auf dem Persistenzmechanismus basieren.

Verbesserungen müssen die gesamte Ausarbeitungsphase hindurch vorgenommen werden und sind häufig ein Kompromiss zwischen:

  • einer exakten 'Entsprechung' mit den Anforderungen der Auftraggeber der Designmechanismen in Bezug auf die erwarteten Merkmale und
  • den Kosten und der Komplexität mit zu vielen Implementierungsmechanismen, die erworben und integriert werden müssen.

Das Gesamtziel ist immer, eine einfache, saubere Gruppe von Mechanismen zu haben, die einem großen System konzeptionelle Integrität, Einfachheit und Eleganz verleihen.

Beispiel: Designmechanismen zu Implementierungsmechanismen zuordnen

Die Designmechanismen für Persistenz können Implementierungsmechanismen wie folgt zugeordnet werden:

Abbildung ist im Inhalt beschrieben.

Eine mögliche Zuordnung zwischen Analysemechanismen und Designmechanismen. Der gepunktete Pfeil bedeutet "wird spezialisiert von" und impliziert, dass die Merkmale der Designmechanismen von den Analysemechanismen übernommen, aber spezialisiert und verbessert werden.

Nachdem Sie die Mechanismen optimiert haben, sind die folgenden Zuordnungen vorhanden:

Abbildung ist im Inhalt beschrieben.

Die Designentscheidungen für eine Clientklasse, dargestellt durch Zuordnung der Mechanismen: Eine Klasse Flug erfordert zwei Formen der Persistenz: Speicherung im Hauptspeicher, implementiert durch eine gebrauchsfertige Bibliotheksroutine, und Speicherung in einer Datenbank, implementiert durch ein Standardprodukt für Objektspeicherung.

Die Zuordnung muss in beide Richtungen navigierbar sein, so dass die Clientklassen leicht erkennbar sind, wenn die Implementierungsmechanismen geändert werden.

Designmechanismen beschreiben

Designmechanismen und Details zu ihrer Verwendung werden im Arbeitsergebnis Projektspezifische Richtlinien dokumentiert. Die Beziehung (oder Zuordnung) der Analysemechanismen zu Designmechanismen zu Implementierungsmechanismen und die zugehörige Begründung für diese Auswahl wird im Arbeitsergebnis Softwarearchitekturdokument dokumentiert.

Wie Analysemechanismen können Designmechanismen mit einer Kollaboration modelliert werden, die eine oder mehrere Architekturmuster oder Designmuster instanzieren kann.

Beispiel: Ein Persistenzmechanismus

Dieses Beispiel verwendet eine Instanz eines Musters für RDBMS-basierte Persistenz, entnommen aus JDBC™ (Java Data Base Connectivity). Wir präsentieren das Design hier zwar, aber JDBC stellt echten Code für einige der Klassen bereit, so dass es von unserer Präsentation bis hin zu einem Implementierungsmechanismus nur ein kleiner Schritt ist.

Die Abbildung "Statische Sicht: JDBC" zeigt die Klassen (d. h. eigentlich die Klassifikatorrollen) in der Kollaboration.

Abbildung ist im Inhalt beschrieben.

Statische Sicht: JDBC

Die gelb gefüllten Klassen sind die Klassen, die bereitgestellt wurden. Die anderen (meineDBKlasse etc.) wurden vom Designer gebunden, um den Mechanismus zu erstellen.

In JDBC arbeitet ein Client mit einer DBClass, um persistente Daten zu lesen und zu schreiben. Die DBClass ist für den Zugriff auf die JDBC-Datenbank unter Verwendung der Klasse DriverManager verantwortlich. Nachdem eine Datenbankverbindung geöffnet wurde, kann die DBClass SQL-Anweisungen erstellen, die an das zugrunde liegende RDBMS gesendet und mit der Klasse Statement ausgeführt werden. Die Klasse Statement "spricht" mit der Datenbank. Das Ergebnis der SQL-Abfrage wird in einem Objekt ResultSet zurückgegeben. 

Die Klasse DBClass ist dafür verantwortlich, eine andere Klasseninstanz persistent zu machen. Sie kennt die OO-RDBMS-Zuordnung und hat das Verhalten, um als Schnittstelle mit dem RDBMS aufzutreten. Die DBClass vereinfacht das Objekt, schreibt es in das RDBMS und liest die Objektdaten   aus dem RDBMS und erstellt das Objekt. Jede persistente Klasse erhält eine entsprechende DBClass. 

PersistentClassList wird verwendet, um eine Gruppe persistenter Objekte als Ergebnis einer Datenbankabfrage (z. B. DBClass.read()) zurückzugeben.

Im Folgenden präsentieren wir Ihnen eine Reihe dynamischer Sichten, um Ihnen zu zeigen, wie der Mechanismus funktioniert.

Abbildung ist im Inhalt beschrieben.

JDBC: Initialize

Die Initialisierung muss stattfinden, damit auf persistente Klassen zugegriffen werden kann.

Zum Initialisieren der Verbindung zur Datenbank muss die DBClass den entsprechenden Treiber laden, indem sie die Operation DriverManager getConnection() mit einem URL, Benutzer und Kennwort aufruft.

Die Operation getConnection() versucht, eine Verbindung zum angegebenen Datenbank-URL herzustellen. Der DriverManager versucht, einen entsprechenden Treiber aus einer Gruppe registrierter JDBC-Treiber auszuwählen.

Parameter:

url: Ein Datenbank-URL mit dem Format jdbc:Unterprotokoll:Untername. Dieser URL wird verwendet, um den eigentlichen Datenbankserver zu suchen und ist in dieser Instanz nicht webbezogen.

user: Der Datenbankbenutzer, für den die Verbindung hergestellt wird.

pass: das Kennwort des Benutzers.

Rückgabewerte:

Eine Verbindung zum URL.

Abbildung ist im Inhalt beschrieben.

JDBC: Create

Zum Erstellen einer neuen Klasse fordert der Persistenzclient die DBClass auf, die neue Klasse zu erstellen. Die DBClass erstellt eine neue Instanz von PersistentClass mit Standardwerten. Anschließend erstellt die DBClass eine neue Anweisung (Statement) mit der Operation createStatement() der Klasse Connection. Die Anweisung wird ausgeführt, und die Daten werden in die Datenbank eingefügt.

Abbildung ist im Inhalt beschrieben.

JDBC: Read

Zum Lesen einer persistenten Klasse fordert der Persistenzclient die DBClass zum Lesen auf. Die DBClass erstellt eine neue Anweisung mit der Operation createStatement() der Klasse Connection. Die Anweisung wird ausgeführt, und die Daten werden in einem Objekt ResultSet zurückgegeben. Anschließend erstellt die DBClass eine neue Instanz von PersistentClass und füllt diese mit den abgerufenen Daten. Die Daten werden in einem Erfassungsobjekt zurückgegeben, einer Instanz der Klasse PersistentClassList.

Anmerkung: Die an executeQuery() übergebene Zeichenfolge muss nicht dieselbe Zeichenfolge sein, die an read() übergeben wird. Die DBClass erstellt die SQL-Abfrage zum Abruf der persistenten Daten aus der Datenbank unter Verwendung der an read() übergebenen Bedingungen. Dies geschieht deswegen, weil wir nicht möchten, dass der Client der DBClass die Interna der Datenbank kennen muss, um eine gültige Abfrage zu erstellen. Dieses Wissen ist in der DBClass gekapselt.

Abbildung ist im Inhalt beschrieben.

JDBC: Update

Zum Aktualisieren einer Klasse fordert der Persistenzclient die DBClass zum Aktualisieren auf. Die DBClass ruft die Daten aus dem angegebenen PersistentClass-Objekt ab und erstellt eine neue Anweisung mit der Operation createStatement() der Klasse Connection. Nachdem die Anweisung erstellt wurde, wird die Aktualisierung durchgeführt und die Datenbank mit den neuen Daten aus der Klasse aktualisiert.

Beachten Sie Folgendes: Die DBClass hat die Aufgabe, die PersistentClass zu vereinfachen und in die Datenbank zu schreiben. Deshalb muss sie aus der angegebenen PersistentClass abgerufen werden, bevor die SQL-Anweisung erstellt wird.

Anmerkung: Im zuvor beschriebenen Mechanismus muss die PersistentClass Zugriffsroutinen für alle persistenten Daten bereitstellen, damit die DBClass auf sie zugreifen kann. Damit ist externer Zugriff auf bestimmte persistente Attribute möglich, die andernfalls nicht öffentlich wären. Dies ist der Preis, den Sie zahlen müssen, um das Persistenzwissen aus der Klasse zu ziehen, die die Daten kapselt.

Abbildung ist im Inhalt beschrieben.

JDBC: Delete

Zum Löschen einer Klasse fordert der Persistenzclient die DBClass auf, die PersistentClass zu löschen. Die DBClass erstellt eine neue Anweisung mit der Operation createStatement() der Klasse Connection. Die Anweisung wird ausgeführt, und die Daten werden aus der Datenbank gelöscht.

In der Implementierung dieses Designs müssen bestimmte Entscheidungen über die Zuordnung von DBClass zu den persistenten Klassen getroffen werden, z. B. Verwendung einer DBClass pro persistenter Klasse und Zuordnung dieser Klassen zu Paketen. Diese Pakete sind vom angegebenen Paket java.sql (siehe JDBC API-Dokumentation) abhängig, das die unterstützenden Klassen DriverManager, Connection, Statement und ResultSet enthält.