Softwaretechnik
Softwaretechnik
Softwaretechnik
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
<strong>Softwaretechnik</strong><br />
Zusammenfassung der Methodik der Vorlesung im Wintersemester 2010/2011<br />
INHALT<br />
1 Objektorientierte Analyse ............................................................................................................... 3<br />
1.1 Use Case – Modell ................................................................................................................... 3<br />
1.1.1 Aktoren bestimmen ......................................................................................................... 3<br />
1.1.2 Anwendungsfälle bestimmen .......................................................................................... 3<br />
1.1.3 Diagramm erstellen ......................................................................................................... 3<br />
1.1.4 Beschreibungen anfertigen ............................................................................................. 3<br />
1.2 Statisches Modell .................................................................................................................... 4<br />
1.2.1 Klassen identifizieren ....................................................................................................... 4<br />
1.2.2 Assoziationen bestimmen ............................................................................................... 4<br />
1.2.3 Attribute identifizieren .................................................................................................... 5<br />
1.2.4 Vererbung einführen ....................................................................................................... 5<br />
1.2.5 Modell überarbeiten ....................................................................................................... 5<br />
1.3 Dynamisches Modell ............................................................................................................... 5<br />
1.3.1 Interaktionsdiagramme entwickeln ................................................................................ 5<br />
1.3.2 Zustands- und Aktivitätsdiagramme entwickeln ............................................................. 6<br />
2 Objektorientierter Entwurf ............................................................................................................. 7<br />
2.1 Objektentwurf ......................................................................................................................... 7<br />
2.1.1 Operationen hinzufügen ................................................................................................. 7<br />
2.1.2 Assoziationen ausrichten ................................................................................................. 8<br />
2.1.3 Zugriffsrechte bestimmen ............................................................................................... 8<br />
2.1.4 Mehrfachvererbung auflösen .......................................................................................... 8<br />
2.1.5 Wiederverwendung von Klassen ..................................................................................... 8<br />
2.2 Realisierung von Zustandsdiagrammen .................................................................................. 8<br />
2.2.1 Prozedurgesteuerte Realisierung .................................................................................... 9<br />
2.2.2 Realisierung durch Fallunterscheidung ........................................................................... 9<br />
2.2.3 Realisierung durch Zustandsobjekte ............................................................................... 9<br />
2.2.4 Realisierung durch eine Zustandsmaschine .................................................................. 10<br />
2.3 Systementwurf ...................................................................................................................... 10<br />
2.3.1 Grundlagen .................................................................................................................... 10
2.3.2 Fassadenklassen ............................................................................................................ 10<br />
2.3.3 Schichtenarchitekturen ................................................................................................. 11<br />
2.3.4 Drei-Schichten-Architektur für betriebliche Informationssysteme ............................... 11<br />
2.3.5 Kontrollobjekte .............................................................................................................. 11<br />
2.3.6 Beobachter .................................................................................................................... 11<br />
Anmerkung:<br />
Der folgende Text versteht sich mit Blick auf die Klausur als Zusammenfassung zur gleichnamigen Vorlesung<br />
und fußt dazu natürlich auf die von Prof. Dr. Hennicker erstellten Inhalte.<br />
Quelle: http://www.pst.ifi.lmu.de/Lehre/wise-10-11/swtechnik<br />
Der Autor übernimmt keinerlei Gewährleistung dafür, dass diese Zusammenfassung inhaltlich vollständig oder<br />
korrekt ist. Die Benutzung erfolgt also zu eigenem Vergnügen – und auf eigene Gefahr. ;)<br />
Daniel Buschek
3<br />
1 OBJEKTORIENTIERTE ANALYSE<br />
Ziel: Die Anforderungen an das Softwaresystem erfassen und präzise und verständlich beschreiben.<br />
1.1 Use Case – Modell<br />
Input: Informelle, knappe Beschreibung, z.B. aus einem Interview.<br />
Ziel: Die (vom Kunden) gewünschte Funktionalität des Systems beschreiben.<br />
1.1.1 Aktoren bestimmen<br />
Zunächst sollen die Aktoren bestimmt werden, die mit dem System interagieren:<br />
• Wer benützt das System?<br />
• Wer holt Informationen vom System?<br />
• Wer liefert dem System Informationen?<br />
1.1.2 Anwendungsfälle bestimmen<br />
Nun können die Anwendungsfälle bestimmt werden; diese beschreiben die Aufgaben, die das<br />
System für einen oder mehrere Aktoren erledigen soll.<br />
Hierbei besteht oft die Schwierigkeit, die richtige Granularität zu finden: Welche Alternativen<br />
gehören noch zum selben Anwendungsfall, was ist schon ein neuer Anwendungsfall?<br />
1.1.3 Diagramm erstellen<br />
Nachdem Aktoren und Anwendungsfälle bestimmt wurden, kann ein entsprechendes<br />
Anwendungsfall-Diagramm (Use Case – Diagramm) erstellt werden. Eventuell kann hier noch eine<br />
kurze Beschreibung der Aktoren und Anwendungsfälle angegeben werden.<br />
1.1.4 Beschreibungen anfertigen<br />
In diesem letzten Schritt werden die Anwendungsfälle (iterativ) mit Beschreibungen versehen. Diese<br />
haben folgendes Format:<br />
• Name des Anwendungsfalls<br />
• Kurzbeschreibung<br />
• Vorbedingung: Was ist Voraussetzung für eine erfolgreiche Ausführung des Anwendungsfalls?<br />
• Nachbedingung: Beschreibung des Zustands nach erfolgreicher Ausführung.<br />
• Primärszenario: Beschreibt den schrittweisen Ablauf im Normalfall.<br />
• Sekundärszenarien: Beschreiben den schrittweisen Ablauf bei Fehlerfällen oder Optionen.
4<br />
1.2 Statisches Modell<br />
Input: Das Use Case – Modell, die ursprüngliche Problembeschreibung, erweitert um Experten- und<br />
Allgemeinwissen.<br />
Ziel: Ein Klassendiagramm, noch ohne Operationen.<br />
1.2.1 Klassen identifizieren<br />
Es sollen die Klassen für das statische Modell gefunden werden. Kandidaten dafür sind Personen<br />
bzw. Rollen, Organisationen, Gegenstände und begriffliche Konzepte (z.B. Bestellung).<br />
Vorgehensweise:<br />
1. Kandidaten notieren:<br />
Hierzu durchsucht man die Use Case – Beschreibungen nach Substantiven.<br />
2. Ungeeignete Klassen streichen:<br />
Es sollen Klassenkandidaten gestrichen werden, die redundant, irrelevant oder vage sind. Ebenso<br />
eignen sich manche der gefundenen Substantive möglicherweise besser als Attribut einer anderen<br />
Klasse oder es handelt sich um eine Tätigkeit.<br />
3. Fehlende relevante Klassen hinzufügen:<br />
Hinweise auf fehlende Klassen ergeben sich aus Problembereichswissen und aus Attributen vom<br />
vorigen Schritt, zu denen es noch keine Klassen gibt.<br />
1.2.2 Assoziationen bestimmen<br />
Nun sollen Assoziationen zwischen den Klassen gefunden werden. Kandidaten dafür sind<br />
physische/logische Verbindungen mit bestimmter Dauer, z.B. konzeptionelle Verbindungen<br />
(„arbeitet für“), Besitz („hat“, „ist Teil von“) sowie häufige Zusammenarbeit von Objekten zur Lösung<br />
einer Aufgabe.<br />
Vorgehensweise:<br />
1. Kandidaten notieren:<br />
Hierzu durchsucht man die Use Case – Beschreibungen nach Verben, Substantiven im Genitiv („die<br />
Karte des Kunden“) oder Possessivpronomen („seine“, „ihre“, …). Achtung: Verben bezeichnen oft<br />
Aktivitäten statt Beziehungen.<br />
2. Ungeeignete Assoziationen streichen:<br />
Vor allem auf redundante (abgeleitete) Assoziationen sollte verzichtet werden.<br />
3. Fehlende relevante Assoziationen hinzufügen:<br />
Analog zur Vorgehensweise beim Bestimmen der Klassen.<br />
4. Multiplizitäten und ggf. explizite Rollennamen hinzufügen:<br />
Im Zweifelsfall kann man die Multiplizitäten aber auch noch weglassen und erst später bestimmen.
5<br />
1.2.3 Attribute identifizieren<br />
Bei der Suche nach Attributen gelten folgende Richtlinien:<br />
• Es sollen nur für die Anwendung relevante Attribute eingeführt werden.<br />
• Attribute sollen keine Objekttypen haben, dafür werden Assoziationen verwendet.<br />
• Die genauen Attributtypen können noch weggelassen werden.<br />
1.2.4 Vererbung einführen<br />
In der Analyse geht es hierbei vor allem um Generalisierung: Gemeinsame Merkmale der<br />
vorhandenen Klassen (Attribute, Assoziationen) können in einer Oberklasse zusammengefasst<br />
werden. Außerdem sollte hier bestimmt werden, welche Klassen abstrakt sind.<br />
1.2.5 Modell überarbeiten<br />
Im Prinzip besteht dieser Schritt aus dem „Überdenken“ der bisherigen Arbeit. Checkliste:<br />
• Fehlen Klassen oder Assoziationen?<br />
• Sind alle Klassen und Assoziationen notwendig?<br />
• Sind alle Attribute und Assoziationen richtig platziert?<br />
• Gibt es Assoziationen, bei denen ein Qualifizierer sinnvoll wäre?<br />
• Welche Typen haben/bekommen die Attribute?<br />
• Fehlen noch Multiplizitäten?<br />
1.3 Dynamisches Modell<br />
Input: Use Case – Beschreibungen (Szenarien) und statisches Modell.<br />
Ziel: Entwurf von Interaktionsdiagrammen für jeden Anwendungsfall, auf deren Basis dann Zustandsund<br />
Aktivitätsdiagramme abgeleitet werden.<br />
1.3.1 Interaktionsdiagramme entwickeln<br />
Interaktionsdiagramme beschreiben die Zusammenarbeit und den Nachrichtenaustausch zwischen<br />
mehreren Objekten. In UML gibt es Sequenzdiagramme und Kommunikationsdiagramme. Im<br />
Rahmen der Vorlesung bzw. Übung wurden nur Sequenzdiagramme auch wirklich verwendet.<br />
Vorgehensweise:<br />
1. Identifizieren der Nachrichten, die innerhalb eines Anwendungsfalls ausgetauscht werden und<br />
der Objekte, die die Nachrichten senden und empfangen.<br />
2. Konstruktion von Interaktionsdiagrammen für jeden Anwendungsfall bzw. dessen Szenarien.
6<br />
1.3.2 Zustands- und Aktivitätsdiagramme entwickeln<br />
Input: Die im vorigen Schritt erstellten Sequenzdiagramme zu den Anwendungsfällen.<br />
Ziel: Ein Zustandsdiagramm für jede Klasse mit „interessanten Verhalten“ entwickeln (Klassen deren<br />
Objekte einen nicht-trivialen Lebenszyklus haben). Die in den Zustandsdiagrammen auftauchenden<br />
Operationen sollen dann mit Aktivitätsdiagrammen beschrieben werden.<br />
Zustands- und Aktivitätsdiagramme erfassen also das vollständige Verhalten eines jeden Objekts<br />
einer Klasse über viele Szenarien hinweg. Aktivitätsdiagramme können auch weggelassen werden,<br />
wenn es bereits ein einziges Interaktionsdiagramm gibt, das schon das vollständige Ablauf-Verhalten<br />
der Operation zeigt.<br />
Kriterien für „interessantes Verhalten“:<br />
• Ein Objekt reagiert auf gleiche Ereignisse in Abhängigkeit seines Zustands unterschiedlich.<br />
• Mindestens ein Ereignis wird in bestimmten Zuständen ignoriert (bzw. kann dort gar nicht<br />
auftreten).<br />
Typische zustandsabhängige Objekte sind Kontrollobjekte für Anwendungsfälle und<br />
Benutzerschnittstellen, Geräte (z. B. Digitaluhr) sowie Objekte mit beschränktem Fassungsvermögen<br />
(voll, leer).<br />
Klassifizierung von Zuständen:<br />
• stabiler/inaktiver Zustand: Ein Zustand, dem keine Aktivität zugeordnet ist.<br />
• Aktivitätszustand: Ein Zustand, dem eine Aktivität zugeordnet ist und der nur durch ein (evtl.<br />
bedingtes) Completion Event verlassen werden kann.<br />
Vorgehensweise zur Konstruktion eines Zustandsdiagramms:<br />
1. Wahl eines Sequenzdiagramms, das eine typische Interaktion für ein Objekt der betrachteten<br />
Klasse zeigt (normalweise das Sequenzdiagramm für das Primärszenario).<br />
2. Betrachten der Lebenslinie des Objekts.<br />
3. Bilden einer Kette von Zuständen, wobei man der Lebenslinie des Objekts folgt:<br />
• Inaktive Phasen werden durch stabile Zustände modelliert.<br />
• Aktive Phasen werden durch Aktivitätszustände umgesetzt, in denen lokale Operationen<br />
zur Durchführung der Aktivität aufgerufen werden (dies wird später in den<br />
Aktivitätsdiagrammen dargelegt).<br />
• Eintreffende Ereignisse werden durch entsprechend markierte Transitionen von stabilen<br />
Zuständen in Aktivitätszustände modelliert.<br />
• Das Ende von aktiven Phasen wird durch eine Transition mit einem Completion Event<br />
von einem Aktivitätszustand in einen stabilen Zustand umgesetzt.<br />
4. Bilden von Zyklen für Abläufe, die wiederholt werden können.<br />
Damit ist dann ein Sequenzdiagramm verarbeitet, freilich noch ohne die Details zu den Aktivitäten.<br />
Die angegebenen Schritte wiederholt man für alle Sequenzdiagramme, in denen ein Objekt der
7<br />
betrachteten Klasse eine Rolle spielt und erweitert das Zustandsdiagramm entsprechend. Meist führt<br />
diese Erweiterung zu Verzweigungen von einem stabilen Zustand aus, der in mehreren<br />
Sequenzdiagrammen als Ausgangszustand des Objekts auftauchte.<br />
Anschließend folgt die Konstruktion von Aktivitätsdiagrammen für die lokalen Operationen (also die<br />
Operationen in den Aktivitätszuständen des erstellten Zustandsdiagramms).<br />
Außerdem kann das Zustandsdiagramm evtl. noch durch das Hinzufügen von Bedingungen bei den<br />
von Aktivitätszuständen ausgehenden Transitionen verfeinert werden. Dies ist wichtig, damit das<br />
Zustandsdiagramm deterministisch ist!<br />
Zuletzt müssen evtl. auch noch weitere angegebene Sekundärszenarien integriert werden, für die<br />
gar kein Sequenzdiagramm erstellt wurde.<br />
2 OBJEKTORIENTIERTER ENTWURF<br />
Input: Das statische und dynamische Modell der objektorientierten Analyse.<br />
Ziel: Ein Modell der Systemimplementierung; also wie die einzelnen Aufgaben gelöst werden.<br />
2.1 Objektentwurf<br />
Das statische Analysemodell wird nun erweitert und überarbeitet. Dazu verwendet man die<br />
Informationen aus dem dynamischen Modell der Analyse. Die beiden Modelle werden also<br />
zusammengeführt.<br />
2.1.1 Operationen hinzufügen<br />
Das statische Modell soll um Operationen erweitert werden.<br />
Vorgehensweise:<br />
1. Betrachten der Interaktionsdiagramme: Für jede an ein Objekt der Klasse K gesendete Nachricht<br />
wird eine entsprechende Operation bei K eingeführt.<br />
2. Betrachten der Zustands- und Aktivitätsdiagramme: Es wird eine Operation eingeführt für jedes<br />
Call-Event eines Zustandsdiagramms und für jede in einem Aktivitätszustand aufgerufene (lokale)<br />
Operation. Das gilt natürlich auch für Aktionen in den zugehörigen Aktivitätsdiagrammen.<br />
3. Benutzerdefinierte Konstruktoren bei nicht-abstrakten Klassen hinzufügen.<br />
4. Benötigte Zugriffsoperationen für Attribute und Rollen hinzufügen (also Getter- und Setter).<br />
5. Beschreiben der Algorithmen der Operationen (z. B. in Java-Pseudocode).
8<br />
2.1.2 Assoziationen ausrichten<br />
Mit diesem Schritt sollen bidirektionale Assoziationen vermieden werden, was die spätere<br />
Implementierung erleichtert. Dazu wird betrachtet, in welche Richtung die bestehenden<br />
Assoziationen durchlaufen werden (z.B. beim Senden von Nachrichten oder Operationsaufrufen).<br />
Wenn sich dabei herausstellt, dass dies nur in eine Richtung geschieht, wird die Assoziation<br />
entsprechend ausgerichtet.<br />
2.1.3 Zugriffsrechte bestimmen<br />
Nun werden die Zugriffsrechte für Attribute, Rollennamen und Operationen festgelegt. Attribute und<br />
Rollennamen sollten dabei nicht öffentlich zugreifbar sein.<br />
2.1.4 Mehrfachvererbung auflösen<br />
Dieser Schritt ist notwendig, wenn die bei der Implementierung benutzte Sprache keine<br />
Mehrfachvererbung unterstützt (z.B. Java). Die Auflösung wird durch die Einführung einer<br />
Schnittstelle umgesetzt.<br />
Eine der beiden Oberklassen wird durch ein Interface ersetzt, das an ihrer Stelle von der Unterklasse<br />
geerbt (bzw. implementiert) wird. Zudem wird eine neue Klasse erstellt, welche die entfernte<br />
Oberklasse ersetzen soll (vermutlich gleiche Implementierung). Diese neue Klasse implementiert<br />
ebenfalls das eingeführte Interface und wird von der Unterklasse zur Delegation bei Aufrufen der<br />
Operationen aus dem Interface benutzt.<br />
Beispieldiagramme dazu finden sich im Skript in Kapitel 4.1.4 (Folie 11).<br />
2.1.5 Wiederverwendung von Klassen<br />
Oft bestehen bereits erprobte und hochwertige Klassen, die man im Entwurf wiederverwenden<br />
möchte. Braucht man noch mehr Funktionen als die vorhandenen, kann man diese durch<br />
Spezialisierung in einer Subklasse hinzufügen.<br />
Achtung: Vielleicht bietet die geerbte Klasse mehr Operationen an, als man eigentlich benötigt.<br />
Dadurch könnte das Kapselungsprinzip verletzt werden. In einem solchen Fall bietet sich eine<br />
Wiederverwendung durch Delegation an. Hierbei bekommt die neue Klasse ein (privates) Objekt der<br />
wiederverwendeten Klasse, an das sie bei Bedarf Methodenaufrufe weiterleiten kann.<br />
2.2 Realisierung von Zustandsdiagrammen<br />
Input: Das Zustandsdiagramm einer Klasse.<br />
Ziel: Ein Objektentwurf mit Algorithmen zur Realisierung des durch das Zustandsdiagramm<br />
beschriebenen Verhaltens.<br />
Zustandsdiagramme können systematisch realisiert und in den Objektentwurf integriert werden.<br />
Dazu gibt es vier Möglichkeiten, die im Folgenden beschrieben werden.
9<br />
2.2.1 Prozedurgesteuerte Realisierung<br />
Bei diesem Ansatz werden Ereignisse durch erzwungene Benutzereingaben unterschieden. Das setzt<br />
voraus, dass es sich bei den Objekten um Kontrollobjekte zur Dialogsteuerung handelt und sich diese<br />
somit an der Systemgrenze befinden.<br />
Vorgehensweise:<br />
Das gesamte Zustandsdiagramm wird überführt in eine Prozedur mit:<br />
• modalen Dialogen für die (externen) Ereignisse<br />
• bedingten Anweisungen für Verzweigungen<br />
• Wiederholungsanweisungen für Zyklen des Diagramms<br />
Anmerkung: Diese Methode ist heutzutage offensichtlich keine allzu gute Idee mehr; flexible<br />
Benutzerschnittstellen sind so nur schwer zu realisieren.<br />
2.2.2 Realisierung durch Fallunterscheidung<br />
Hier merkt sich das Objekt seinen Zustand in Form eines Attributs. In den Operationen kann dann<br />
anhand dieses Wertes entschieden werden, wie sie sich zu verhalten haben.<br />
Vorgehensweise:<br />
1. Ein Enumerationstyp stellt die endlich vielen (stabilen) Zustände dar.<br />
2. Die Klasse bekommt ein explizites Zustandsattribut dieses Typs.<br />
3. Die zustandsabhängigen Operationen werden durch Fallunterscheidung nach dem aktuellen<br />
Wert des Zustandsattributs realisiert.<br />
Vorteil: Leichte Erweiterbarkeit bezüglich neuer Operationen. Eine neue Operation wird einfach zur<br />
Klasse hinzugefügt und nutzt die Fallunterscheidung nach dem Wert des Zustandsattributs.<br />
Nachteil: Schlechte Erweiterbarkeit bezüglich neuer Zustände. Ein neuer Zustand bedeutet<br />
möglicherweise Veränderungen (nämlich einen neuen Fall) bei den Fallunterscheidungen in allen<br />
bisherigen Operationen.<br />
2.2.3 Realisierung durch Zustandsobjekte<br />
Ein spezielles Zustandsobjekt übernimmt hier die Ausführung der zustandsabhängigen Operationen.<br />
Vorgehensweise:<br />
1. Jedes Objekt der Klasse bekommt ein Zustandsobjekt, das den aktuellen Zustand repräsentiert.<br />
2. Aufrufe von zustandsabhängigen Operationen werden an das Zustandsobjekt delegiert.<br />
3. Das aktuelle Zustandsobjekt führt die gewünschte Aktivität aus und gibt den (neuen) Zustand<br />
zurück, der nun mit dem Basisobjekt verbunden werden soll.
10<br />
Vorteil: Leichte Erweiterbarkeit bezüglich neuer Zustände. Ein neuer Zustand kann einfach als neue<br />
Unterklasse der abstrakten Zustandsklasse umgesetzt werden.<br />
Nachteil: Schlechte Erweiterbarkeit bezüglich neuer Operationen. Eine neue Operation muss<br />
zumindest in die Klasse und den abstrakten Zustand aufgenommen werden; möglicherweise aber<br />
leider auch in alle bisherigen Zustands-Unterklassen.<br />
2.2.4 Realisierung durch eine Zustandsmaschine<br />
Dieser Ansatz realisiert das Zustandsdiagramm, in dem dieses komplett mit verbundenen Objekten<br />
„nachgebaut“ wird.<br />
Idee:<br />
• Alle in einem Zustandsdiagramm vorkommenden Größen (stabile Zustände, Transitionen,<br />
Aktivitäten, Ereignisse) werden durch Objekte dargestellt.<br />
• Ereignisse werden von einer speziellen „Event-Handle“-Operation interpretiert.<br />
• Das gesamte Zustandsdiagramm wird durch eine verzeigerte Objektstruktur repräsentiert.<br />
2.3 Systementwurf<br />
Ziel: Der Objektentwurf soll in die Systemumgebung eingebettet werden. Außerdem wird die<br />
Systemarchitektur festgelegt.<br />
2.3.1 Grundlagen<br />
Die Systemarchitektur beschreibt die Gesamtstruktur des Software-Systems durch Angabe von<br />
Subsystemen und Beziehungen zwischen diesen. Eine grobe Systemarchitektur wird meist schon zu<br />
Beginn der Systementwicklung angegeben. Subsysteme werden durch Pakete oder durch<br />
Komponenten (mit Schnittstellen) dargestellt.<br />
Grundregeln:<br />
• hohe Kohärenz (high cohesion):<br />
Systemteile die (logisch) zusammen gehören sollen in einem Subsystem zusammengefasst werden.<br />
• geringe Kopplung (low coupling):<br />
Zwischen den Subsystemen sollen möglichst wenige Abhängigkeiten bestehen.<br />
→Vorteil: Änderung und Austauschen von einzelnen Teilen wird vereinfacht.<br />
2.3.2 Fassadenklassen<br />
Mit Hilfe von Fasadenklassen kann eine geringe Kopplung erreicht werden. Sie vereinen die Dienste<br />
verschiedener Klassen eines Subsystems durch Delegation der Aufrufe an die zuständigen Objekte.<br />
Ein Beispiel dazu findet sich im Skript in Kapitel 4.3.2 (Folie 50).
11<br />
2.3.3 Schichtenarchitekturen<br />
In einer Schichtenarchitektur stellt jede Schicht Dienste für die darüber liegende(n) Schicht(en)<br />
bereit. Ein bekanntes Beispiel ist das OSI-Modell.<br />
• Bei „geschlossenen“ Architekturen darf eine Schicht nur auf die direkt darunterliegende Schicht<br />
zugreifen, andernfalls spricht man von einer „offenen“ Architektur.<br />
• Als Client/Server-System bezeichnet man eine Verteilung der Schichten auf verschiedene Rechner.<br />
• Eine Schicht kann selbst aus verschiedenen Subsystemen bestehen.<br />
2.3.4 Drei-Schichten-Architektur für betriebliche Informationssysteme<br />
Für viele Anwendungen wird eine Drei-Schichten-Architektur gewählt. Diese besteht aus einer<br />
Benutzerschnittstelle, dem Anwendungskern und einer Datenbankschnittstelle.<br />
Benutzerschnittstelle:<br />
• Behandelt Nutzereingaben (Mausklicks, Tasten)<br />
• Ein-/Ausgabe von Daten<br />
• Dialogkontrolle<br />
Anwendungskern:<br />
• Zuständig für die Anwendungslogik, also die eigentlichen Aufgaben des Problembereichs<br />
• Ergibt sich aus dem Objektentwurf<br />
Datenbankschnittstelle:<br />
• Sorgt für Speicherung persistenter Daten der Anwendung und den Zugriff darauf<br />
Daneben gibt es noch Subsysteme für allgemeine Dienste, wie etwa Kommunikationsdienste,<br />
Dateiverwaltung oder Bibliotheken (APIs, GUI, …).<br />
2.3.5 Kontrollobjekte<br />
Für die Dialogsteuerung (z.B. Verwaltung mehrerer Fenster) oder zur Steuerung der Aufgaben des<br />
Anwendungskerns werden häufig eigene Objekte verwendet. Solche Kontrollobjekte sorgen für<br />
geringe Kopplung und haben meist ein interessantes Verhalten, das durch Zustandsdiagramme<br />
beschrieben werden kann.<br />
2.3.6 Beobachter<br />
Es gilt die Sichtbarkeitsregel zu beachten: Der Anwendungskern darf die Benutzerschnittstelle nicht<br />
kennen. Das hat den Vorteil, dass Änderungen an der GUI keine Auswirkungen auf den Code des<br />
Anwendungskerns haben. Um die berechneten Daten dennoch anzeigen zu können, kann man mit<br />
Beobachtern arbeiten.
12<br />
Indirekte Kommunikation durch Beobachter:<br />
• GUI-Objekte melden sich als Beobachter (Observer) beim Anwendungskern an (addObserver).<br />
• Falls der Anwendungskern ein Ereignis publizieren will, benachrichtigt er alle seine Beobachter<br />
(notifyObservers), die entsprechend reagieren (update).<br />
• Jeder konkrete Beobachter implementiert das Interface Observer.<br />
• Der Anwendungskern kennt (zur Programmierzeit) nur das Observer-Interface. Konkrete<br />
Observer werden zur Laufzeit dynamisch eingebunden.