|
|
I-PROGR3 WS03 - PROGRAMMIEREN3 - Vorlesung mit Übung
|
In den vorausgehenden Übungen wurde bei der Analyse bisher nur unterschieden zwischen den statischen Elementen eines Modells sowie deren Dynamik. Es gibt aber noch einen weiteren wichtigen Aspekt bei der Erarbeitung eines Modells; gemeint ist die Unterscheidung in Verhaltensmodell und Designmodell. Dies soll in der heutigen Vorlesung in Grundzügen angesprochen und an einem Beispiel illustriert werden.
(Anmerkung: Die Überlegungen dieses Abschnitts wurden entscheidend beeinflusst von einem längeren Gespräch mit meinem Kollegen Matthias Wagner, als wir das Für und Wider der SWE-Designphilosophie von Craig LARMAN [2001] diskutierten).
Die Unterscheidung zwischen Verhaltensmodell (englisch 'requirements model') und Designmodell ergibt sich aus der 'Natur' des gesamten Softwareengineering Prozesses (dessen Details in späteren Vorlesungen vertieft werden). Es hat damit zu tun, dass der Auslöser für eine Software aus einem Auftrag resultiert, in dem ein Kunde beschreibt, welche Dienste eine Software für ihn in einem bestimmten Anwendungsbereich (Domäne) bieten soll. Dienste bestehen aus einer Menge von nachprüfbaren Verhaltensaktionen, in denen die Software auf bestimmte Eingaben mit bestimmten Ausgaben reagiert.
Der Anwendungsbereich (die Domäne) ist in der Regel ein spezifischer Wirklichkeitsausschnitt, der mit sprachlichen Ausdrücken beschrieben wird, die i.d.R. ebenfalls spezifisch für diese Domäne sind. SoftwareingenieureInnen, die die gewünschten Dienste in der Domäne zu beschreiben haben, müssen versuchen, die domänenspezifische Sprache zu verwenden, um damit dem Verständnis des Auftraggebers so nah wie möglich zu kommen und auf diese Weise Missverständnisse soweit wie möglich zu vermeiden.
Es liegt in der Natur der Sache, dass die domänenspezifische Beschreibung der Dienste keinerlei Bezug nimmt auf die Art und Weise, wie diese Dienste mittels Hardware und/ oder Software zu realisieren ist; es zählen hier einzig und alleine die gewünschten Verhaltensweisen selbst. Entscheidend ist hier nur das Was der Dienste: was soll die Software --ausgedrückt in der Sprache der Einsatzdomäne-- leisten.
Die Menge der Anforderungen ('requirements'), die die Wünsche des Kunden bzgl. der gewünschten Dienste beschreibt, sollte so generisch wie möglich, zugleich aber auch so vollständig wie möglich sein.
Auch bei einer Beschränkung auf den Aspekt des Verhaltens bietet eine systematische Analyse die Möglichkeit, unter dem Blickwinkel der beteiligten statischen Elemente (Klassen) sowie der implizierten Dynamik (Sequenzdiagramme) eine erste Modellierung vorzunehmen. Die Gesamtheit dieser Analysen wird unter dem Begriff des Verhaltensmodells zusammengefasst.
Durchläuft man diesen Prozess (siehe Beispiel unten), dann wird man am Ende feststellen, dass die erstellten Klassen und Sequenzdiagramme merkwürdig unvollständig erscheinen; es treten zwar öffentlich zugängliche Methoden und Attribute in den Klassen und in der Sequenz auf, aber es fehlen die privaten Elemente; es fehlen die Details einer möglichen Realisierung; es fehlt das Wie der Software! Das Verhaltensmodell ist implementierungsneutral.
Diese Beobachtung führt unmittelbar zum Designmodell. Denn um von einem Verhaltensmodell zu einem funktionsfähigen Quellkode zu kommen, müssen sowohl in den Klassen wie auch in den Sequenzdiagrammen noch sehr viele Details nachgeliefert werden. Überall muss gesagt werden, WIE denn die gewünschten Verhaltensweisen konkret realisiert werden sollen. Dieser Übergang vom reinen Verhaltensmodell (engl. 'requirements model) zum Quelltext wird unter dem Label des Designmodells organisiert.
SWE-Schema mit Statisch/ Dynamisch + Verhalten/ Design
Das Designmodell nimmt seinen Ausgangspunkt bei dem Verhaltensmodell auf der einen Seite, und bei den bekannten Randbedingungen einer Realisierung auf der anderen Seite. Diese Randbedingungen können eine Vielzahl von Faktoren umfassen ( Finanzierungsrahmen des Projektes, verfügbare Technologien, firmenspezifische Besonderheiten, verpflichtende Standards, Besonderheiten der späteren Benutzer usf.), die alle auf unterschiedliche Weise dazu beitragen, die Implementierung zu beeinflussen. In dieser Vorlesung beschränkt sich die Betrachtung des Designmodells auf die Aspekte, welche Angaben noch gemacht werden müssen, um aus dem Verhaltensmodell ein lauffähiges Programm unter C++ zu generieren.
Dies bedeutet, dass die Klassen aus dem Verhaltensmodell mit zusätzlichen Angaben bzgl. möglicher privater Attribute und Methoden erweitert werden müssen oder auch bzgl. möglicher Querbeziehungen zwischen verschiedenen Klassen. Ferner müssen die Details der Methoden geklärt werden, z.B. in Form von Aktivitäts- oder Zustandsdiagrammen. Dies führt dann auch zu einer Erweiterung der Sequenzdiagramme; sie werden detaillierter.
Die obigen Überlegungen zur Unterscheidung zwischen Verhaltens- und Designmodell sollen jetzt an einem Beispiel illustriert werden.
In Erweiterung der Überlegungen aus der vorausgehenden Vorlesung werden als Domäne die Bereiche Computerspiele und Simulation gewählt. Das Konzept 'Board' wird durch das allgemeine Konzept 'World' ersetzt.
Es wird eine Anwendungssituation angenommen, in der es zwei verschiedene Akteure gibt: (i) einen Master, der die Eckwerte für eine Spielwelt ('world') festlegt, und einen User, der im Rahmen der Vorgaben ein Spiel starten und modifizieren kann.
Use Case für world1-Anwendung
Wie schon mehrfach erwähnt ist das Anwendungsdiagramm selbst sehr abstrakt. Es sollte durch geeignete textliche Beschreibungen ergänzt werden. Eine Möglichkeit, dies gezielt zu tun, ist die Erstellung einer Liste der erwünschten Verhaltensweisen. Da Verhaltensweisen sich aus Ereignis-Reaktions-Paaren bilden, kann man diese Liste dann als eine Ereignis- Reaktions-Liste realisieren (siehe dazu ausführlich und mit vielen Beispielen z.B. [ELLIS 1994]). In dieser Liste werden alle Ereignisse aufgelistet, auf die das System reagieren soll sowie alle zu einem Ereignis erwarteten Reaktionen des Systems. Dabei ist zu beachten, dass nur alle aus der sicht des Masters oder des Users beobachtbaren Verhaltensweise der Software (des Systems) aufgelistet werden können; Bezug auf Details interner Prozesse würde in den Bereich der Implementierung und damit auch in den Bereich des Designs fallen; dies würde den Rahmen des Verhaltensmodells sprengen. Im vorliegenden Beispiel könnte dies etwa wie folgt aussehen:
NR. |
EREIGNIS |
REAKTION |
NEXT |
PREVIOUS |
---|---|---|---|---|
1. |
Dimensionsangaben für Welt |
Geeignetes Feedback über die intern erfolgten Änderungen |
1-3 |
1-3 |
2. |
Festlegung der möglichen Objekte |
Geeignetes Feedback über die intern erfolgten Änderungen |
1-3 |
1-3 |
3. |
Eingabe von Regeln |
Geignetes Feedback über die intern erfolgten Änderungen |
1-3 |
1-3 |
4. |
Start eines Spieles |
Anzeige der Handlungsmöglichkeiten |
5-6,8-9 |
4 |
5. |
Stoppen eines Spiels |
Feedback zur Beendigung |
4 |
4 |
6. |
Unterbrechen eines laufenden Spieles |
Warten auf Fortsetzung |
7 |
6 |
7. |
Fortsetzung eines unterbrochenen Spiels |
Anzeige der aktuellen Handlungsmöglichkeiten |
5,6,8-9 |
6 |
8. |
Auswahl von Objekten aus Angebot |
Geeignetes Fedback über die erfolgten Änderungen |
5-6,9 |
4,7,9 |
9. |
Auswahl einer Aktion |
Geeignetes Fedback über die erfolgten Änderungen |
5-6,8-9 |
4,7,8 |
Man kann an dieser Liste erkennen, dass diese Beschreibungen für eine tatsächliche Realisierung noch viel zu vage sind. Das beobachtbare Verhalten muss also noch weiter präzisiert werden.
Im Klassendiagramm soll nur aufgelistet werden, welche Klassen grundsätzlich für eine Umsetzung des gewünschten Verhaltens angenommen werden, ohne dass hier auf Details dieser Klassen eingegangen wird.
Wie man im Diagramm sehen kann (siehe Diagramm), werden drei Klassen angenommen:
Die Klasse world bildet die Basis. Sie enthält allgemeine Informationen über die Welt.
Die Klasse object enthält Informationen über spezielle Objekte. Eine Welt kann mehrere Objekte besitzen.
Die Klasse rule_set enthält die Regeln für das Verhalten der Objekte in der Welt.
Klassendiagramm für world1-Anwendung
Strenggenommen gehen diese Annahmen über die Klassen schon über das rein beobachtbare Verhalten hinaus; es ist die Identifizierung von möglichen Trägern des Verhaltens. Im einfachsten Fall würde man sagen, es gibt nur einen Träger allen beobachtbaren Verhaltens, eben die world. Die Unterscheidung von world und object bildet schon eine Differenzierung, die man eigens erklären muss. Die weitere Diferenzierung in world, object und rule_set ist noch erklärungsbedürftiger.
Die weitere Ausarbeitung muss zeigen, ob sich diese Annahmen durchhalten lassen, oder ob noch Änderungen vorgenommen werdeb müssen.
Es sollen jetzt die Klassen aus dem Klassendiagramm einzeln analysiert werden. Man muss feststellen, welche Verhaltensweisen man den einzelnen Klassen aufgrund der Anwendungsanalyse zuweisen muss. Bei der Ausarbeitung zeigt sich, dass man rückwirkend die Ereignis-Reaktionsliste neu überarbeiten muss (was an dieser Stelle noch nicht geschehen ist.
Ausführliches Klassendiagramm für world1-Anwendung
Die Zusammenhänge zwischen den einzelnen Klassen wurden wie folgt angenommen:
Die Klasse world bildet sowohl eine Schnittstelle für den Master wie auch für den User.
Der Master legt über die Welt fest, welche allgemeinen Eigenschaften die Welt haben soll. Über die Welt editiert der Master auch die Klasse rule_set (neue Regeln einführen, Regeln anzeigen, Regeln ändern, Regeln kopieren, Regeln löschen). Als Ergebnis der Erzeugung einer Regelmenge kann der Master dann eine Liste der aktuellen Objekttypen erzeugen lassen und in die Welt übernehmen.
Der User kann über die Welt ein Spiel starten. Im Rahmen des Spiels kann er Objekte einführen, Aktionen ausführen, das Spiel unterbrechen, wieder aufnehmen und natürlich auch das Spiel wieder stoppen.
Das nachfolgende Sequenzdiagramm zeigt nur die verhaltensbasierten Aktionen, und auch diese nicht vollständig; die einzelnen Aktionen des Masters (Regeländerungen, Regeln löschen usw.) wurden ausgelassen.
Sequenzdiagramm für world1-Anwendung (nur Verhalten, bei Master nicht vollständig)
In den Übungen