23.10.2012 Aufrufe

Eine Simulationsumgebung für strukturierte ... - It works!

Eine Simulationsumgebung für strukturierte ... - It works!

Eine Simulationsumgebung für strukturierte ... - It works!

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Diplomarbeit<br />

<strong>Eine</strong> <strong>Simulationsumgebung</strong> <strong>für</strong><br />

<strong>strukturierte</strong> natürlichsprachliche<br />

Anwendungsfallbeschreibungen<br />

von<br />

Mark Lehmacher<br />

Vorgelegt der<br />

Fakultät <strong>für</strong> Mathematik, Informatik und Naturwissenschaften der<br />

Rheinisch-Westfälischen Technischen Hochschule Aachen<br />

im März 2008<br />

Angefertigt am<br />

Lehr- und Forschungsgebiet Informatik 3<br />

Prof. Dr. rer. nat. Horst Lichter<br />

Gutachter:<br />

Prof. Dr. rer. nat. Horst Lichter<br />

Prof. Dr.-Ing. Manfred Nagl<br />

Betreuer:<br />

Dipl.-Inform. Veit Hoffmann


Hiermit versichere ich, dass ich die vorliegende Arbeit selbständig verfasst und keine<br />

anderen als die angegebenen Quellen und Hilfsmittel benutzt sowie Zitate kenntlich<br />

gemacht habe.<br />

Aachen, den 25. März 2008<br />

Mark Lehmacher


Inhaltsverzeichnis<br />

1 Einleitung 1<br />

1.1 Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

1.2 Aufbau der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />

2 Theoretische Grundlagen 5<br />

2.1 UML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />

2.2 NarrativeModel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />

2.3 Beispiel <strong>für</strong> eine textbasierte Anwendungsfallbeschreibung . . . . . . 23<br />

3 Technische Grundlagen 27<br />

3.1 Eclipse-Plattform . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />

3.2 GEF und Draw2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />

3.3 Eclipse Modeling Framework . . . . . . . . . . . . . . . . . . . . . . 42<br />

3.4 ViPER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49<br />

4 Konzeptueller Lösungsansatz 55<br />

4.1 Ausführungssicht auf eine NarrativeModel-Instanz . . . . . . . . . . 55<br />

4.2 ExecutionModel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57<br />

4.3 SimulationModel . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64<br />

5 Technische Umsetzung 67<br />

i


5.1 Berechnung des ExecutionModels . . . . . . . . . . . . . . . . . . . 67<br />

5.2 FlowView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71<br />

5.3 ExecutionModelView . . . . . . . . . . . . . . . . . . . . . . . . . . 73<br />

5.4 Simulator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79<br />

5.5 Integration der graphischen Einzelkomponenten . . . . . . . . . . . . 82<br />

6 Evaluierung 85<br />

6.1 Inhaltliche Evaluierung . . . . . . . . . . . . . . . . . . . . . . . . . 85<br />

6.2 Softwaretechnische Evaluierung . . . . . . . . . . . . . . . . . . . . 88<br />

7 Zusammenfassung und Ausblick 91<br />

ii


Abbildungsverzeichnis<br />

2.1 Grobe Struktur des NarrativeModels . . . . . . . . . . . . . . . . . . 10<br />

2.2 Feine Struktur der Verhaltenselemente . . . . . . . . . . . . . . . . . 12<br />

2.3 Typhierarchie der abstrakten Event-Metaklasse . . . . . . . . . . . 13<br />

2.4 Typhierarchie der abstrakten Context-Metaklasse . . . . . . . . . . 14<br />

2.5 Kontrollfluss bei Ausnahmeflüssen . . . . . . . . . . . . . . . . . . . 15<br />

2.6 Inklusionskontext- und Inklusionskonzepte . . . . . . . . . . . . . . 17<br />

2.7 Abstrakte Erweiterungskontext- und Erweiterungsankerkonzepte . . . 18<br />

2.8 Verfeinerung der Erweiterungskontext- und Erweiterungsankerkonzepte 19<br />

2.9 Generalisierung und Redefinierbarkeit im NarrativeModel . . . . . . 21<br />

2.10 Use Case Modellierung eines Geldautomaten . . . . . . . . . . . . . 23<br />

2.11 Textuelle Beschreibung der Geldautomatanwendungsfälle . . . . . . . 24<br />

3.1 Architektur der Eclipse-Plattform . . . . . . . . . . . . . . . . . . . . 29<br />

3.2 Screenshot der Eclipse-Workbench . . . . . . . . . . . . . . . . . . . 32<br />

3.3 Integration von Java-Editor und die OutlineView . . . . . . . . . . . 33<br />

3.4 Architektur der Workbench (vgl. [Eclc]) . . . . . . . . . . . . . . . . 33<br />

3.5 Workbench Konzepte(vgl. [Eclc]) . . . . . . . . . . . . . . . . . . . 34<br />

3.6 SelectionService, SelectionProvider und SelectionListener (vgl. [Eclb]) 36<br />

3.7 Typhierarchie von ISelection (vgl. [Eclb]) . . . . . . . . . . . . 36<br />

3.8 Grobe Sicht der GEF-Architektur (vgl. [Ecle]) . . . . . . . . . . . . . 37<br />

iii


3.9 Grobe Sicht der Draw2D-Architektur (vgl. [Ecld]) . . . . . . . . . . . 38<br />

3.10 MVC Architektur in GEF (vgl. [Ecle]) . . . . . . . . . . . . . . . . . 40<br />

3.11 Erzeugung von EditParts mittels EditPartFactory (vgl. [Ecle]) . 41<br />

3.12 Typhierarchie von Ecore im Überblick . . . . . . . . . . . . . . . . . 44<br />

3.13 Vereinfachter Ausschnitt aus dem Ecore-Modell . . . . . . . . . . . . 45<br />

3.14 Beispiel <strong>für</strong> Metamodellierung mittels Ecore . . . . . . . . . . . . . . 46<br />

3.15 Auszug aus der EObject-Schnittstelle . . . . . . . . . . . . . . . . 46<br />

3.16 Screenshot der NarrativeModel-Perspektive . . . . . . . . . . . . . . 52<br />

4.1 Aktivitätsdiagramm zum Geldautomatenbeispiel . . . . . . . . . . . . 57<br />

4.2 Grobe Struktur des ExecutionModels . . . . . . . . . . . . . . . . . . 58<br />

4.3 Event repräsentiert von zwei EventExecutions . . . . . . . . . . . . . 59<br />

4.4 Reduzierende Kontextwechsel . . . . . . . . . . . . . . . . . . . . . 59<br />

4.5 Verfeinerung der ExecutionContextChange-Metaklasse . . . . 60<br />

4.6 Eigenschaften der Transition-Metaklasse . . . . . . . . . . . . . 61<br />

4.7 Semantische Variation durch Inklusion abstrakten Verhaltens . . . . . 62<br />

4.8 Schleife modelliert mittels Erweiterung . . . . . . . . . . . . . . . . 64<br />

4.9 Struktur des SimulationModels . . . . . . . . . . . . . . . . . . . . . 65<br />

4.10 Funktionsweise der record-Operation einer Trace . . . . . . . . . . . 66<br />

5.1 ExecutionModelBuilder- und EventExecutionSuccessor-<br />

Strategy-Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . 68<br />

5.2 Implementierung der supports-Methode in DirectSuccessorStrategy<br />

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68<br />

5.3 Funktionsweise von Nachfolgerstrategien . . . . . . . . . . . . . . . 70<br />

5.4 Screenshot der FlowView . . . . . . . . . . . . . . . . . . . . . . . . 71<br />

5.5 Screenshot der FlowView . . . . . . . . . . . . . . . . . . . . . . . . 72<br />

5.6 Screenshot der ExecutionModelView . . . . . . . . . . . . . . . . . . 74<br />

iv


5.7 Screenshot der ExecutionModelView . . . . . . . . . . . . . . . . . . 74<br />

5.8 Das Geldautomatenbeispiel als Menge von Aktivitäten . . . . . . . . 76<br />

5.9 Metaklassen zur Modellierung von Aktivitäten . . . . . . . . . . . . . 77<br />

5.10 Screenshot einer Folge von Bildschirmmasken des TraceEditors . . . 80<br />

5.11 Screenshot der Darstellung zweier Traces in der SimulationView . . . 81<br />

5.12 ChoiceLogic-Schnittstelle . . . . . . . . . . . . . . . . . . . . . . 82<br />

5.13 Screenshot der <strong>Simulationsumgebung</strong> . . . . . . . . . . . . . . . . . 83<br />

v


Kapitel 1<br />

Einleitung<br />

Vor mehr als 20 Jahren hat Ivar Jacobson das Objectory-Prozessmodell vorgestellt<br />

[Jac87] und in diesem Zuge einen Ansatz zur Beschreibung von Systemverhalten in<br />

Form von Use Cases eingeführt.<br />

A use case is a prose description of a system’s behavior when interacting<br />

with the outside world.<br />

Mit diesem Satz beschreibt Alistair Cockburn in [Coc00] kurz und prägnant, was<br />

einen Anwendungsfall (engl. Use Case) ausmacht. Use Cases haben so schnell wie<br />

kein zweiter Ansatz zur Anforderungsspezifikation Einzug in die Welt des Software-<br />

Engineerings gehalten. Waren die Use Cases von Jacobson ursprünglich eine informelle<br />

„prose description“ eines Systems, hat das Konzept der Anwendungsfälle mittlerweile<br />

eine gewisse Formalisierung erfahren und ist heute Bestandteil der UML (Unified<br />

Modeling Language).<br />

Die Modellierung von Systemverhalten mit Hilfe von Anwendungsfällen wird aus einer<br />

Sicht heraus betrieben, in der die Interaktionen des zu beschreibenden Systems<br />

mit sogenannten Akteuren im Mittelpunkt stehen. Akteure sind Entitäten, in der Regel<br />

Personen oder Systeme, die sich außerhalb des Zielsystems befinden und durch ihre<br />

Interaktion mit dem System ein bestimmtes Ziel verfolgen oder sonst irgendwie von<br />

dieser Interaktion betroffen sind. Diese Betrachtungsweise resultiert in der Beschreibung<br />

eines Systems als Menge von Interaktionen mit der Außenwelt. Für diesen Grad<br />

der Modellierung spezifiziert die UML Elemente und Beziehungen zwischen diesen<br />

Elementen. Für eine detaillierte Beschreibung des Verhaltens der verschiedenen Interaktionen<br />

stellt die UML allerdings keinerlei Modellierungselemente zur Verfügung.<br />

Somit lässt die UML offen, wie das Verhalten, das von einem Use Case repräsentiert<br />

wird, unterhalb der Abstraktionsebene eines Anwendungsfalles verfeinert beschrieben<br />

werden soll. Auf dieser Ebene spezifiziert die UML lediglich, dass jeder Anwendungsfall<br />

eine Menge möglicher Verhaltenssequenzen beschreibt. Jede Verhaltenssequenz<br />

setzt sich dabei zusammen aus einer Folge atomarer Verhaltensschritte. Aus diesem<br />

1


Grund gibt es diverse Konzepte, um Use Case-Verhalten detailliert zu spezifizieren<br />

und die allgemein gehaltenen Begriffe der UML zu verfeinern. Ein Ansatz ist am Lehr<br />

und Forschungsgebiet der Informatik 3 an der RWTH Aachen im Rahmen einer Diplomarbeit<br />

entstanden [Wal07].<br />

In diesem Ansatz wurde eine <strong>strukturierte</strong> textbasierte Darstellungsform gewählt, um<br />

das Verhalten von Anwendungsfällen in natürlicher Sprache zu beschreiben. Begründet<br />

wurde die Entscheidung <strong>für</strong> diese Form damit, dass eine textbasierte Beschreibung<br />

einem Anwender größtmöglichen Nutzen und Flexibilität bietet. Dieser Ansatz wurde<br />

im NarrativeModel formalisiert. Das NarrativeModel ist ein Metamodell und stellt<br />

Konzepte und Elemente zur Modellierung natürlichsprachlicher Beschreibungen von<br />

Use Cases zur Verfügung. Damit liegt einer textuellen Anwendungsfallbeschreibung<br />

ein Modell zugrunde, ebenso wie einem Use Case-Modell das UML-Metamodell zugrunde<br />

liegt. Aus dem Einsatz eines Metamodells folgen all die Vorteile, die einem<br />

<strong>strukturierte</strong>n und formalen Ansatz innewohnen. Dazu gehört beispielsweise die automatische<br />

Prüfung des Modells bezüglich bestimmter Gesichtspunkte wie Konsistenz<br />

mit Hilfe von Randbedingungen, die im Metamodell formuliert sind. Obwohl<br />

das NarrativeModel eine Struktur <strong>für</strong> die textuelle Beschreibung von Use Cases vorgibt,<br />

schränkt es die Ausdrucksweise des Modellierers nicht zu stark ein, da es den<br />

Einsatz natürlicher Sprache zur Beschreibung bestimmter Verhaltenselemente zulässt.<br />

Dem hier gewählten Ansatz liegt eine flussorientierte Sicht auf das Verhalten eines Use<br />

Cases zugrunde.<br />

Laut UML kapselt ein Anwendungsfall Verhaltenssequenzen, die jeweils als Folge einzelner<br />

Verhaltensatome zusammengesetzt sind. Die Verhaltenssequenzen werden im<br />

NarrativeModel in Form von Flüssen beschrieben, die Verhaltensatome in Form von<br />

Aktionen. Jede natürlichsprachliche Beschreibung beinhaltet ein oder mehrere Flüsse.<br />

Jeder Fluss besteht aus einer Folge von Aktionen, die in natürlicher Sprache spezifiziert<br />

werden. Zwischen Flüssen können, ebenso wie zwischen Anwendungsfällen,<br />

Inklusions- und Erweiterungsbeziehungen definiert werden. Für diesen Zweck gibt es<br />

neben den Aktionen ausgezeichnete Stellen in einem Fluss, an denen die Beziehungen<br />

ansetzen. Dieses Vorgehen orientiert sich an den vorhandenen UML-Mechanismen,<br />

wie beispielsweise den Erweiterungspunkten in einem Use Case, an denen Verhalten<br />

eines anderen Anwendungsfalles mittels Erweiterung eingefügt werden kann.<br />

Auf Grundlage der Ergebnisse von [Wal07] soll in dieser Arbeit ein Werkzeug entwickelt<br />

werden, um die Ausführung von Anwendungsfällen, bzw. ihrer textuellen Beschreibungen,<br />

zu simulieren. In der Folge wird dieses Werkzeug als <strong>Simulationsumgebung</strong><br />

bezeichnet. Die Simulation eines Use Cases bedeutet anschaulich, dass einzelne<br />

Szenarien „durchgespielt“ werden. Ein Szenario ist eine individuelle Use Case Instanz,<br />

also ein spezieller Pfad (eine spezielle Verhaltenssequenz) durch einen Anwendungsfall.<br />

In dem Fall, dass ein Use Case eine Menge von Verhaltensalternativen beinhaltet,<br />

ist ein Szenario genau eine mögliche Verhaltensausprägung vom Start des Anwendungsfalles,<br />

der durch eine Aktion eines Akteurs ausgelöst wird, bis hin zu seinem<br />

Ende.<br />

2


1.1 Zielsetzung<br />

Die simulierte Ausführung von Anwendungsfällen soll der Validierung der in Use Cases<br />

und textuellen Beschreibungen festgehaltenen Anforderungen dienen und nachgelagerte<br />

Analysetätigkeiten unterstützen. Zur Validierung der Anforderungen gehören<br />

Prüfungen auf Vollständigkeit und Korrektheit. Die Simulation soll Anhaltspunkte <strong>für</strong><br />

diese Prüfungen liefern. Beispielsweise kann im Verlauf der Simulation festgestellt<br />

werden, dass gewisse Alternativabläufe in der Verhaltensbeschreibung eines Anwendungsfalles<br />

fehlen. Die simulierte Ausführung kann außerdem Schwachpunkte in der<br />

Anforderungsbeschreibung des Zielsystems aufzeigen. Dies können beispielsweise inkorrekt<br />

formulierte Sachverhalte oder nur ungenügend beschriebene Aktionen sein.<br />

Stößt ein Entwickler zu einem Entwicklungsteam hinzu, kann er die Ausführung der<br />

existierenden Anwendungsfälle simulieren, um sich mit den Abläufen und Anforderungen<br />

des Zielsystems vertraut zu machen und ein generelles Systemverständnis zu<br />

entwickeln.<br />

Mittels bestimmter Artefakte, die im Zuge der Simulationsdurchführung entstehen,<br />

können idealerweise Erkenntnisse über die Qualität der aufgenommenen Anforderungen<br />

gewonnen werden und im Rahmen des Projektmanagements weiterverarbeitet<br />

werden. Als Artefakt ist hier beispielsweise eine Modellinstanz denkbar, die eine<br />

ausführungsorientierte Sicht auf die zugrundeliegende Anwendungsfallbeschreibung<br />

bietet und auf deren Grundlage die Simulation durchgeführt wird. Über den Einsatz<br />

geeigneter Metriken, die dieses Modell bezüglich spezieller Gesichtspunkte und Eigenschaften<br />

bewerten, sind Rückschlüsse auf die Qualität der Anforderungen möglich.<br />

<strong>Eine</strong> Textdarstellung der im Laufe der Simulation durchgespielten Szenarien kann<br />

möglicherweise als Ausgangspunkt <strong>für</strong> die Klärung offener Fragen und Probleme im<br />

Rahmen eines Kundengesprächs dienen.<br />

Im Bereich eingebetteter Systeme ist der Einsatz der Simulation <strong>für</strong> frühe Machbarkeitsstudien<br />

denkbar. Das Problem in diesem Bereich ist häufig, dass nur begrenzte<br />

Hardwareressourcen <strong>für</strong> die Realisierung des Zielsystems zur Verfügung stehen. Um<br />

frühzeitig die Umsetzbarkeit der Anforderungen bezüglich der vorhandenen Ressourcen<br />

zu evaluieren, ließen sich einzelne Schritte der Simulationsausführung mit geschätzten<br />

Zusatzinformationen, den Ressourcenverbrauch betreffend, annotieren. Die<br />

Simulation selbst gibt dann Aufschluss darüber, ob die Planung auch tatsächlich umsetzbar<br />

ist.<br />

Unabhängig von diesen fachlichen Zielsetzungen soll die <strong>Simulationsumgebung</strong> außerdem<br />

gewissen anderen Anforderungen genügen. Zu diesen gehört, dass dem Benutzer<br />

eine anschauliche graphische Visualisierung des möglichen Simulationsablaufs<br />

zur Verfügung gestellt wird. Diese Darstellung dient idealerweise gleichsam zur Veranschaulichung<br />

der zugrundeliegenden textuellen Beschreibung. Außerdem soll die<br />

<strong>Simulationsumgebung</strong> in die ebenfalls am Lehrstuhl entstandene Eclipse Rich Client<br />

Plattform integriert werden. Daraus folgt, dass sich die Umsetzung der <strong>Simulationsumgebung</strong><br />

an den Eclipse UI-Paradigmen zur Entwicklung graphischer Benutzeroberflächen<br />

orientiert.<br />

3


1.2 Aufbau der Arbeit<br />

Die Arbeit ist wie folgt gegliedert: Zunächst werden in Kapitel 2 die theoretischen<br />

Grundlagen <strong>für</strong> das weitere Verständnis gelegt. Dazu gehören eine kurze Abhandlung<br />

über die hier relevanten Spracheinheiten der UML und eine ausführliche Beschreibung<br />

des Metamodells <strong>für</strong> <strong>strukturierte</strong> natürlichsprachliche Beschreibungen von Anwendungsfällen.<br />

Das Kapitel wird abgeschlossen mit einem Beispiel, welches die Anforderungsmodellierung<br />

eines Geldautomaten mittels des vorgestellten Metamodells<br />

illustriert.<br />

Das dritte Kapitel beschäftigt sich mit den technischen Grundlagen, auf deren Basis die<br />

technische Realisierung dieser Arbeit stattgefunden hat. Zuerst werden hierzu die Architektur<br />

der Eclipse-Plattform thematisiert und danach die <strong>für</strong> diese Arbeit relevanten<br />

Eclipse-Technologien eingeführt. Den Abschluss des Kapitels bilden die Vorstellung<br />

der ViPER-IDE und ihrer Komponenten.<br />

In Kapitel 4 wird der konzeptuelle Lösungsansatz, der der Realisierung der <strong>Simulationsumgebung</strong><br />

zugrunde liegt, vorgestellt. Da<strong>für</strong> wird zunächst die Modellbildung<br />

eines eigenen Metamodells zur Kapselung von Ausführungskonzepten motiviert und<br />

dieses Metamodell anschließend ausführlich erklärt.<br />

Das fünfte Kapitel erläutert die technische Realisierung der <strong>Simulationsumgebung</strong>.<br />

Die <strong>Simulationsumgebung</strong> besteht aus einer Menge graphischer Komponenten, die in<br />

diesem Kapitel der Reihe nach vorgestellt werden. Am Ende des Kapitels wird die Integration<br />

der Einzelkomponenten, die in ihrer Summe die <strong>Simulationsumgebung</strong> ausmachen,<br />

beschrieben.<br />

Inhalt des sechsten Kapitels ist die Evaluierung der erarbeiteten Lösung. Dabei wird<br />

die Qualität der <strong>Simulationsumgebung</strong> mit Blick auf die oben formulierten Zielsetzungen<br />

untersucht.<br />

Das siebte Kapitel bildet den Abschluss dieser Arbeit und fasst die Ergebnisse zusammen.<br />

Darüber hinaus wird ein Ausblick auf mögliche zukünftige Arbeiten geboten.<br />

4


Kapitel 2<br />

Theoretische Grundlagen<br />

Dieses Kapitel legt den theoretischen Grundstein <strong>für</strong> das Verständnis der konzeptuellen<br />

Realisierung der <strong>Simulationsumgebung</strong>. Zunächst erfolgt ein kurzer Überblick über<br />

die UML und ihr Metamodell. Im Anschluss wird das Metamodell <strong>für</strong> textbasierte Anwendungsfallbeschreibungen<br />

ausführlich vorgestellt. Abgeschlossen wird das Kapitel<br />

mit einem Beispiel, welches die Modellierung natürlichsprachlicher Beschreibungen<br />

am Beispiel eines Geldautomaten illustriert.<br />

2.1 UML<br />

Die UML (Unified Modeling Language) ist eine von der OMG (Object Management<br />

Group) standardisierte Beschreibungssprache [UML, OMG]. Zu ihren Anwendungsbereichen<br />

gehört die Beschreibung von Strukturen, Verhalten und Architekturen, sowie<br />

von Geschäftsprozessen und Datenbanken. Die UML findet hauptsächlich Anwendung<br />

im Gebiet des Software-Engineerings. Dort wird sie eingesetzt, um statische Strukturen<br />

und dynamische Abläufe eines Softwaresystems deskriptiv oder auch präskriptiv<br />

festzuhalten [LL06].<br />

Der UML zugrunde liegt ein Metamodell, welches Begriffe und Beziehungen zwischen<br />

diesen Begriffen festlegt. Mittels dieser Elemente werden Systemmodelle spezifiziert.<br />

Darüber hinaus definiert die UML graphische Notationen <strong>für</strong> ihre verschiedenen<br />

Metamodellelemente.<br />

Da die UML in ihrem Umfang seit Version 1.0 stark gewachsen ist, besteht die UML2<br />

-Spezifikation aus drei Teilspezifikationen. Diese Dreiteilung reduziert Komplexität<br />

und erleichtert den Umgang mit der Spezifikation während der Entwicklung. Für den<br />

Anwender ist die Spezifikation durch ihre Zerlegung besser lesbar und einfacher verständlich.<br />

Die drei Spezifikationen, die in ihrer Gesamtheit die UML2-Spezifikation<br />

ausmachen, werden im Folgenden kurz vorgestellt. Darüber hinaus ist außerdem ein<br />

Standard zum Informationsaustausch von Diagramminformationen definiert.<br />

5


• UML Infrastructure ([Obj07a]): Die Infrastructure legt, wie ihr Name bereits<br />

andeutet, das Fundament <strong>für</strong> die UML2. Sie beinhaltet einen wiederverwendbaren<br />

Kernel, der als Basis <strong>für</strong> die Entwicklung weiterer Metamodelle dient. Er<br />

umfasst Sprachkonstrukte in Form grundlegender Metamodellelemente. Zu diesen<br />

gehören beispielsweise die Elemente Paket, Klasse, Multiplizität und Assoziation.<br />

Mittels dieser Elemente können spezielle Konstrukte in den jeweiligen<br />

Metamodellen formuliert werden. Ein derartiges Metamodell, welches auf den<br />

Konzepten des Kernels aufsetzt, ist die Superstructure.<br />

• UML Superstructure ([Obj07b]): Die Superstructure ist der zweite Teil der<br />

UML2-Spezifikation und beinhaltet Sprachelemente, die auf denen der Infrastructure<br />

aufbauen. Während die Infrastructure hauptsächlich als Basis <strong>für</strong> die<br />

Entwicklung auf ihr aufsetzender Metamodelle dient, stellt die Superstructure<br />

einem Anwender Konzepte zur Verfügung, die dieser zur Modellierung einsetzt.<br />

Intern ist die Superstructure modular aufgebaut. Sie ist unterteilt in sogenannte<br />

Spracheinheiten, die die Superstructure nach Struktur und Verhalten aufteilen.<br />

Die Spracheinheit Activities umfasst beispielsweise Elemente <strong>für</strong> die Modellierung<br />

von Systemverhalten, das sich am besten mit Hilfe des Formalismus von<br />

Daten- und Kontrollflüssen darstellen lässt. Weitere Spracheinheiten sind Interactions,<br />

State Machines oder Use Cases, die zur Verhaltensmodellierung eingesetzt<br />

werden. Die Spracheinheiten Classes und Composite Structures dienen der<br />

Modellierung von Strukturen.<br />

• Object Constraint Language ([Obj03a]): Die OCL ist eine formale Sprache, die<br />

der Spezifikation von Randbedingungen in einem Metamodell dient. Dazu gehören<br />

etwa Spezifikation von Invarianten in Klassendiagrammen, von Bedingungen<br />

in Sequenzdiagrammen oder die Formulierung von Vor- und Nachbedingungen<br />

<strong>für</strong> Methoden. Außerdem können mittels OCL Suchanfragen (Queries)<br />

über ein Modell gestellt werden. Die Auswertung der formulierten Ausdrücke<br />

ist frei von Seiteneffekten und kann den Zustand eines Modells nicht ändern.<br />

Diese Eigenschaft entspricht generell der Semantik einer Spezifikationssprache.<br />

• Diagram Interchange [DI06]: Die Superstructure legt mittels ihrer Spracheinheiten<br />

Diagrammtypen fest, die in der Praxis zur Modellierung von Systemen eingesetzt<br />

werden. Dazu gehören einerseits Metamodellelemente und andererseits<br />

die graphische Repräsentation dieser Elemente. Damit unterschiedliche Modellierungswerkzeuge<br />

untereinander Diagramme austauschen und weiterverarbeiten<br />

können, schreibt das Diagram Interchange eine standardisierte Serialisierung<br />

von Diagrammen vor. Sie legt fest, wie Diagramminformationen persistent abgelegt<br />

werden.<br />

2.1.1 Spracheinheiten<br />

Im Rahmen dieser Arbeit sind einige Spracheinheiten der UML-Superstructure von<br />

besonderem Interesse. Dazu gehören Klassendiagramme, die im Zuge der Metamodellierung<br />

der theoretischen Grundlagen dieser Arbeit eingesetzt wurden, ebenso wie<br />

6


die Spracheinheit der Use Cases, die den Ausgangspunkt <strong>für</strong> den Ansatz der natürlichsprachlichen<br />

Anwendungsfallbeschreibungen legt. Im Laufe der Simulation dieser textuellen<br />

Beschreibungen werden Aktivitätsdiagramme eingesetzt, weil diese sich sehr<br />

gut zur Visualisierung von Verhaltensabläufen, Auswahlmöglichkeiten und Verzweigungen<br />

eignen.<br />

Classes<br />

Die Spracheinheit Classes ist die gebräuchlichste und bekannteste Spracheinheit der<br />

UML. Sie umfasst den eigentlichen Kern der Modellierungssprache und definiert den<br />

Klassenbegriff und die verschiedenen Beziehungen zwischen Klassen. Dabei setzt sie<br />

auf dem abstrakten Classifier-Begriff der Infrastructure auf und konkretisiert diesen.<br />

Ein Classifier ist eine abstrakte Metaklasse, die eine Klassifikation mehrerer Instanzen<br />

bezüglich bestimmter Eigenschaften darstellt. Ein Classifier beschreibt also eine Menge<br />

von Instanzen bezüglich ihrer Gemeinsamkeiten. Klassen und Schnittstellen sind<br />

konkrete derartige Classifier und werden in der Superstructure als Teil der Spracheinheit<br />

Classes definiert. Des Weiteren stellt die Superstructure spezielle Beziehungen<br />

zwischen den verschiedenen Konzepten der Spracheinheit zur Modellierung zur Verfügung.<br />

Dazu gehören beispielsweise Aggregations- und Kompositionsbeziehungen.<br />

Elemente dieser Spracheinheit werden üblicherweise in Klassendiagrammen, Objektdiagrammen<br />

und Paketdiagrammen dargestellt.<br />

Use Cases<br />

Die Elemente der Spracheinheit Use Cases dienen der Modellierung von Anforderungen<br />

an ein System. Die wichtigsten Elemente hierbei sind Anwendungsfälle. Jeder<br />

Anwendungsfall beschreibt eine Anforderung an das zu modellierende System. Die<br />

Use Case Modellierung basiert auf einer Vorgehensweise, die die Interaktion externer<br />

Entitäten mit dem System in den Mittelpunkt rückt und daraus Anforderungen ableitet.<br />

Ein Use Case kapselt Verhalten im Sinne einer Black Box, welches im Rahmen einer<br />

Interaktion ein Resultat <strong>für</strong> ein oder mehrere externe Entitäten generiert. Diese externen<br />

Entitäten, die das Systemverhalten anstoßen und von seinen Resultaten abhängig<br />

sind, nennt man Akteure. Üblicherweise wird ein Anwendungsfall aus Sicht eines Akteurs<br />

beschrieben. Akteure spezifizieren, wer (im Sinne einer Person) oder was (im<br />

Sinne eines anderen Systems) im Rahmen der Ausführung des aktuellen Use Cases<br />

mit dem modellierten System interagiert. Kommt ein Anwendungsfall im System zur<br />

Ausführung, muss er ein beobachtbares Resultat, das <strong>für</strong> einen oder mehrere Akteure<br />

von Bedeutung ist, generieren. Sowohl Anwendungsfälle als auch Akteure sind spezielle<br />

Classifier. Außer diesen Entitäten stellt die Superstructure in dieser Spracheinheit<br />

Beziehungen zwischen Anwendungsfällen und Akteuren zur Verfügung. Dies umfasst<br />

Generalisierungsbeziehungen zwischen je zwei Akteuren oder Anwendungsfällen,<br />

eine binäre Assoziationsbeziehung zwischen je einem Use Case und Akteur, sowie<br />

Inklusions- und Erweiterungsbeziehungen zwischen Anwendungsfällen. Letztere<br />

7


dienen der Wiederverwendung des Verhaltens, das in einem Use Case gekapselt ist 1 .<br />

Graphisch werden Anwendungsfälle in Anwendungsfalldiagrammen dargestellt.<br />

Activities<br />

Das zentrale Element der Spracheinheit Activities ist das Element Aktivität selbst. <strong>Eine</strong><br />

Aktivität dient der Modellierung des dynamischen Verhaltensablaufs eines Systems.<br />

Sie beschreibt das Verhalten des Systems in Form einer Sequenz elementarer Aktionen.<br />

Aktionen sind Teil einer eigenen Spracheinheit (Actions) und stellen die elementaren<br />

Bausteine <strong>für</strong> die Modellierung eines Verhaltensablaufs in der UML dar. Aktionen<br />

können Eingabewerte entgegennehmen und Ausgabewerte erzeugen. Aktionen sind in<br />

einer Aktivität über Kanten gekoppelt, die den Kontrollflussverlauf von einer Aktion<br />

zur anderen symbolisieren. In diesem Sinne hat eine Aktivität die Struktur eines Graphen<br />

mit Knoten und Kanten. Außer den Aktionen gibt es noch weitere Arten von<br />

Knoten. Beispielsweise gibt es sogenannte Kontrollknoten, an denen der Kontrollfluss<br />

in der Aktivität kontrolliert bzw. gesteuert werden kann. An einem Entscheidungsknoten<br />

(DecisionNode) verzweigt sich der Kontrollfluss, an einem MergeNode laufen<br />

verschiedene Kontrollflüsse zusammen. Den Knoten entsprechend gibt es verschiedene<br />

Arten von Kanten, die ja nach Typ verschiedene Knotenarten miteinander verbinden<br />

können. Komplexere Aktivitäten können verschachtelt und mit Kontrollstrukturen<br />

modularisiert werden. Graphisch dargestellt werden Aktivitäten in einem Aktivitätsdiagramm.<br />

Auf die <strong>für</strong> diese Arbeit relevanten Elemente dieser Spracheinheit wird in<br />

Abschnitt 5.3 noch ausführlicher eingegangen.<br />

Profile<br />

Die UML Infrastructure [Obj07a] stellt einen generischen Erweiterungsmechanismus<br />

durch sogenannte Profile zur Verfügung. Profile werden im Zuge der Implementierung<br />

eines Teils dieser Arbeit verwendet (vgl. Abschnitt 5.3).<br />

Ein Profil beinhaltet eine Menge von Stereotypen, die zusammen ein bestimmtes Modellierungsproblem<br />

beschreiben und somit die Modellierung in einer spezifischen Domäne<br />

ermöglichen. Im Allgemeinen erweitern Stereotypen das Vokabular der UML<br />

um neue Elemente, die von existierenden Elementen abgeleitet werden und diese um<br />

domänenspezifische Eigenschaften erweitern. Sie werden benutzt, um Bausteine der<br />

UML zu klassifizieren bzw. speziell auszuzeichnen, und um neue Bausteine <strong>für</strong> eine<br />

bestimmte Domäne zu gewinnen. Anschaulich gesprochen dient ein Stereotyp der<br />

Spezialisierung einer Elementinstanz zur Laufzeit.<br />

Der Profilmechanismus ist leichtgewichtig in dem Sinne, dass das UML-Metamodell<br />

unverändert bleibt. Stereotypen können auf Elemente, Attribute, Methoden, Assoziationen<br />

und Assoziationsenden angewendet werden.<br />

1 Genaugenommen werden Verhaltensbeschreibungen wiederverwendet.<br />

8


2.2 NarrativeModel<br />

2.2.1 Motivation und Ziel<br />

Das NarrativeModel ist ein Metamodell <strong>für</strong> textbasierte Anwendungsfallbeschreibungen.<br />

Es dient der Modellierung der internen Struktur eines Use Cases und der Beschreibung<br />

seines Verhaltens in natürlicher Sprache. Die UML definiert einen Standard,<br />

der Konzepte und Elemente vorgibt, um eine System mittels einer Menge von<br />

Anwendungsfällen und ihrer Beziehungen untereinander zu modellieren. Die UML-<br />

Spezifikation macht allerdings keine Aussage über die Form der detaillierten Beschreibungen<br />

des Verhaltens einzelner Use Cases. Hier<strong>für</strong> gibt es diverse Ansätze und Notationen,<br />

aus denen sich allerdings kein Standard herausgebildet hat.<br />

Als ein solcher Ansatz zur detaillierten Beschreibung von Anwendungsfällen ist das<br />

NarrativeModel-Metamodell im Rahmen einer früheren Diplomarbeit am Lehr- und<br />

Forschungsgebiet Informatik 3 an der RWTH Aachen entstanden [Wal07]. Der Modellbildung<br />

zugrunde lag die informelle Notation <strong>für</strong> die natürlichsprachliche Beschreibung<br />

von Anwendungsfällen, die Bittner und Spence in ihrem Buch vorgestellt haben<br />

[BS02]. Seitdem hat das NarrativeModel allerdings einige Veränderungen erfahren und<br />

wird deswegen an dieser Stelle noch einmal ausführlich vorgestellt.<br />

Dem NarrativeModel-Ansatz liegt eine flussorientierte Sicht auf die Ausführung von<br />

Anwendungsfällen zugrunde. Jeder Anwendungsfall beschreibt ein oder mehrere Szenarien,<br />

die durch seine konkreten Verhaltensausprägungen zustande kommen. Die Ausführung<br />

eines Use Cases resultiert im Hinblick auf das durchgeführte Verhalten in<br />

einem konkreten Szenario. Ziel des NarrativeModel-Ansatzes ist die <strong>strukturierte</strong> Beschreibung<br />

aller möglicher Verhaltensausprägungen in natürlicher Sprache. Praktisch<br />

geschieht dies, indem man die interne Use Case-Struktur mit den Elementen, die das<br />

NarrativeModel zur Verfügung stellt, modelliert und dabei an bestimmten Stellen die<br />

natürliche Sprache zur Beschreibung von Verhalten einsetzt.<br />

<strong>Eine</strong> Instanz eines Use Case-Modells besteht aus einer Menge von Instanzen von Metaklassen<br />

des UML-Metamodells. Im NarrativeModel gibt es Metaklassen, welche bestimmte<br />

UML-Metaklassen der Use Case-Spracheinheit referenzieren. Das dient der<br />

Sicherstellung der Konsistenz zwischen beiden Modellen. Auf diese Weise wird gewährleistet,<br />

dass es zu bestimmten Elementen des Use Case-Modells eine detaillierte<br />

Beschreibung dieser Elemente im NarrativeModel gibt. In diesen Fällen gibt es gerichtete<br />

1:1 Beziehungen vom NarrativeModel in das UML-Modell. Derartig repräsentierte<br />

Metaklassen sind beispielsweise UseCase, ExtensionPoint, Include und<br />

Actor. Bei der Konzipierung des NarrativeModels wurden unterschiedliche Ansätze<br />

der Integration mit dem zu beschreibenden Use Case-Modell erwogen [Wal07].<br />

Letzen Endes wurde der Ansatz gewählt, das NarrativeModel als Erweiterung des Use<br />

Case-Modells zu modellieren und bestimmte Elemente des Use Case-Modells aus dem<br />

NarrativeModel heraus zu referenzieren.<br />

Der Verhaltensbeschreibung eines Anwendungsfalles zugrunde liegt in aller Regel die<br />

9


Vorstellung, dass jeder Anwendungsfall einen Standardablauf und mögliche Alternativabläufe<br />

besitzt. Der Standardablauf stellt den Normalfall des Use Cases in Form einer<br />

Verhaltenssequenz, die wiederum aus einzelnen Verhaltenssegmenten besteht, dar.<br />

Dieser Standardablauf ist also ein Szenario, welches Teil aller Verhaltensausprägungen<br />

des Anwendungsfalles ist. Die Verhaltenssegmente beschreiben atomares Verhalten in<br />

natürlicher Sprache (in diesem Fall spricht man von Verhaltensatomen) oder dienen<br />

dem bedingten oder unbedingten Einfügen anderer Verhaltenssequenzen an wohl definierten<br />

Stellen des Verhaltensablaufs. Verhalten welches bedingt, also an eine Bedingung<br />

gekoppelt, zur Ausführung kommt, heißt Alternativverhalten. Das bedingte und<br />

unbedingte Einfügen von Verhalten wird in der UML-Notation durch Erweiterungen<br />

und Inklusionen modelliert. Standardablauf in Kombination mit Alternativen spannen<br />

den Zustandsraum <strong>für</strong> Szenarien auf.<br />

Die Begriffe der Verhaltenssequenzen und Verhaltenssegmente stammen aus der Spezifikation<br />

der UML. Im Vorgriff auf die folgenden Ausführungen sei an dieser Stelle<br />

bereits erwähnt, dass die Verhaltenssequenzen von Anwendungsfällen im Narrative-<br />

Model durch Flüsse dargestellt werden und die Verhaltenssegmente durch Ereignisse.<br />

2.2.2 Das Metamodell<br />

Abbildung 2.1: Grobe Struktur des NarrativeModels<br />

Abbildung 2.1 gibt einen Überblick über die Metaklassen des NarrativeModels, die<br />

dessen grobe Struktur ausmachen. Insbesondere dienen diese Metaklassen der Spiegelung<br />

der Kompositionshierarchie eines Use Case-Modells in einem NarrativeModel.<br />

Ein UML-Model ist üblicherweise als Kompositionshierarchie strukturiert, in der jedes<br />

Element Teil eines anderen Elements ist. Das Wurzelelement, welches in der Regel<br />

ein Model-Element ist, bildet hierbei die Ausnahme und ist nicht Kind eines anderen<br />

Elements. Dieses Wurzelelement ist in einem NarrativeModel eine Instanz der Meta-<br />

10


klasse NarrativeModel. Diese NarrativeModel-Instanz referenziert das durch sie<br />

beschriebene Use Case-Modell.<br />

In der UML gibt es außerdem noch andere Elemente, die der hierarchischen Komposition<br />

dienen. Im Rahmen der Modellierung eines Use Case-Modells werden die<br />

UML-Konzepte Package und Component eingesetzt, um logisch zusammenhängende<br />

Elemente zu gruppieren. Um die mittels Verschachtelung dieser Elemente gebildete<br />

Kompositionsstruktur nachzubilden, besitzt das NarrativeModel das Konzept des<br />

NarrativeContainers. NarrativeContainer-Instanzen lassen sich beliebig<br />

ineinander schachteln. Als Wurzel einer NarrativeContainer-Hierarchie dient eine<br />

Instanz der NarrativeModel-Metaklasse.<br />

Als weitere Kinder eines NarrativeContainers kommen neben anderen NarrativeContainern<br />

noch Instanzen der Metaklassen NarrativeActor und NarrativeDescription<br />

in Frage. NarrativeDescription und NarrativeActor dienen<br />

der natürlichsprachlichen Beschreibung von UseCase-Instanzen einerseits und<br />

Actor-Instanzen andererseits. Die UML-Elemente werden jeweils durch eine Verfeinerung<br />

der umlNamespace-Assoziation von den sie repräsentierenden NarrativeModel-<br />

Elementen referenziert.<br />

An dieser Stelle sieht man, dass Konsistenz zwischen Use Case-Modell und NarrativeModel-Modell<br />

sichergestellt werden muss. Zu jeder UseCase-Instanz muss es<br />

tatsächlich auch eine NarrativeDescription-Instanz geben. Außerdem müssen<br />

noch andere als die bisher vorgestellten Elemente eines Use Case-Modells in einem<br />

NarrativeModel-Modell abgebildet werden. Beispielsweise müssen sich externe Erweiterungspunkte,<br />

sowie Erweiterungs- und Inklusionsbeziehungen in der Narrative-<br />

Model-Instanz durch entsprechende Elemente repräsentiert wiederfinden.<br />

2.2.3 Flüsse<br />

Die Semantik der UML <strong>für</strong> Use Cases besagt, dass jeder Use Case eine Menge von<br />

Verhaltenssequenzen beinhaltet. Sie macht darüber hinaus aber keine Aussage über<br />

deren Struktur [Obj07b]. Der Begriff des Verhaltenssequenz muss also im Rahmen<br />

einer detaillierten Anwendungsfallbeschreibung konkretisiert werden.<br />

Hier<strong>für</strong> gibt es im NarrativeModel das Konzept der Flüsse (Metaklasse Flow). Ein<br />

Fluss beschreibt eine solche Verhaltenssequenz als eine Folge einzelner Ereignisse.<br />

Die Ereignisse entsprechen dabei den Verhaltenssegmenten der UML und werden<br />

durch die Metaklasse Event dargestellt. Ereignisse werden ausführlich in Abschnitt<br />

2.2.4 behandelt.<br />

<strong>Eine</strong> textbasierte Beschreibung beinhaltet ein oder mehrere Flüsse, die untereinander<br />

in Beziehung stehen können und somit die interne Struktur eines Use Cases ausmachen.<br />

Als mögliche Beziehungen gibt es hier analog zu den Beziehungen zwischen<br />

Use Cases die Inklusions- und Erweiterungsbeziehung sowie die Generalisierungsbeziehung.<br />

Darüber hinaus gibt es noch das Konzept der Ausnahmeflüsse. Ein Ausnah-<br />

11


mefluss kapselt Verhalten zur Ausnahmebehandlung, welches jederzeit als Reaktion<br />

auf eine Ausnahmesituation in einem anderen Fluss zur Ausführung kommen kann.<br />

Abbildung 2.2: Feine Struktur der Verhaltenselemente<br />

Abbildung 2.2 illustriert den Zusammenhang zwischen NarrativeDescriptions nochmals<br />

in graphischer Form. Es gibt zwei verschiedene Assoziationen zwischen NarrativeDescription<br />

und Flow. Über die Kompositionsbeziehung besitzt jede<br />

NarrativeDescription eine Menge von Flüssen, nämlich diejenigen, die auch tatsächlich<br />

in der jeweiligen NarrativeDescription definiert oder redefiniert werden. Die gerichtete<br />

Beziehung von NarrativeDescription zu Flow ist eine Aggregation<br />

über die Vererbungshierarchie der jeweiligen NarrativeDescription und beinhaltet neben<br />

den lokal definierten Flüssen auch diejenigen, die von einer generelleren NarrativeDescription<br />

geerbt wurden, ohne lokal redefiniert zu werden (<strong>für</strong> eine detaillierte<br />

Beschreibung der Generalisierungsbeziehung vgl. Abschnitt 2.2.6).<br />

2.2.4 Ereignisse in Flüssen<br />

Flüsse sind Verhaltenssequenzen und bestehen aus einer Folge von Verhaltenssegmenten.<br />

Im Sinne der Ausführung ereignen sich diese Verhaltenssegmente an einem Stück.<br />

Ein Verhaltenssegment findet seine Entsprechung im NarrativeModel in Form eines<br />

Ereignisses (abstrakte Metaklasse Event). Ein Fluss besteht aus einer diskreten Sequenz<br />

von Ereignissen.<br />

Auch dieser Zusammenhang ist in Abbildung 2.2 zu sehen. Analog zu den Beziehungen<br />

zwischen NarrativeDescription und Flow wird auch zwischen Flow und<br />

Event einerseits unterschieden nach innerhalb des konkreten Flusses definierten Ereignissen<br />

und geerbten Verhaltensbausteinen andererseits.<br />

Die Metaklasse Event ist abstrakt. Das NarrativeModel kennt verschiedene Arten<br />

von Spezialisierungen des Ereignis-Begriffs. Zum einen gibt es Ereignisse, die aus<br />

Sicht des Flusses, deren Teil sie sind, atomares Verhalten darstellen. Ein derartiges<br />

Ereignis heißt Aktion (Metaklasse Action) und wird vom Modellierer in natürlicher<br />

Sprache beschrieben. Die Beschreibung an sich hat aus Sicht des Metamodells keine<br />

Semantik.<br />

Außerdem gibt es Ereignisarten, die der Definition potentieller Kontrollflussverlagerungen<br />

(abstrakte Metaklasse ControlEvent) im Fluss dienen. Das sind ausgezeichnete<br />

Positionen im Fluss, an denen Verhalten anderer Flüsse bedingt (Erweiterung)<br />

oder unbedingt (Inklusion) zur Ausführung kommt. Aus Sicht des Ereignisses<br />

ändert sich an dieser Stelle möglicherweise der aktuelle Kontext (das Kontextkonzept<br />

12


wird im folgenden Abschnitt 2.2.5 ausführlich vorgestellt). Das passiert genau dann,<br />

wenn der Kontrollfluss den bisher aktuellen Fluss (möglicherweise nur vorübergehend)<br />

verlässt und sich in einen anderen Fluss verlagert.<br />

Abbildung 2.3: Typhierarchie der abstrakten Event-Metaklasse<br />

Abbildung 2.3 gibt einen Überblick über die verschiedenen Ereignisarten. Man erkennt<br />

die Verfeinerung des abstrakten Event-Konzepts zu dem abstrakten ControlEvent-<br />

Begriff einerseits und der konkreten Metaklasse Action andererseits. Control-<br />

Event wird dabei noch weiter unterteilt in Inclusion und ExtensionAnchor,<br />

bei denen wiederum noch unterschieden wird zwischen internen und externen Ereignissen<br />

dieser Art. Der genaue Verwendungszweck dieser Typen wird erläutert im Abschnitt<br />

2.2.6, der sich mit der Darstellung von Inklusions- und Erweiterungsbeziehungen<br />

im Modell beschäftigt.<br />

2.2.5 Flüsse und Kontexte<br />

Jeder Fluss hat einen oder mehrere Kontexte (Metaklasse Context), die bestimmen,<br />

auf welche Arten und Weisen ein Fluss verwendet werden kann. Beispielsweise besitzt<br />

ein Fluss, der nur dazu geeignet ist, über eine Erweiterungsbeziehung zusätzliches<br />

Verhalten <strong>für</strong> andere Flüsse zur Verfügung zu stellen und demnach nicht <strong>für</strong> sich alleine<br />

genommen ausführbares Verhalten darstellt, einen dementsprechenden Kontext. Stellt<br />

ein Fluss einen Standardablauf dar, hat er ebenfalls einen bestimmten Kontext, der<br />

aussagt, dass der Fluss über einen Akteur angestoßen werden kann.<br />

Abbildung 2.4 stellt die Typhierarchie der Context-Metaklasse vor. Es gibt zwei<br />

Spezialisierungen, die <strong>für</strong> einen Fluss mit derartigen Kontexten zur Folge haben, dass<br />

er über Inklusion oder Erweiterung aus einem anderen Fluss heraus zur Ausführung<br />

13


Abbildung 2.4: Typhierarchie der abstrakten Context-Metaklasse<br />

kommen kann (Metaklassen ExtensionContext und InclusionContext).<br />

Diese beiden Kontextkonzepte werden im Rahmen der Beschreibungen der Inklusionsund<br />

Erweiterungsbeziehungen in späteren Abschnitten näher ausgeführt. Darüber hinaus<br />

gibt es noch zwei andere Spezialisierungen des Kontextbegriffs.<br />

Dies ist zum einen der Interaktionskontext (Metaklasse InteractionContext).<br />

Ein Fluss, an dem ein derartiger Kontext definiert ist, kann als Einstieg in einen Anwendungsfall<br />

benutzt werden. Die Ausführung eines solchen Flusses wird durch einen<br />

Akteur ausgelöst, d.h. der Akteur interagiert mit dem System. Der Interaktionskontext<br />

koppelt ein oder mehrere Akteure an einen Fluss. Dabei hat genau ein Akteur<br />

die ausgezeichnete Rolle als primärer Akteur inne. Nur primäre Akteure können einen<br />

Anwendungsfall anstoßen. Außerdem können im Interaktionskontext Vor- und Nachbedingungen<br />

natürlichsprachlich formuliert werden, die vor bzw. nach Ausführung des<br />

Flusses gelten müssen. Auch Invarianten, die während der kompletten Ausführung erfüllt<br />

sein müssen, können dort in natürlicher Sprache festgehalten werden. Der Inhalt<br />

der Vor- und Nachbedingungen und der Invariante hat allerdings keine Semantik <strong>für</strong><br />

das NarrativeModell an sich.<br />

Zum anderen gibt es Ausnahmekontexte (Metaklasse ExceptionContext). Ein<br />

Fluss, der einen derartigen Kontext besitzt, ist ein Ausnahmefluss. Im Allgemeinen<br />

kann ein Fluss zwar mehrere Kontexte besitzen, aber üblicherweise verfügt er, wenn<br />

er der Behandlung von Ausnahmen dient, nur über einen Kontext (den Ausnahmekontext).<br />

In diesem Fall ist es dann anschaulicher, von einem Ausnahmefluss zu sprechen.<br />

Ein Ausnahmefluss definiert Verhalten, welches zur Ausführung kommt als Reaktion<br />

auf eine aufgetretene Ausnahme in einem anderen Fluss. Die Kopplung an den anderen<br />

Fluss geschieht über den Kontext. Hier wird auch eine natürlichsprachliche Bedingung<br />

(entryCondition) formuliert, die angibt, in welchem Fall der Ausnahmefluss<br />

im überwachten Fluss zur Ausnahmebehandlung aktiv wird. Anders als Erweiterungen<br />

oder Inklusionen, die an wohl definierten Stellen eines Flusses stattfinden, bedeutet die<br />

Kopplung eines Flusses an einen Ausnahmefluss, dass die Ausnahmebedingung zu jeder<br />

Zeit der Ausführung eintreten kann und damit das Verhalten des Ausnahmeflusses<br />

zum Einsatz kommt.<br />

14


Ausnahmeflüsse haben semantische Besonderheiten in zweifacher Art: Die erste Besonderheit<br />

besteht darin, dass der Kontrollfluss abhängig vom Zustand nach Ausführung<br />

des Ausnahmeflusses an verschiedenen Stellen fortfahren kann. Er kann im Ursprungfluss<br />

hinter demjenigen Ereignis, an dem die Ausnahme eingetreten war, fortgesetzt<br />

werden. Ebenso kann auch zum Ende des Ursprungflusses gesprungen werden<br />

oder sogar zum Ende des gesamten Anwendungsfalles. Während der Ausführung<br />

wird abhängig vom Zustand am Ende des Ausnahmeflusses eine dieser drei Rücksprungsmöglichkeiten<br />

gewählt. Für jede dieser drei Möglichkeiten kann man je eine<br />

Bedingung im Kontext spezifizieren, unter der diese stattfindet (continueCondition,<br />

bypassCondition und abortCondition). Die zweite semantische Besonderheit ist durch<br />

den Gültigkeitsbereich des Ausnahmeflusses gegeben. Ein Ausnahmefluss kann auch<br />

jederzeit in Flüssen zum Effekt kommen, die erst über Inklusion oder Erweiterung<br />

desjenigen Flusses, an den der Ausnahmefluss gekoppelt ist, zur Ausführung kamen.<br />

Abbildung 2.5: Kontrollfluss bei Ausnahmeflüssen<br />

Abbildung 2.5 illustriert beispielhaft die Kontrollflussmöglichkeiten <strong>für</strong> Ausnahmeflüsse.<br />

Ausgangspunkt ist, dass sich der Kontrollfluss nach der Aktion A vom Hauptfluss<br />

zum Ausnahmefluss verlagert. Dies setzt voraus, dass die Ausnahmebedingung<br />

während der Ausführung von A erfüllt wurde. Daraufhin wird im Ausnahmefluss dessen<br />

gesamtes Verhalten in Form dreier Aktionen ausgeführt. Beim Verlassen des Ausnahmeflusses<br />

kann der Kontrollfluss auf drei verschiedene Arten weiterlaufen:<br />

1. die Ausführung des Hauptflusses wird mit dem Ereignis hinter der Aktion A,<br />

welche die Ausnahmebehandlung ausgelöst hat, fortgesetzt,<br />

2. die Ausführung des Hauptflusses wird beendet,<br />

3. die Ausführung des kompletten Anwendungsfalles wird beendet.<br />

15


Ausnahmekontexte, Erweiterungs- und Inklusionskontexte koppeln je zwei Flüsse über<br />

die durch den Kontext bestimmte Beziehung. Bei Ausnahmekontexten ist dies unmittelbar<br />

der Fall, bei Erweiterungs- und Inklusionskontexten, wie im Folgeabschnitt beschrieben,<br />

nur mittelbar.<br />

2.2.6 Beziehungen zwischen Flüssen<br />

In der UML gibt es zwei Arten von Beziehungen zwischen Use Cases, welche eine<br />

Aussage über die Verhaltensbeziehungen zwischen den Use Cases machen, nämlich<br />

Erweiterungs- und Inklusionsbeziehungen. Diese Beziehungen werden im Narrative-<br />

Model verfeinert und auf die Flussebene übertragen. Die Generalisierungsbeziehung<br />

zwischen Use Cases überträgt sich ganz analog auf die dazugehörigen NarrativeDescriptions.<br />

Welche Folgen das <strong>für</strong> die Elemente der NarrativeDescriptions hat, wird in<br />

Abschnitt 2.2.6 erläutert.<br />

Es ist klar, dass sich Inklusions- und Erweiterungsbeziehungen zwischen Use Cases<br />

wiederfinden müssen als Beziehungen zwischen Flüssen. Inkludiert ein Use Case U1<br />

einen Use Case U2, muss es auch mindestens einen Fluss in U1 geben, der einen<br />

Fluss aus U2 inkludiert. Nur wenn es mindestens eine Inklusionsbeziehung zwischen<br />

Flüssen der beiden Anwendungsfälle gibt, ist auch die Inklusionsbeziehung auf Ebene<br />

der Use Cases „befriedigt“. Diese fordert, dass das Verhalten von U2 an einer Stelle in<br />

U1 zur Ausführung kommen muss.<br />

Im Folgenden werden die drei Beziehungsarten im Detail beschrieben. Insbesondere<br />

wird geklärt, inwiefern verschiedene Elemente des Metamodells zusammenwirken,<br />

um die jeweiligen Beziehungstypen im Modell zu realisieren.<br />

Inklusionen<br />

<strong>Eine</strong> Inklusion bewirkt die unbedingte Ausführung des gesamten Verhaltens eines<br />

Flusses aus einem anderen Fluss heraus. Hierbei spricht man von einem inkludierenden<br />

Fluss auf der einen Seite und von einem inkludierten Fluss auf der anderen. Das<br />

Verhalten des inkludierten Flusses wird an der Stelle der Inklusion im inkludierenden<br />

Fluss ausgeführt. Die genaue Stelle in einem Fluss, an der dies stattfindet, wird in<br />

Form einer Event-Spezialisierung, der Inklusion (Metaklasse Inclusion), modelliert.<br />

Die Inklusion ist ein spezieller Kontextwechsel: eine Inklusion induziert in jedem<br />

Fall einen Wechsel des aktuellen Kontexts (der aktuelle Fluss wird verlassen und ein<br />

anderer betreten).<br />

Auf der Gegenseite muss der inkludierte Fluss über einen Inklusionskontext (Metaklasse<br />

InclusionContext) verfügen. Besitzt er einen solchen Kontext, heißt das,<br />

dass man diesen Fluss aus einem anderen Fluss heraus einmal oder mehrmals inkludieren<br />

kann. Möchte man denselben Fluss aus einem anderen Fluss heraus inkludieren,<br />

bedarf es eines weiteren Inklusionskontexts. Ein Kontext stellt also immer eine Verbindung<br />

zwischen zwei Flüssen dar. Je nachdem, ob ein Fluss intern oder extern inkludiert<br />

16


wird, kann zwischen internen und externen Inklusionskontexten unterschieden werden<br />

(Metaklassen InternalInclusionContext und ExternalInclusion-<br />

Context). Analog dazu gibt es ebenfalls Spezialisierungen <strong>für</strong> Inklusionen (Metaklassen<br />

InternalInclusion und ExternalInclusion).<br />

Abbildung 2.6: Inklusionskontext- und Inklusionskonzepte<br />

Abbildung 2.6 illustriert den Zusammenhang der verschiedenen Elemente, über die eine<br />

Inklusionsbeziehung zustande kommt. Die abstrakten Konzepte Context und ControlEvent<br />

werden verfeinert zu den abstrakten Begriffen InclusionContext und Inclusion,<br />

um dann schließlich <strong>für</strong> externe und interne Inklusionsbeziehungen konkretisiert<br />

zu werden. Zu beachten ist hier, dass jede Inklusion mit genau einem Kontext verbunden<br />

ist. Dies spiegelt zum einen die Richtung der Inklusionsbeziehung von inkludierender<br />

Verhaltenssequenz zu inkludiertem Verhalten wider und zum anderen den Fakt,<br />

dass diese Beziehung „verbindlich“ in dem Sinne ist, dass sie unbedingt stattfindet.<br />

Aus Sicht des Kontextes kann dieser mit ein oder mehreren Inklusionen verbunden<br />

sein, solange diese alle als Teil desselben Flusses definiert sind.<br />

Erweiterungen<br />

Besteht eine Erweiterungsbeziehung zwischen zwei Use Cases, hat dies zur Folge,<br />

dass es auch mindestens zwischen zwei Flüssen der jeweiligen Use Cases eine derartige<br />

Verbindung gibt. In dem Fall spricht man von einem erweiterten Fluss, in den<br />

Verhalten eingefügt werden kann und einem erweiternden Fluss, dessen Verhalten eingefügt<br />

wird.<br />

In der Verhaltenssequenz des erweiterten Flusses muss es demnach ein oder mehrere<br />

Positionen geben, an denen dies der Fall sein kann. Solch ein Punkt wird innerhalb des<br />

Flusses repräsentiert durch ein spezielles Ereignis (genauer: einen speziellen Con-<br />

17


trolEvent), einen sogenannten Erweiterungsanker (Metaklasse ExtensionAnchor).<br />

An dieser Stelle kann dann unter einer bestimmten Bedingung während der<br />

Ausführung des Flusses das Verhalten eines anderen Flusses eingefügt werden.<br />

Da<strong>für</strong> muss der erweiternde Fluss allerdings als Voraussetzung einen Erweiterungskontext<br />

(Metaklasse ExtensionContext) besitzen. Hat ein Fluss einen derartigen<br />

Erweiterungskontext, dient er als mögliches Alternativverhalten <strong>für</strong> einen anderen<br />

Fluss. Während der Ausführung wird das Verhalten dann je nach Gültigkeit einer bestimmten<br />

Bedingung, die im Erweiterungskontext in natürlicher Sprache formuliert ist,<br />

im erweiterten Fluss eingefügt. Beachtenswert hierbei ist, dass der erweiternde Fluss,<br />

der den Erweiterungskontext besitzt, damit auch die Bedingung angibt, unter der er<br />

in einem anderen Fluss zur Ausführung kommt. Dies entspricht der Semantik der Erweiterungsbeziehung<br />

in der UML, die mittels Extend-Metaklasse modelliert wird.<br />

Die Erweiterungsbeziehung ist eine gerichtete Beziehung von erweiterndem Use Case<br />

zum erweiterten Use Case. Der erweiternde Anwendungsfall spezifiziert unter welcher<br />

Bedingung er zum Tragen kommt. Der erweiterte Use Case bietet nur Stellen an, an<br />

denen er erweitert werden kann.<br />

Abbildung 2.7: Abstrakte Erweiterungskontext- und Erweiterungsankerkonzepte<br />

Abbildung 2.7 veranschaulicht diesen Zusammenhang. Ein Erweiterungsfluss muss<br />

einen Erweiterungskontext besitzen. Der erweiterte Fluss muss ein spezielles Ereignis<br />

in Form eines Erweiterungsankers definieren, an dem das Verhalten des erweiternden<br />

Flusses zur Ausführung kommen kann. Er kann mehrere derartige Anker an verschiedenen<br />

Stellen in seinem Verhaltensablauf definieren, an die dann mögliche Kontexte<br />

„angedockt“ werden. Diese Kardinalität spiegelt die Richtung der Erweiterungsbeziehung<br />

wider (von erweiterndem Fluss zu erweitertem Fluss): Erweiterungsanker werden<br />

lokal in einem Fluss definiert, ohne Wissen, ob an den Stellen tatsächlich bedingtes<br />

Verhalten zum Einsatz kommt. Daher muss ein Anker auch nicht zwangsläufig mit einem<br />

Kontext verbunden sein. Andersherum muss ein Erweiterungskontext mit ein oder<br />

mehreren Ankern verbunden werden, die dann allerdings alle Teil desselben Flusses<br />

sein müssen. Die Konzepte in Abbildung 2.7 sind alle abstrakt. Sie werden im Folgenden<br />

bezüglich des Aspekts verfeinert, ob eine Erweiterungsbeziehung zwischen zwei<br />

Flüssen einer NarrativeDescription oder verschiedener NarrativeDescriptions besteht.<br />

18


Man unterscheidet zwischen internen Erweiterungskontexten (Metaklasse InternalExtensionContext),<br />

die Flüsse einer NarrativeDescription koppeln und Externen<br />

(Metaklasse ExternalExtensionContext), über die zwei Flüsse verschiedener<br />

NarrativeDescriptions in eine Erweiterungsbeziehung gesetzt werden. Ein<br />

externer Erweiterungskontext hat dabei einen Verweis auf die Extend-Instanz des<br />

UML-Modells, die er repräsentiert. Man kann nur dort externe Erweiterungsbeziehungen<br />

zwischen Flüssen von Use Cases modellieren, wo auch eine Erweiterungsbeziehung<br />

zwischen den entsprechenden Use Cases besteht. Analog zu den internen und externen<br />

Kontexten wird bei den Ankern, an denen die Erweiterungsbeziehung ansetzt,<br />

ebenfalls unterschieden zwischen internen und externen Erweiterungsankern (Metaklassen<br />

InternalExtensionAnchor, ExternalExtensionAnchor). Auch<br />

hier hat der externe Erweiterungsanker eine Referenz auf die entsprechende ExtensionPoint-Instanz<br />

des UML-Modells.<br />

Abbildung 2.8: Verfeinerung der Erweiterungskontext- und Erweiterungsankerkonzepte<br />

Abbildung 2.8 beschreibt die Spezialisierungen der aus Abbildung 2.7 bekannten Konzepte.<br />

Man sieht wie die Erweiterungsbeziehung zu internen und externen Kontexten<br />

und Ankern verfeinert wird.<br />

Darüber hinaus unterscheidet sich die Semantik der internen Erweiterungsbeziehung<br />

zwischen zwei Flüssen einer NarrativeDescription von derjenigen der externen Erweiterungsbeziehung.<br />

Die Semantik der externen Beziehung ist vorgegeben durch die<br />

Semantik des Extends in der UML. Diese besagt, dass bestimmte Teile des Verhaltens<br />

des erweiternden Use Cases an ein oder mehreren Stelle im erweiterten Use Case<br />

zur Ausführung kommen können (abhängig davon, ob die Bedingung erfüllt ist oder<br />

nicht). Kommt das Alternativverhalten des erweiternden Flusses im erweiterten Fluss<br />

zur Ausführung, wird der Kontrollfluss im erweiterten Fluss nach Ausführung des Alternativverhaltens<br />

hinter der Stelle, an der die Erweiterung ursprünglich stattgefunden<br />

hat, fortgesetzt. Es ist nicht möglich nach der Ausführung des erweiternden Flusses<br />

19


den Kontrollfluss an einer anderen Stelle im erweiterten Fluss fortzusetzen.<br />

Anders verhält es sich im Falle von internen Erweiterungsbeziehungen. Hier kann<br />

man am Ende der Ausführung eines erweiternden Flusses abhängig von bestimmten<br />

Bedingungen entscheiden, an welcher Stelle im erweiterten Fluss der Kontrollfluss<br />

fortgesetzt werden soll. Konkret geschieht dies über (interne) Erweiterungsanker (Metaklasse<br />

InternalExtensionAnchor), welche als Rücksprungsanker <strong>für</strong> einen<br />

internen Erweiterungskontext dienen. Jeder Rücksprungsanker ist außerdem über den<br />

Kontext assoziiert mit einer (in natürlicher Sprache formulierten) Rücksprungsbedingung.<br />

Am Ende der Ausführung des erweiternden Flusses wird dann abhängig von der<br />

erfüllten Bedingung zu einem dieser Anker zurückgesprungen. Verbunden wird ein<br />

interner Erweiterungsanker in seiner Funktion als herkömmlicher Erweiterungspunkt<br />

mit einem internen Erweiterungskontext über die branchingInternalExtension/internalBranchAnchor-Assoziation<br />

zwischen den beiden Elementen. Analog dazu gibt es<br />

eine mergingInternalExtension/internalMergeAnchor-Assoziation über die ein Anker<br />

als Rücksprungspunkt mit einem Kontext verbunden wird.<br />

Generalisierung<br />

Als dritten Beziehungstypen zwischen Use Cases gibt es die Generalisierung. Anders<br />

als Inklusions- und Erweiterungsbeziehungen dient die Generalisierung nicht der Modellierung<br />

von Verhaltensbeziehungen zwischen Flüssen. Die Generalisierung im Sinne<br />

der UML, beschreibt eine taxonomische Beziehung zwischen einem spezielleren<br />

und einem generelleren Classifier.<br />

Im UML-Metamodell ist die Generalisierung demnach nicht als reflexive Beziehung<br />

zwischen Use Cases definiert, sondern bereits auf der Ebene der abstrakten Metaklasse<br />

Classifier. Ein Classifier dient der Klassifizierung von Instanzen bezüglich ihrer<br />

sie kennzeichnenden Eigenschaften. Classifier können in einer Generalisierungsbeziehung<br />

zu anderen Classifiern stehen. Damit stehen Eigenschaften, die <strong>für</strong> Instanzen des<br />

generelleren Classifiers spezifiziert wurden, auch denjenigen des spezielleren Classifiers<br />

zur Verfügung. Sowohl Use Cases als auch Akteure sind Classifier.<br />

Ein verwandtes UML-Konzept wird durch die abstrakte Metaklasse Redefinable-<br />

Element beschrieben. Ein derartig redefinierbares Element ist ein Element, welches,<br />

wenn es im Kontext eines Classifiers definiert wurde, von einem anderen Classifier, der<br />

eine Spezialisierung des Kontextclassifiers darstellt, redefiniert werden kann. Classifier<br />

selbst sind derartige redefinierbare Elemente, damit also insbesondere auch Akteure<br />

und Use Cases.<br />

Aus dem Vorhergegangenen folgt, dass ein Use Case A, der als Spezialisierung des<br />

Use Case B modelliert wird, diesen Use Case B redefinieren kann. Auch die Extend-Metaklasse<br />

über die die Erweiterungsbeziehung zwischen Use Cases realisiert<br />

wird, ist eine RedefinableElement-Spezialisierung. Somit sieht die UML nicht<br />

nur vor, dass Use Cases als Ganzes redefiniert werden, sondern durchaus auch einzelne<br />

Elemente von Use Cases. Über die Redefinition des Verhaltens von Use Cases<br />

20


macht die UML-Spezifikation selbst allerdings keinerlei Angaben. Damit bleibt offen,<br />

auf welcher Granularität Verhalten redefiniert werden kann und was Redefinition<br />

in diesem Kontext überhaupt bedeutet. Bei der Konzipierung des NarrativeModels<br />

wurde die von Bittner und Spence ausgeführte Interpretation [BS02] <strong>für</strong> die Generalisierungsbeziehung<br />

zwischen Anwendungsfällen adaptiert und auf die Elemente des<br />

NarrativeModels angewendet.<br />

Nach Bittner und Spence wird im Rahmen der Spezialisierungsbeziehung zwischen<br />

Use Cases natürlich auch Verhalten verfeinert. Konkret kann das Verhalten des generellen<br />

Use Cases im spezialisierenden Use Case zutage treten, in aller Regel geschieht<br />

dies jedoch in modifizierter Form. Bezogen auf die textuellen Beschreibungen von Use<br />

Cases vererben sich im Zuge der Spezialisierung die formulierten Verhaltenssequenzen<br />

(also die Flüsse) der generellen NarrativeDescription an die speziellere NarrativeDescription.<br />

Abbildung 2.9: Generalisierung und Redefinierbarkeit im NarrativeModel<br />

Damit folgt, dass insbesondere alle diejenigen Elemente redefinierbar sein müssen,<br />

die die interne Struktur einer natürlichsprachlichen Beschreibung ausmachen. Anders<br />

als ihre referenzierten Entsprechungen im UML-Metamodell sind die Metaklassen<br />

NarrativeActor und NarrativeDescription nicht redefinierbar. Erst<br />

die NarrativeModel-Metaklassen, die eingesetzt werden zur Spezifikation der internen<br />

Struktur einer NarrativeDescription, spezialisieren die RedefinableElement<br />

Metaklasse. Die Elemente die das Verhalten einer NarrativeDescription ausmachen<br />

sind Flow, Context und Event. Dies ist illustriert in Abbildung 2.9. In dieser<br />

Abbildung sieht man, dass NarrativeDescription und NarrativeActor<br />

keine RedefinableElements sind. Sie besitzen wohl aber eine specific/general-<br />

Assoziation, über die eine NarrativeDescription mit ihren spezielleren bzw. generelleren<br />

NarrativeDescriptions verbunden ist. Die Hierarchie der NarrativeDescriptions<br />

gemäß dieser Assoziation entspricht genau der Generalisierungshierarchie zwischen<br />

den dazugehörigen Use Cases.<br />

21


Mittels dieser Mechanismen kann eine textuelle Beschreibung bezüglich ihrer verschiedenen<br />

Eigenschaften spezialisiert und redefiniert werden. Besteht eine Spezialisierungsbeziehung<br />

zwischen zwei textuellen Beschreibungen A und B (von A nach<br />

B), erbt die NarrativeDescription A die Eigenschaften von B, d.h. insbesondere alle<br />

in B definierten Flüsse, samt dazugehöriger Kontexte und Ereignisse. Auf Narrative-<br />

Description-Strukturebene können im Rahmen der Spezialisierung neue Flüsse hinzugefügt<br />

werden oder bestehende Flüsse redefiniert werden. Dabei können bestehende<br />

Ereignisse redefiniert werden oder an beliebigen Stellen im Fluss neue Ereignisse hinzugefügt<br />

werden. Flüsse können außerdem zusätzliche Kontexte erhalten und bestehende<br />

Kontexte können redefiniert werden.<br />

Ist ein Use Case abstrakt, dann ebenso die dazugehörige NarrativeDescription. Innerhalb<br />

der NarrativeDescription können Flüsse als Ganzes abstrakt sein (d.h. sie definieren<br />

keinerlei Ereignisse) oder ein Fluss besitzt eine Menge von konkreten und abstrakten<br />

Ereignissen. Beinhaltet ein Fluss ein abstraktes Ereignis, ist der Fluss als solcher<br />

notwendigerweise auch abstrakt. Dies setzt sich dann fort bis auf die Ebene der NarrativeDescription.<br />

Umgekehrt gilt, dass ein konkreter Use Case keinerlei abstraktes<br />

Verhalten besitzen kann. Konsistenz zwischen Use Case-Modell und NarrativeModel-<br />

Modell wird hier, wie an vielen anderen Stellen, durch im Metamodell formulierte<br />

Randbedingungen sichergestellt.<br />

2.2.7 Randbedingungen im Metamodell<br />

Viele Elemente des Metamodells sind mit Randbedingungen (constraints) versehen,<br />

die mittels OCL (Object Constraint Language) [Obj03a] formuliert sind. Randbedingungen<br />

sollen Qualität und Konsistenz einer Modellinstanz verbessern und sicherstellen.<br />

Neben den Arten von Randbedingungen, die in der UML-Spezifikation beschrieben<br />

sind [Obj07b] unterscheiden wir zwischen zwei weiteren Typen:<br />

• Randbedingungen, die die strukturelle Konsistenz eines NarrativeModels mit<br />

dem zu beschreibenden Use Case-Modell gewährleisten sollen und<br />

• Randbedingungen, die Semantik <strong>für</strong> Elemente des NarrativeModels formulieren.<br />

Die zweite Art Randbedingung ist insofern wichtiger, als dass eine derartige Bedingung<br />

Semantik definiert und im Falle ihrer Verletzung die NarrativeModel-Instanz<br />

inkorrekt ist. Konkret kann dies beispielsweise bedeuten, dass bestimmte Flüsse gar<br />

nicht oder nur ungenügend spezifiziert wurden.<br />

Mit Hilfe von Randbedingungen kann sichergestellt werden, dass eine Modellinstanz<br />

ohne Verletzungen korrekt ist in dem Sinne, dass die Elemente des Use Case-Modells<br />

Entsprechungen im NarrativeModel besitzen (Konsistenz). Weiterhin kann garantiert<br />

22


werden, dass alle durch die NarrativeModel-Instanz beschriebenen Szenarien ein wohl<br />

definiertes Startereignis haben, von dem aus ein endlicher Pfad, der aus einer diskreten<br />

Folge von Ereignissen besteht, zum Ende des Anwendungsfalles existiert. Randbedingungen<br />

können offensichtlich nicht sicherstellen, dass Anwendungsfälle vollständig<br />

und korrekt im Sinne der modellierten Domäne beschrieben werden.<br />

Als Beispiel <strong>für</strong> eine semantische Absicherung mittels Randbedingung dienen Inklusionen.<br />

Weiter oben wurde <strong>für</strong> Inklusionskontexte beschrieben, dass jeder Fluss, der<br />

einen solchen Kontext besitzt, aus einem anderen Fluss heraus ein- oder mehrmals<br />

inkludiert werden kann. Über eine Randbedingung wird an dieser Stelle abgesichert,<br />

dass nicht zwei verschiedene Flüsse den inkludierten Fluss über denselben Kontext<br />

inkludieren.<br />

<strong>Eine</strong> andere Randbedingung gewährleistet, dass der Rücksprung aus einem erweiternden<br />

Fluss (mittels interner Erweiterung) nur zu einem Anker des ursprünglich erweiterten<br />

Flusses erfolgen kann und nicht etwa zu einem anderen Fluss.<br />

2.3 Beispiel <strong>für</strong> eine textbasierte Anwendungsfallbeschreibung<br />

An dieser Stelle wird ein (<strong>für</strong> diesen Zweck vereinfachtes) Beispiel vorgestellt. Inhalt<br />

ist die Modellierung eines Geldautomaten mit Hilfe eines Use Case-Diagramms und<br />

darauf aufsetzender textueller Beschreibung.<br />

Abbildung 2.10: Use Case Modellierung eines Geldautomaten<br />

23


In Abbildung 2.10 ist das System Geldautomat modelliert. Der Akteur auf der linken<br />

Seite ist der Kunde. Er ist der primäre Akteur und aus seiner Sicht wird die funktionale<br />

Anforderung Geld abheben an den Geldautomaten formuliert. Aus diesem Grund ist<br />

der Kunde mit dem entsprechenden Use Case assoziiert.<br />

Da ein Kunde, der Geld ausgezahlt bekommen möchte, sich auch immer authentifizieren<br />

muss, inkludiert Geld abheben den Anwendungsfall Authentifizieren. Verbunden<br />

mit diesen beiden Use Cases ist der Akteur Banksystem. Während der Transaktion des<br />

Geld abhebens und des Authentifizierungsvorgangs kommuniziert der Geldautomat<br />

mit dem Banksystem. Der Anwendungsfall Quittung drucken steht als Erweiterung<br />

mit Geld abheben in Beziehung. Wenn der Kunde es wünscht, bekommt er eine Quittung<br />

der gerade getätigten Auszahlung gedruckt.<br />

Use Case Geld abheben<br />

Geld abheben Standard:<br />

Kontexte:<br />

wird ausgelöst vom Kunden<br />

Ereignisse:<br />

1. Der Kunde steckt seine Bankkarte in den<br />

Automaten.<br />

2. Inklusion: Use Case Authentifizieren<br />

3. {hinter Authentifizierung}<br />

4. Der Kunde gibt gewünschten Geldbetrag<br />

ein.<br />

5. Der Automat gibt die Bankkarte zurück.<br />

6. Der Automat zahlt das Geld aus.<br />

7. {hinter Geld Ausgabe}<br />

Kunde bricht ab:<br />

Kontexte:<br />

Zu jeder Zeit in {Geld abheben Standard},<br />

wenn Kunde abbricht<br />

Ereignisse:<br />

1. Der Automat gibt die Bankkarte zurück.<br />

Kontrollfluss:<br />

Anwendungsfall beenden, wenn: wahr<br />

UC Authentifizieren<br />

Authentifizieren Standard:<br />

Kontexte:<br />

inkludiert von Fluss {Geld abheben Standard}<br />

in Use Case Geld abheben<br />

Ereignisse:<br />

1. {vor PIN Eingabe}<br />

2. Der Kunde gibt seine PIN ein.<br />

3. {hinter PIN Eingabe}<br />

erneute PIN Eingabe:<br />

Kontexte:<br />

erweitert Fluss {Authentifizieren Standard}<br />

an {hinter PIN Eingabe}, wenn PIN inkorrekt<br />

Ereignisse:<br />

1. Der Automat fordert den Kunden zur erneuten<br />

PIN Eingabe auf.<br />

Kontrollfluss:<br />

zurück zu {vor PIN Eingabe}, wenn: wahr<br />

UC Quittung drucken<br />

Quittung drucken Standard:<br />

Kontexte:<br />

erweitert Fluss {Geld abheben Standard} an<br />

{hinter Geld Ausgabe}, wenn Kunde Quittung<br />

wünscht<br />

Ereignisse:<br />

1. Der Automat druckt eine Quittung.<br />

Kontrollfluss:<br />

zurück zu {hinter Geld Ausgabe}, wenn:<br />

wahr<br />

Abbildung 2.11: Textuelle Beschreibung der Geldautomatanwendungsfälle<br />

Abbildung 2.11 repräsentiert eine NarrativeModel-Instanz in Form einer <strong>strukturierte</strong>n<br />

Darstellung in natürlicher Sprache, die angelehnt ist an die informelle Darstellung von<br />

textuellen Anwendungsfallbeschreibungen von Bittner und Spence [BS02].<br />

Hier findet man all diejenigen Elemente als Teil der Beschreibung wieder, die wie im<br />

Vorgängerkapitel vorgestellt, die interne Struktur eines Use Cases ausmachen. Zum<br />

Use Case Geld abheben gehört eine NarrativeDescription, <strong>für</strong> die zwei Flüsse definiert<br />

24


sind. Zum einen ist dies der Fluss Geld abheben Standard, der den Standardablauf des<br />

Anwendungsfalles beschreibt und der durch einen Kunden ausgelöst wird (festgehalten<br />

im Kontext des Flusses), indem dieser seine Karte in den Automaten einführt (die<br />

erste Aktion im Fluss). Im NarrativeModel hat dieser Fluss insgesamt sieben Ereignisse:<br />

• vier Aktionen (an den Positionen 1, 4, 5 und 6 im Fluss)<br />

• eine externe Inklusion (an der Position 2)<br />

• zwei Erweiterungsanker (ein Interner an Position 3, namens {hinter Authentifizierung}<br />

und ein Externer an Position 7 {hinter Geld Ausgabe}<br />

Der Erweiterungsanker {hinter Authentifizierung} wird im Rahmen dieses Beispiels<br />

nicht benutzt. An dieser Stelle würde als Teil einer vollständigen Beschreibung internes<br />

Alternativverhalten zum Zuge kommen. Beispielsweise ein Test, ob der Kunde<br />

nach Inklusion des Anwendungsfalles Authentifizieren tatsächlich authentifiziert ist.<br />

Im Beispiel ist das Verhalten des Flusses Authentifizieren Standard insofern sehr simpel<br />

gehalten, als dass der Kunde nach Eingabe einer falschen PIN erneut aufgefordert<br />

wird, sich zu authentifizieren. In der Realität würde der Automat nach einer bestimmten<br />

Anzahl erfolgloser Eingabeversuche die Bankkarte des Kunden einziehen. In dem<br />

Fall ist der Kunde nach Ausführung von Authentifizieren nicht authentifiziert und es<br />

müsste vom Standardablauf abweichendes Alternativverhalten zur Aktion kommen.<br />

Außerdem besitzt der Anwendungsfall Geld abheben noch einen anderen Fluss, nämlich<br />

Kunde bricht ab. Dies ist ein Ausnahmefluss, dessen Verhalten jederzeit zur Ausführung<br />

kommen kann, wenn der Kunde die aktuelle Transaktion abbricht. Hierbei ist<br />

zu beachten, dass der Ausnahmefluss sich zwar auf den Fluss Geld abheben Standard<br />

bezieht, aber auch wirksam wird während der Ausführung der Flüsse Authentifizieren<br />

Standard und Quittung drucken aus Geld abheben Standard heraus. Am Ende der<br />

Ausführung eines Ausnahmeflusses gibt es grundsätzlich drei verschiedene Möglichkeiten,<br />

den Kontrollfluss fortzusetzen. Im konkreten Fall des Ausnahmeflusses Kunde<br />

bricht ab folgt jedoch immer das Ende des Anwendungsfalles.<br />

25


Kapitel 3<br />

Technische Grundlagen<br />

Im Zuge der technischen Realisierung der <strong>Simulationsumgebung</strong> wurden diverse Technologien<br />

aus dem Umfeld von Eclipse eingesetzt. Diese werden ebenso wie die Eclipse-<br />

Plattform selbst im Folgenden vorgestellt. Den Abschluss dieses Kapitels bildet eine<br />

Beschreibung der ViPER-IDE.<br />

3.1 Eclipse-Plattform<br />

Eclipse ([Ecla]) wurde ursprünglich entwickelt von OTI (Object Technology International)<br />

als Nachfolgeprodukt von VisualAge. Die Verantwortung <strong>für</strong> Eclipse ging<br />

mit der OTI Übernahme durch IBM 1996 an IBM Kanada über. Anfang 2001 hat<br />

IBM Eclipse der Open-Source-Gemeinde geschenkt. 2003 wurde der Open-Source-<br />

Entwicklungsprozess <strong>für</strong> Eclipse in Form der Eclipse Foundation institutionalisiert.<br />

Die Eclipse Foundation steuert die Entwicklung von Eclipse und ist da<strong>für</strong> verantwortlich,<br />

dass Eclipse spätestens seit der Version 3.0 mehr ist als eine bloße Java-<br />

Entwicklungsumgebung. Seit dieser Version dient der strukturelle Kern von Eclipse<br />

als Basis <strong>für</strong> beliebige Desktopanwendungen. Wo Eclipse in Version 2.1 primär eine<br />

Java-Entwicklungsumgebung darstellte, fand mit Version 3.0 ein Paradigmenwechsel<br />

statt. Eclipse wird nunmehr primär als Plattform wahrgenommen und die Java-<br />

Entwicklungsumgebung als eine Ausprägung dieser Plattform. Technologische Voraussetzung<br />

<strong>für</strong> dieses Umdenken war die Einführung einer OSGi-basierten [OSG]<br />

Plattformlaufzeitumgebung, die den Grundstein legte <strong>für</strong> eine dynamische Plugin-<br />

Architektur. Mit Version 3.1 ist Eclipse zu einer auch in der Praxis bewährten Rich<br />

Client Plattform gereift. Beispielsweise hat die NASA auf Basis der Eclipse-Plattform<br />

ein Produkt zur Steuerung des Mars-Rovers „Spirit“ entwickelt [Mae].<br />

<strong>Eine</strong> Rich Client Plattform gibt dem Entwickler Technologien und Rahmenwerke <strong>für</strong><br />

die Entwicklung von Rich Clients an die Hand. Rich Clients bieten einem Benutzer <strong>für</strong><br />

eine bestimmte Domäne eine komfortable und qualitativ hochwertige graphische Oberfläche.<br />

Die graphische Oberfläche eines Rich Client nutzt native Desktop-Metaphern<br />

27


wie Drag-and-Drop, Zwischenablage, Navigation und Look-and-Feel [ML05]. <strong>Eine</strong><br />

Rich Client Plattform unterstützt und erleichtert die Entwicklung eines derartigen Rich<br />

Clients, indem sie sowohl einen technologischen Rahmen als auch eine Architektur<br />

vorgibt. Im Idealfall erleichtert sie außerdem die Integration verschiedener generell<br />

unabhängiger, aber doch zusammenarbeitender Anwendungskomponenten.<br />

In der Eclipse-Nomenklatur heißen einzelne Komponenten, die gemeinsam die Plattform<br />

ausmachen, Plugins. Die Plattform kann jederzeit durch weitere Plugins erweitert<br />

werden. Die Eclipse-Plattform stellt Mechanismen und Regeln bereit, um die nahtlose<br />

Integration verschiedener Werkzeuge in Form von Plugins zu ermöglichen.<br />

Ein Plugin ist die kleinste Einheit einer Funktionalität, die gesondert <strong>für</strong> die Eclipse-<br />

Plattform entwickelt und eingesetzt werden kann [Obj03b]. Bis auf den funktionalen<br />

Eclipse Kern, die Plattform-Runtime, ist der komplette Rest der Eclipse-Funktionalität<br />

in Form von Plugins realisiert. Plugins werden in Java programmiert. Ein typisches<br />

Plugin besteht aus einer Menge von Java-Klassen und diversen anderen Artefakten,<br />

wie beispielsweise HTML- und Bilddateien sowie generell jeder beliebigen Art von<br />

Datei. Notwendiger Bestandteil eines jeden Plugins ist das Plugin-Manifest. Dieses<br />

Manifest spezifiziert deklarativ, inwiefern das aktuelle Plugin andere Plugins erweitert<br />

(Extension) oder selbst Erweiterungspunkte (ExtensionPoint) anbietet, über die es<br />

selbst von anderen Plugins erweitert werden kann.<br />

Als Beispiel <strong>für</strong> diesen Mechanismus sei das Workbench-Plugin von Eclipse genannt.<br />

Dieses definiert einen Erweiterungspunkt <strong>für</strong> Benutzereinstellungen (Preferences). Jedes<br />

Plugin kann seine eigenen lokalen Benutzereinstellungen mittels Extension zu diesem<br />

Erweiterungspunkt beisteuern. Ein Erweiterungspunkt kann Schnittstellen definieren,<br />

die ein erweiterndes Plugin in Form von Java-Klassen Implementierungen bereitstellen<br />

muss, um den Erweiterungspunkt anzusteuern.<br />

Beim Start der Eclipse-Plattform legt die Plattform-Runtime alle verfügbaren Plugins<br />

in der ExtensionRegistry ab. Hier<strong>für</strong> werden die einzelnen Plugins noch nicht komplett<br />

in den Speicher geladen, sondern nur ihr jeweiliges Manifest gelesen und die<br />

daraus extrahierten Informationen in der ExtensionRegistry gespeichert. Dieses „lazyloading“<br />

von Plugins garantiert schnelle Startzeiten <strong>für</strong> die Plattform und reduziert den<br />

anfänglichen Speicherverbrauch. Solange ein Plugin nicht vollständig geladen ist, ist<br />

sein Speicherverbrauch vernachlässigbar. Während der Laufzeit können der Ausführungsplattform<br />

keine neuen Plugins hinzugefügt werden.<br />

Ein Plugin wird aktiviert, wenn der Code des Plugins tatsächlich ausgeführt werden<br />

soll. Erst zu diesem Zeitpunkt werden seine Java-Klasse instanziiert. Außerdem nutzt<br />

das Plugin die ExtensionRegistry, um auf die Erweiterungen durch externe Plugins<br />

zuzugreifen und diese einzubinden.<br />

Die Plattform-Runtime definiert einen speziellen Erweiterungspunkt <strong>für</strong> Anwendungen,<br />

die auf der Eclipse Rich Client Plattform basieren. Wenn eine Instanz der Plattform<br />

ausgeführt wird, wird ihr der Name der Anwendung per Parameter übergeben.<br />

Damit wird einzig das Plugin der Anwendung geladen und aktiviert.<br />

28


Abbildung 3.1: Architektur der Eclipse-Plattform<br />

Abbildung 3.1 stellt die grobe Struktur der Eclipse-Plattform Architektur dar. Alle<br />

Komponenten bestehen aus ein oder mehreren Plugins. Die <strong>für</strong> diese Arbeit relevanten<br />

Komponenten sind Workspace und Workbench. Workbench baut auf dem SWT/JFace-<br />

Toolkit auf.<br />

3.1.1 Workspaces<br />

Die verschiedenen Werkzeuge, die als Plugin die Eclipse-Plattform erweitern, operieren<br />

auf physischen Dateien im Workspace des Benutzers. Der Workspace ist ein<br />

Eclipse-Konzept und wird technisch durch das gleichnamige Plugin als Teil der Eclipse-<br />

Plattform realisiert. Der Workspace besteht aus einer Menge von top-level Projekten,<br />

die jeweils im Dateisystem eine Entsprechung in Form eines benutzerdefinierten Verzeichnisses<br />

haben. Jedes Projekt beinhaltet Dateien, die vom Benutzer mittels diverser<br />

Operationen manipuliert werden können. Dies beinhaltet neben der Modifikation und<br />

des Löschens vorhandener Dateien natürlich auch das Anlegen neuer Dateien. Auf alle<br />

Dateien des Workspaces kann außerdem über die normalen Betriebssystemmechanismen<br />

und Anwendungen zugegriffen werden. Allerdings legt die Eclipse-Plattform <strong>für</strong><br />

Werkzeuge, die in die Plattform integrierte sind, eine Abstraktionsschicht über diese<br />

Ebene. Hier sind Projekte, Dateien und Verzeichnisse Ressourcen (IResource-<br />

Instanzen), auf die per Platform-API zugegriffen werden kann. Derartige Workspace-<br />

Ressourcen werden durch adaptierbare Objekte repräsentiert. Das sind Objekte, die das<br />

29


IAdaptable-Interface implementieren und deren Verhalten über diesen Weg von<br />

anderen Werkzeugen (in Form von Plugins) erweitert werden kann. Darüber hinaus<br />

bietet die Plattform einen Mechanismus zum Verfolgen von Workspace-Änderungen.<br />

Dies geschieht mit Hilfe von Notifikationen, mittels derer interessierte Werkzeuge über<br />

Manipulationen an bestimmten Ressourcen in Form sogenannter Ressource-Deltas informiert<br />

werden.<br />

3.1.2 SWT/JFace<br />

Die Bedienoberfläche der Eclipse-Plattform basiert auf einer Workbench, die ein Erscheinungsbild<br />

vorgibt und dem Benutzer eine erweiterbare Oberfläche präsentiert.<br />

API und Implementierung der Workbench basieren beiderseits auf zwei verschiedenen<br />

Toolkits.<br />

SWT (Standard Widget Toolkit) ([SWT]) ist eine low-level Graphikbibliothek, die Standardkomponenten<br />

<strong>für</strong> die Entwicklung einer graphischen Benutzeroberfläche zur Verfügung<br />

stellt. Das SWT Entwicklerteam bewertet SWT wie folgt:<br />

SWT provides efficient, portable access to the UI facilities of the OSs on<br />

which it is implemented.<br />

Dies unterscheidet SWT auch grundsätzlich von anderen Java-basierten graphischen<br />

Toolkits wie AWT und Swing. SWT ist ein „thin layer“ <strong>für</strong> existierende graphische<br />

Komponenten des Zielsystems. Wo es geht, werden native Graphikressourcen eingesetzt.<br />

Auf der Zielplattform nicht verfügbare Komponenten werden emuliert. SWT<br />

erlaubt den Zugriff auf native Windowssysteme über eine konsistente und portable<br />

Java-API. SWT Anwendungen sind portabel zwischen allen Plattformen, <strong>für</strong> die es<br />

SWT Implementierungen gibt. Dank der Nutzung nativer Betriebssystemressourcen<br />

sind SWT Anwendungen schneller als vergleichbare Swing/AWT-Anwendungen und<br />

bilden zum anderen das Look-and-Feel der Zielplattform inklusive anderer spezifischer<br />

Desktop-Metaphern wie Drag-and-Drop besser ab. SWT ist nicht abhängig von<br />

der Eclipse Plattform-Runtime, sondern kann auch als Toolkit außerhalb der Eclipse-<br />

Plattform benutzt werden.<br />

SWT bietet eine Vielzahl graphischer Komponenten zur Erstellung einer graphischen<br />

Oberfläche. Dazu gehören einzelne Bedienelemente (sogenannte Widgets) genauso wie<br />

LayoutManager. Bedienelemente stehen in Form einfacher Knöpfe und Textfelder bis<br />

hin zu Komponenten zur Unterstützung von Datumsauswahl und -eingabe zur Verfügung.<br />

LayoutManager dienen der Positionierung von Bedienelementen in zusammengesetzten<br />

Elementen (Composite). Dies erleichtert den hierarchischen Aufbau von<br />

Oberflächen. Allerdings bietet SWT über die Widgets hinaus keinerlei übergreifende<br />

Konzepte <strong>für</strong> die graphische Repräsentation von Modellen. Der Programmierer muss<br />

im Zuge der Realisierung einer graphischen Oberfläche mittels SWT relativ viel manuelle<br />

Arbeit verrichten. Dies hat damit zu tun, dass SWT nur eine dünne Schicht<br />

über die Betriebssystemressourcen legt. Für die Kopplung und Interaktion zwischen<br />

30


Widgets kann ein Ereignismodell genutzt werden, das Aktionen des Benutzers wie<br />

beispielsweise Mausbewegungen oder Tastatureingaben in Ereignisse umsetzt, die programmatisch<br />

verarbeitet werden können.<br />

Das JFace-Toolkit bietet höherwertige Abstraktionen <strong>für</strong> häufig genutzte graphische<br />

Konstrukte und Hilfsmittel. JFace ist in seiner API und Implementierung unabhängig<br />

vom Windowssystem des Zielsystems. Es nutzt SWT, ohne diese Benutzung zu verstecken.<br />

JFace beinhaltet die üblichen Bestandteile eines graphischen Toolkits in Form von<br />

Komponenten <strong>für</strong> Bild- und Fontverwaltung, Dialoge, Präferenzen und vieles mehr.<br />

Erwähnenswert ist außerdem ein Rahmenwerk <strong>für</strong> die Erstellung von Wizards. Wizards<br />

dienen dazu, Benutzer in Form einer Sequenz modaler Dialoge durch eine komplexe<br />

Aktivität zu führen. Zwei andere interessante JFace-Konzepte sind Aktionen (Actions)<br />

und Viewer.<br />

Der Aktionsmechanismus erlaubt es, Benutzeraktionen unabhängig von ihrem konkreten<br />

Einsatzgebiet in der graphischen Oberfläche wiederverwendbar zu kapseln. Technisch<br />

realisiert wird dies über die Implementierung der Schnittstelle IAction. Die<br />

Aktionslogik kommt in der Methode run() zur Ausführung. Derartig durch eine Aktion<br />

gekapseltes Verhalten kann aus den verschiedensten Stellen der Benutzeroberfläche<br />

zum Einsatz kommen, z.B. aus Kontextmenüs oder Werkzeugleisten heraus. Jede Aktion<br />

verfügt als Teil des IAction-Interfaces über Eigenschaften, die ihre graphische<br />

Repräsentation betreffen. Dazu gehören Icons, Beschriftungen, ein Tooltip und andere<br />

Darstellungsspezifika. Somit ist es einfach, eine Aktion auszutauschen oder zu modifizieren,<br />

selbst wenn sie an diversen Stellen der Oberfläche zum Einsatz kommt.<br />

Viewer sind modellbasierte Adapter <strong>für</strong> bestimmte Arten von SWT Widgets. Das heißt,<br />

dass Viewer eine Abstraktion über SWT-Komponenten wie Listen, Tabellen und Bäume<br />

bieten und im Sinne des MVC-Paradigmas genutzt werden können. Dazu gehören<br />

die Darstellung eines Modellelements und die Navigation über seine möglichen<br />

Kinder, sowie die Synchronisation der Viewer mit Modellen und Änderungen an<br />

diesen Modellen. Um dies zu erreichen, werden Viewer mit Implementierungen von<br />

IStructuredContentProvider und ILabelProvider parametrisiert. Der<br />

Viewer delegiert Navigation und Darstellung des aktuell dargestellten Modellelements<br />

an diese Provider. Der <strong>für</strong> den <strong>strukturierte</strong>n Inhalt des Viewers verantwortliche ContentProvider<br />

muss außerdem Änderungen des zugrundeliegenden Modells in Updates<br />

am Viewer übersetzen. Der LabelProvider sorgt <strong>für</strong> die graphische Repräsentation eines<br />

Modellelements mittels textueller Beschriftung und Icon. Darüber hinaus unterstützen<br />

Viewer als Teil ihrer Darstellungsstrategie Sortierung und Filterung von Modellelementen<br />

über Delegation an spezielle Implementierungen von ViewerSorter<br />

und ViewerFilter.<br />

31


3.1.3 Workbench<br />

Anders als SWT und JFace, die auch außerhalb der Eclipse-Plattform wiederverwendbare<br />

Toolkits sind, macht die Workbench die Benutzeroberfläche der Eclipse-Plattform<br />

(Eclipse Platform UI) aus. Sie gibt Strukturen vor, in deren Rahmen Benutzer mit<br />

Werkzeugen in Interaktion treten können. Wegen ihrer zentralen Rolle ist die Workbench<br />

synonym mit der Benutzeroberfläche der Eclipse-Plattform als Ganzem. Sie<br />

stellt das Fenster dar, das beim Starten der Plattform angezeigt wird (siehe Abbildung<br />

3.2). Die Workbench-Implementierung nutzt die von SWT und JFace zur Verfügung<br />

gestellte Infrastruktur graphischer Bedienelemente.<br />

Abbildung 3.2: Screenshot der Eclipse-Workbench<br />

Das Eclipse-Plattform UI-Paradigma basiert auf der Anordnung von Editoren und<br />

Views (nicht zu verwechseln mit den bereits vorgestellten SWT-Viewern) in Perspektiven.<br />

Aus Benutzersicht besteht das Fenster der Workbench aus verschiedenen Editoren<br />

und Views. <strong>Eine</strong> bestimmte Anordnung von Editoren und Views zur Laufzeit auf dem<br />

Bildschirm stellt eine Perspektive dar.<br />

Editoren dienen dem Öffnen, Editieren und Speichern von Workspace-Ressourcen.<br />

Editoren sind mit der Workbench integriert und können die übergreifenden Menüs der<br />

Workbench um editorspezifische Aktionen (im Sinne einer JFace-Aktion) erweitern.<br />

Ein generischer Texteditor zur textuellen Bearbeitung beliebiger Ressourcen ist Teil<br />

der Basisplattform. Andere Plugins erweitern die Plattform um spezifischere Editoren.<br />

Views stellen Informationen von Ressourcen dar, die gerade in der Workbench bearbeitet<br />

werden. <strong>Eine</strong> View unterstützt üblicherweise einen Editor, indem sie Zusatzinformationen<br />

über die gerade im Editor geöffnete Ressource anzeigt. Abbildung 3.3 zeigt<br />

einen Java-Editor und die OutlineView, welche die Felder und Methoden der aktuell<br />

im Editor geöffneten Klasse anzeigen. Im Kontext eines aktiven graphischen Editors<br />

gibt die OutlineView einen Gesamtüberblick über das aktuell im Editor geöffnete Dia-<br />

32


Abbildung 3.3: Integration von Java-Editor und die OutlineView<br />

gramm. <strong>Eine</strong> View kann aber auch an die aktuelle Darstellung einer anderen View<br />

gekoppelt sein und deren Inhalt bezüglich eines anderen Aspekts visualisieren. Die<br />

Plattform umfasst eine Menge von Standard-Views. Spezifischere Views können auch<br />

hier als Erweiterung der Plattform durch andere Plugins integriert werden.<br />

Abbildung 3.4: Architektur der Workbench (vgl. [Eclc])<br />

Die technische Realisierung der Workbench in Form einer Kompositionshierarchie<br />

ist in Abbildung 3.4 zu sehen. Die Workbench beinhaltet ein oder mehrere WorkbenchWindows.<br />

Zu jedem WorkbenchWindow wiederum gehört genau eine Workbench-<br />

Page 1 . Das WorkbenchWindow stellt einen Rahmen <strong>für</strong> Inhalte, sowie Fensteroperationen<br />

bereit (Minimieren, Maximieren, Schließen). Die WorkbenchPage ist verantwortlich<br />

<strong>für</strong> den Inhalt des Fensters. Views und Editoren gehören zu einer Page und<br />

sind dieser über ViewFactory- und EditorManager-Indirektionsmechanismen zugeord-<br />

1 Seit Eclipse v2, vorher konnte ein WorkbenchWindow auch mehrere WorkbenchPages besitzen<br />

33


net. Die ViewFactory verwaltet eine Menge von Views. Der EditorManager ist neben<br />

der Verwaltung von Editoren außerdem verantwortlich <strong>für</strong> die Verwaltung deren<br />

gemeinsamer Ressourcen. Beiden gemein ist, dass Referenzen verwaltet werden und<br />

nicht die Editoren oder Views selbst. Die ViewFactory hält außerdem in Form eines<br />

Referenz-Zählers fest, Bestandteil wie vieler Perspektiven eine View ist. Perspektiven<br />

werden mittels Layout-Informationen definiert, die bestimmen, wie Views und Editoren<br />

in der Perspektive angeordnet werden. Perspektiven referenzieren somit also Views<br />

und Editoren von WorkbenchPages. Der Verwaltungsmechanismus mittels Referenzen<br />

dient der Effizienzoptimierung, da er „lazy-loading“ von Views und Editoren ermöglicht.<br />

Abbildung 3.5: Workbench Konzepte(vgl. [Eclc])<br />

Abbildung 3.5 illustriert den oben geschilderten Zusammenhang. Man sieht die vorgestellten<br />

Elemente in Form ihrer graphischen Darstellung. Die graphische Hierarchie<br />

korrespondiert weitgehend mit der Kompositionshierarchie. Ausnahme hierbei ist die<br />

Perspektive, die man in ihrer graphischen Funktion intuitiv als Container der Views<br />

und Editoren interpretiert, die tatsächlich aber nur eine Layout-Abstraktion darstellt.<br />

Die graphische Darstellung der Perspektive entspricht somit nicht ihrer Rolle in der<br />

Kompositionshierarchie.<br />

Plugins können die Workbench um eigene Editoren und Views erweitern. Da<strong>für</strong> sind<br />

die Schnittstellen IEditorPart bzw. IViewPart eingerichtet, deren Implementierung<br />

dann über einen Erweiterungspunkt der Workbench in die Plattform eingebunden<br />

wird. Editoren und Views dienen der Darstellung von Informationen, unterscheiden<br />

sich jedoch in ihren Benutzungs-Paradigmen. Der Hauptunterschied zwischen<br />

Editoren und Views besteht darin, dass ein Editor der Bearbeitung einer explizit<br />

ihm zugewiesenen Workspace-Ressource dient. Dies geschieht im Rahmen eines<br />

Öffnen-Bearbeiten-Speichern-Schließen-Kreislaufes. Das Speichern findet hierbei zu<br />

Benutzer-definierten Zeitpunkten statt. Ein Editor muss also in der Lage sein, die Än-<br />

34


derungen, die an seiner geöffneten Ressource durchgeführt wurden, auch zu persistieren.<br />

Diese Anforderung an den Editor wird als Teil der IEditorPart-Schnittstelle<br />

in Form einer zu realisierenden save()-Methode formuliert. Die IViewPart-Schnittstelle<br />

definiert eine solche Methode nicht. Dies hängt damit zusammen, dass Änderungen<br />

an einer Ressource, die über eine View erfolgen, direkt an die zugrundeliegende<br />

Datenquelle weitergeleitet werden. Im Gegensatz zum Editor, bei dem der Speichervorgang<br />

durch eine separate Aktion des Benutzers in der Benutzeroberfläche ausgelöst<br />

wird, werden Änderungen in Views direkt persistiert.<br />

Ein zentrales Workbench-Konzept sind Selektionen. Diese dienen der Koordination<br />

von Views und Editoren untereinander. Views sollen Informationen zu bestimmten<br />

Objekten anzeigen. Welches Objekt gerade in einer View dargestellt wird, hängt in aller<br />

Regel von den Selektionen anderer Views oder Editoren des aktuellen Workbench-<br />

Fensters ab. Die OutlineView z.B. (vgl. Abbildung 3.3) zeigt immer die Struktursicht<br />

derjenigen Ressource, die gerade im aktuellen Editor geöffnet ist.<br />

Anstatt Plugins im Rahmen der Implementierung bezüglich dieses Aspekts eng zu<br />

koppeln, wird ein sogenannter SelectionService benutzt, um die Integration von Editoren<br />

und Views aus verschiedenen Plugins zu realisieren. Dieser Service wird benachrichtigt,<br />

wenn sich im aktuellen Fenster der Workbench eine Selektion ändert<br />

und gibt diese Information dann weiter an registrierte IWorkbenchPart-Instanzen<br />

(IEditorPart und IViewPart sind Spezialisierungen von IWorkbenchPart).<br />

Technisch umgesetzt ist dies so, dass eine WorkbenchPage einen derartigen Selection-<br />

Service darstellt (IWorkbenchPart ist Spezialisierung von ISelectionService).<br />

Damit verfügt jedes WorkbenchWindow über genau einen SelectionService.<br />

Der SelectionService verfolgt die Selektionen des aktuellen WorkbenchParts und propagiert<br />

Selektionsänderungen an registrierte Listener. Derartige Selektionsereignisse<br />

treten auf, wenn sich die Selektion des aktuellen WorkbenchParts verändert oder wenn<br />

ein bisher inaktives, anderes WorkbenchPart aktiviert wird. Beide Möglichkeiten können<br />

durch Benutzerinteraktionen oder programmatisch ausgelöst werden. Für eine<br />

View, in der ein Objekt gerade selektiert ist, ist unerheblich, welche anderen Views<br />

an ihrer Selektion interessiert sind. Somit kann man die Plattform um neue Views erweitern,<br />

ohne bestehenden Code anpassen zu müssen. Existierende Views, die anderen<br />

Views Selektionen zur Verfügung stellen, bleiben also unverändert wenn neue Views<br />

deren Selektionen nutzen.<br />

Abbildung 3.6 illustriert den SelectionService als zentrales Konzept, das Selektionsänderungen<br />

von sogenannten SelectionProvidern an eine Menge von sogenannten SelectionListenern<br />

propagiert. Ein Objekt, das die ISelectionProvider-Schnittstelle<br />

realisiert, kann als Quelle von Selektionen dienen. Damit seine Selektionen auch tatsächlich<br />

vom SelectionService an registrierte Listener propagiert werden, muss das<br />

Objekt in seiner Funktion als SelectionProvider bei der aktuellen WorkbenchPage<br />

(dem SelectionService) angemeldet werden. Analog registrieren sich ISelection-<br />

Listener-Instanzen, um über Selektionsänderungen informiert zu werden.<br />

Aus Benutzersicht stellt eine Selektion eine Menge markierter Elementen eines gra-<br />

35


Abbildung 3.6: SelectionService, SelectionProvider und SelectionListener (vgl.<br />

[Eclb])<br />

Abbildung 3.7: Typhierarchie von ISelection (vgl. [Eclb])<br />

phischen Bedienelements, wie einer Tabelle oder eines Baumes dar. <strong>Eine</strong> Selektion<br />

kann natürlich auch ein markiertes Textfragment eines Editors sein. Diese graphischen<br />

Elemente sind plattformintern alle als Java-Objekte repräsentiert. Die bereits angesprochene<br />

MVC-Implementierung von JFace unterstützt das Übersetzen zwischen diesen<br />

beiden Repräsentationen. Die meisten JFace-Widgets implementieren standardmäßig<br />

die ISelectionProvider-Schnittstelle und können derart direkt am Selection-<br />

Service registriert werden.<br />

Intern ist eine Selektion eine Datenstruktur, die aus denjenigen Modellobjekten besteht,<br />

die mit den aktuell graphisch markierten Elementen korrespondieren. Der SelectionService<br />

leitet ein Selektionsereignis in Form einer ISelection-Instanz an die<br />

Interessenten dieses Ereignisses weiter. Die Eclipse-Plattform verfeinert den Selektionsbegriff<br />

in drei ISelection-Unterkonzepte. Zum einen in IStructuredSelection,<br />

die eine <strong>strukturierte</strong> Menge von selektierten Objekten darstellt und zum<br />

anderen in ITextSelection und IMarkSelection, die beide Textselektionen<br />

kapseln (Abbildung 3.7).<br />

36


Über die hier vorgestellten Workbench-Konzepte hinaus, gibt es noch eine Reihe anderer<br />

Mechanismen, deren Beschreibung hier allerdings den Rahmen sprengen würde.<br />

Für eine detaillierte Beschreibung der Eclipse-Plattform und insbesondere auch der<br />

Workbench, sei hiermit an [CR06] verwiesen.<br />

3.2 GEF und Draw2D<br />

Das Graphical Editing Framework (GEF) ([GEF]) ist ein Rahmenwerk <strong>für</strong> die Entwicklung<br />

graphischer Editoren und Views in Eclipse. Die Voraussetzung <strong>für</strong> den Einsatz<br />

von GEF ist die Existenz eines Modells, das graphisch dargestellt und/oder editiert<br />

werden soll. Dabei stellt GEF keinerlei spezielle Voraussetzung an das zu visualisierende<br />

Modell.<br />

Im Rahmen dieser Diplomarbeit sind zwei Eclipse-Views als Teile der <strong>Simulationsumgebung</strong><br />

mit Hilfe von GEF entstanden: Erstens zur Visualisierung der statischen<br />

internen Struktur einer NarrativeDescription (Abschnitt 5.2) und zweitens zur graphischen<br />

Darstellung einer ExecutionModel-Instanz (Abschnitt 5.3).<br />

Grundsätzlich folgt GEF dem MVC-Paradigma. Gemäß diesem Ansatz werden View<br />

und Modell über einen Controllermechanismus entkoppelt. Mit View ist hierbei die<br />

graphische Darstellung des zugrundeliegenden Modells im Sinne des MVC-Entwurfsmusters<br />

[GHJV95] gemeint 2 . Der Controller ist da<strong>für</strong> verantwortlich, Benutzerinteraktionen<br />

mit graphischen Elementen in Modelloperationen und -modifikationen zu übersetzen.<br />

Abbildung 3.8: Grobe Sicht der GEF-Architektur (vgl. [Ecle])<br />

2 Diese View kann beispielsweise mittels Eclipse-View Mechanismus realisiert werden.<br />

37


Abbildung 3.8 illustriert die generelle Funktionsweise von GEF (dargestellt durch die<br />

Ellipse in der Mitte der Abbildung). Das Rahmenwerk verbindet ein Modell mit einer<br />

graphischen Darstellung dieses Modells. Außerdem bietet es Mechanismen zur Umwandlung<br />

von Benutzereingaben, die das Rahmenwerk in Form von SWT-Ereignissen<br />

empfängt, in Requests. Derartige Requests werden vom Controller bearbeitet und resultieren<br />

in Operationen auf dem Modell, die in Commands gekapselt werden.<br />

3.2.1 Draw2D<br />

Teil des GEF-Rahmenwerks ist ein Darstellungsplugin namens Draw2D. Draw2D<br />

stellt sogenannte Figures und LayoutManager zur Verfügung, die die graphische Ebene<br />

einer GEF Applikation ausmachen. Draw2D kann unabhängig von GEF benutzt<br />

werden, ist <strong>für</strong> sich alleine genommen aber kein MVC-Rahmenwerk. Es dient rein<br />

der graphischen Darstellung. Im Rahmen von GEF wird Draw2D zur Darstellung der<br />

View im Sinne des MVC-Ansatzes genutzt.<br />

Draw2D ist ein leichtgewichtiges Toolkit zur Darstellung spezieller graphischer Komponenten,<br />

sogenannter Figures. <strong>Eine</strong> Figure ist leichtgewichtig in dem Sinne, dass sie<br />

ein reines Java-Objekt ist und keine Repräsentation in Form einer Betriebssystem-<br />

Ressource besitzt. Figures können via Vater-Kind-Beziehung zusammengesetzt werden<br />

und besitzen damit eine hierarchische Struktur. Jede Figure hat eine rechteckige<br />

Begrenzung (bounds), in deren Rahmen sie und ihre geschachtelten Kinder gezeichnet<br />

werden. LayoutManager können eingesetzt werden, um Kinder auf besondere Art und<br />

Weise in ihrer Vater-Figure anzuordnen.<br />

Abbildung 3.9: Grobe Sicht der Draw2D-Architektur (vgl. [Ecld])<br />

Draw2D baut auf der Graphikfunktionalität von SWT auf. Dies geschieht allerdings<br />

nicht direkt, sondern mittels einer Zwischenschicht, dem zu Draw2D gehörendem<br />

38


LightweightSystem. In SWT werden Canvas-Instanzen als Zeichenflächen <strong>für</strong> beliebige<br />

Graphiken genutzt. LightweightSystem erweitert Canvas und stellt eine<br />

Abstraktionsschicht dar, in der nicht mehr Widgets als Bedienelemente eingesetzt<br />

werden, sondern Figures als Bausteine der graphischen Darstellung dienen. Dabei ist<br />

das LightweightSystem verantwortlich <strong>für</strong> die in ihm dargestellten Figures. Außerdem<br />

leitet es SWT-Ereignisse (die es in seiner Eigenschaft als Canvas von SWT<br />

empfängt) an den SWTEventDispatcher weiter, der diese in Ereignisse <strong>für</strong> bestimmte<br />

Figures übersetzt. Spezielle Ereignisse, die das LightweightSystem auffordern, seinen<br />

Inhalt zu zeichnen, werden an den UpdateManager weitergeleitet. Dieser koordiniert<br />

die durch ihn ausgelösten Aktionen „Zeichnen“ und „Layouten“. Wenn sich bestimmte<br />

Eigenschaften von Figures wie Größe oder Aussehen ändern, sorgt der UpdateManager<br />

da<strong>für</strong>, dass nur einmal die Aktion „Layouten“ ausgeführt wird und dann im Rahmen<br />

der Aktion „Zeichnen“ nur die Region neugezeichnet wird, die von der Änderung<br />

betroffen ist. Abbildung 3.9 illustriert, wie die verschiedenen Draw2D-Konzepte miteinander<br />

verknüpft sind.<br />

Auf Klassenebene sind Figures Realisierungen der IFigure-Schnittstelle oder Spezialisierungen<br />

der Standard-Implementierung Figure. Das Draw2D-Rahmenwerk<br />

besitzt eine umfangreiche Klassenbibliothek, zu deren Umfang folgende Elemente gehören:<br />

• diverse geometrische Standard-Figures (Kreis, Ellipse, Rechteck, etc.),<br />

• Behälter-Figures, die eine Menge von transparenten Schichten (Layer) beinhalten<br />

können,<br />

• Figures, die als Rahmen <strong>für</strong> andere dienen (Border),<br />

• spezielle Figures, die Verbindungen zwischen zwei anderen Figures darstellen<br />

(Connection),<br />

• verschiedene Anker (ConnectionAnchor), mittels derer Verbindungen an<br />

einer Figure festgemacht werden,<br />

• verschiedenste LayoutManager (LayoutManager) und Routing-Algorithmen<br />

<strong>für</strong> Connections (ConnectionRouter),<br />

• viele weitere Helferklassen, die den Umgang mit Figures erleichtern.<br />

Als Beispiel <strong>für</strong> eine Behälter-Figure sei hier die Klasse LayeredPane genannt,<br />

die neben einer primären Schicht noch weitere Schichten enthält. Dazu gehört z.B.<br />

der ConnectionLayer <strong>für</strong> die Darstellung von Verbindungen (in Form von Connections)<br />

zwischen regulären Figuren der primären Schicht und der FeedbackLayer, in<br />

dem Effekte bestimmter Benutzeraktionen dargestellt werden (z.B. Farbänderung bei<br />

Selektion einer Figure).<br />

39


EditParts<br />

Im Rahmen der Darstellung eines Modells mittels GEF wird jedes graphisch darzustellende<br />

Modellelement durch eine Instanz einer Unterklasse von Figure repräsentiert.<br />

Benutzerinteraktionen mit der graphischen Modelldarstellung werden von GEF<br />

in Modellmanipulationen übersetzt. Dies geschieht mittels Controller-Mechanismus.<br />

Zu jedem graphisch visualisierten Modellelement gibt es einen Controller. In der GEF-<br />

Nomenklatur ist der Controller ein EditPart. EditParts verbinden Modell und die graphische<br />

Darstellung des Modells und sind ebenso verantwortlich <strong>für</strong> die Durchführung<br />

von Modellmodifikationen. Da<strong>für</strong> besitzen EditParts Helferobjekte, sogenannte Edit-<br />

Policies, die einen Großteil der Operationen auf dem Modell vornehmen.<br />

EditParts bilden eine hierarchische Struktur. Jedes EditPart hat eine Menge von Kindern.<br />

Normalerweise korrespondiert dies mit einer Vater-Kind Beziehung im Modell.<br />

Beispielsweise kann ein Modell aus einem Diagramm mit Knoten bestehen. In diesem<br />

Falle gäbe es ein Diagramm-EditPart, das Kinder in Form von Knoten-EditParts<br />

besitzt.<br />

Abbildung 3.10: MVC Architektur in GEF (vgl. [Ecle])<br />

Die Vater-Kind Beziehungen der EditParts übertragen sich in die Figure-Hierarchie.<br />

Die Figure des Vater-EditParts beinhaltet die Figures der Kinder-EditParts. Die graphische<br />

Darstellung des Vaters kann auch durch eine zusammengesetzte Figure erfolgen,<br />

von der eine der Teil-Figures die ausgezeichnete Rolle des ContentPane innehat. Die<br />

Figure jedes Kindes wird dann dieser ContentPane-Figure als Kind hinzugefügt. Resultat<br />

hiervon ist, dass es drei mehr oder weniger parallele Hierarchien gibt. Abbildung<br />

3.10 veranschaulicht diesen Sachverhalt graphisch.<br />

Verbindungen (Connections) zwischen zwei Figures stellen hierbei die Ausnahme dar<br />

und sind nicht Teil der Baumstruktur. Graphische Verbindungen zwischen Figures repräsentieren<br />

üblicherweise Assoziationen zwischen Modellelementen. Assoziationen<br />

sind in der Regel auch durch spezielle EditParts auf Seite der Controller repräsentiert,<br />

konkret durch Spezialisierungen des ConnectionEditParts. Auf Seiten der graphischen<br />

Darstellung werden Verbindungen in Form spezieller Figures als Connection-Instanzen<br />

visualisiert. Die ConnectionEditParts werden von Quell- und Ziel-<br />

EditParts an jedem Ende verwaltet. Diese EditParts sind die Controller der Modellelemente,<br />

die graphisch miteinander verbunden werden.<br />

40


Die gesamten Verantwortlichkeiten eines EditParts umfassen somit:<br />

• die Kopplung eines Modellelements an eine graphische Darstellung und die Synchronisation<br />

zwischen graphischer Darstellung und Modell,<br />

• die Verwaltung seiner strukturellen Eigenschaften in Form von Kind-EditParts<br />

und ConnectionEditParts,<br />

• die Unterstützung von Modellmodifikationen.<br />

Das Bindeglied zwischen SWT und GEF ist ein EditPartViewer. Der EditPartViewer<br />

dient der graphischen Darstellung von EditParts. Es wird unterschieden zwischen<br />

zwei Arten von EditPartViewern in GEF. Zum einen gibt es einen graphischer Viewer<br />

zur Darstellung von Figures und zum anderen einen Viewer zur Visualisierung von<br />

Bäumen ([GEF]). Im Zusammenhang dieser Arbeit ist nur der graphische EditPart-<br />

Viewer von Interesse, der <strong>für</strong> die Darstellung von Figures genutzt wird. Jeder Edit-<br />

PartViewer ist außerdem SelectionProvider. EditParts sind hierbei die Selektionseinheiten,<br />

die anderen Viewern als Selektionen zur Verfügung gestellt werden. Der graphische<br />

EditPartViewer kapselt ein Draw2D FigureCanvas und damit gleichzeitig<br />

das Draw2D LightweightSystem. Der Viewer selbst wird von einem WorkbenchPart<br />

(im Regelfall ein EditorPart oder ViewPart) genutzt. Auch <strong>für</strong> den graphischen Edit-<br />

PartViewer gibt es mehrere Spezialisierungen. Beispielsweise gibt es Viewer mit oder<br />

ohne Scrollbalken. Wurzelelement jedes EditPartViewers ist ein spezielles EditPart,<br />

genannt RootEditPart. Dieses hat keine Entsprechung im Modell, sondern definiert<br />

einen gemeinsamen Kontext <strong>für</strong> die EditParts, die als Controller <strong>für</strong> bestimmte Modellelemente<br />

dienen. GEF bietet auch hier verschiedene Standardimplementierungen, die<br />

z.B. eingebaute Zoom-Funktionalität zur Verfügung stellen.<br />

Abbildung 3.11: Erzeugung von EditParts mittels EditPartFactory (vgl. [Ecle])<br />

Der Inhalt von Viewer bzw. RootEditPart ist in der Regel ein Wurzelmodellelement,<br />

das eine Kompositionshierarchie darstellt und den graphischen Viewer mit darzustel-<br />

41


lenden Elementen versorgt. Die EditPartFactory des Viewers ist da<strong>für</strong> verantwortlich,<br />

ein Modellelement in ein passendes EditPart zu übersetzen, das dann als Inhalt des<br />

RootEditParts gesetzt wird. Die dazugehörige Figure wird zur RootFigure des Root-<br />

EditParts hinzugefügt. Das auf diese Weise gewonnene Kind-EditPart des RootEdit-<br />

Parts erzeugt jetzt wiederum seine Kinder-EditParts, analog zu der hierarchischen<br />

Struktur des Modells. Die Kinder-EditParts erzeugen ihrerseits weitere Kinder- und<br />

ConnectionEditParts, bis das gesamte Modell in Form von Controllern und Figures<br />

aufgespannt wurde. Die Erzeugung von EditParts wird hierbei immer an die EditPart-<br />

Factory des Viewers delegiert. Abbildung 3.11 illustriert diesen Zusammenhang.<br />

Bisher wurde nur über die reine Darstellung eines Modells mittels Figures gesprochen,<br />

in der zudem jedem Modellelement ein Controller in Form eines EditParts zugeordnet<br />

ist. GEF dient aber nicht nur der graphischen Darstellung von Modellen, sondern<br />

ebenso deren Bearbeitung. Editieren ist üblicherweise die komplexeste Tätigkeit, <strong>für</strong><br />

die ein EditPart verantwortlich ist. Das EditPart muss nicht nur Modelländerungen<br />

durchführen, sondern dem Benutzer auch graphische Rückmeldungen <strong>für</strong> seine Interaktionen<br />

mit der View geben. Benutzerinteraktionen werden von GEF in Form von<br />

Requests (Typ Request) gekapselt, die zur Bearbeitung an ein EditPart weitergereicht<br />

werden. Als Resultat dieser Anfrage gibt das EditPart einen Command (Klasse<br />

Command) zurück, der Modellmodifikationen kapselt. Liefert das EditPart einen leeren<br />

oder unausführbaren Command zurück, bedeutet das, dass die Anfrage nicht vom<br />

EditPart bearbeitet werden kann und die aktuelle Benutzerinteraktion nicht zulässig<br />

ist.<br />

EditParts bearbeiten derartige Anfragen nicht selber, sondern delegieren sie an sogenannte<br />

EditPolicies, die Strategien (im Sinne des gleichnamigen Entwurfsmusters) zur<br />

Behandlung von Anfragen sind. Jede EditPolicy ist verantwortlich <strong>für</strong> eine Editier-<br />

Teilaufgabe oder eine Menge von zusammengehörenden Aufgaben. Auf diese Weise<br />

ist gemeinsames Editier-Verhalten in verschiedenen EditPart-Implementierungen wiederverwendbar.<br />

Über die Anforderung von Commands hinaus werden Requests auch<br />

eingesetzt, um visuelle Rückmeldungen <strong>für</strong> bestimmte Benutzerinteraktionen von einem<br />

EditPart zu erhalten oder auch die Durchführung beliebiger Aktionen durch ein<br />

EditPart selbst anzustoßen.<br />

Weitere zentrale GEF-Konzepte wie Tools und Palette werden an dieser Stelle nicht<br />

vorgestellt, weil sie <strong>für</strong> den Rahmen dieser Arbeit nicht relevant sind. <strong>Eine</strong>n guten<br />

Überblick, der über die hier vorgestellten Inhalte hinausgeht, bietet [Ecle].<br />

3.3 Eclipse Modeling Framework<br />

Das Eclipse Modeling Framework ([EMF, BSM + 03]) ist ein Eclipse-basiertes Rahmenwerk,<br />

das Funktionalitäten <strong>für</strong> die Metamodell-Modellierung und zur Codegenerierung<br />

zur Verfügung stellt. Es unterstützt die Entwicklung von Werkzeugen und Anwendungen,<br />

die auf einem <strong>strukturierte</strong>n Datenmodell basieren. Aus einer Modellspezifikation<br />

kann EMF eine Menge von Java-Klassen generieren, die das Modell darstel-<br />

42


len. Ebenso kann EMF andere Artefakte, die die Arbeit mit dem Modell unterstützen<br />

und vereinfachen, erzeugen. Beispielsweise wird <strong>für</strong> jedes Metamodell automatisch<br />

ein eigener Editor generiert, über den Modellinstanzen erstellt und bearbeitet werden<br />

können. Modelle können mittels Java-Annotationen, XML-Dokumenten oder mit Hilfe<br />

von Modellierungswerkzeugen wie Rational Rose ([Rat]) spezifiziert werden.<br />

Die beiden Metamodelle, die im Rahmen dieser Arbeit entstanden sind, wurden beide<br />

mit Hilfe des Rational Software Architect ([Rat]) in Form eines UML-Klassendiagramms<br />

spezifiziert. EMF wurde eingesetzt <strong>für</strong> die Generierung des Modell Java-<br />

Codes.<br />

Der Einsatz von EMF bringt viele Vorteile mit sich:<br />

• Verwaltung bidirektionaler Assoziationen: EMF übernimmt die Verwaltung<br />

bidirektionaler Assoziationen zwischen zwei Metamodellelementen. Das bedeutet,<br />

dass bei der Modifikation eines Endes einer bidirektionalen Assoziation das<br />

jeweils andere Ende automatisch entsprechend angepasst wird. <strong>Eine</strong> manuelle<br />

Lösung, die dies generisch umsetzt, ist aufwändig zu realisieren und deshalb<br />

fehleranfällig.<br />

• Notifikationsmechanismus: Ein mittels EMF generiertes Modell besitzt einen<br />

Notifikationsmechanismus, der auf feingranulare Änderungen an Elementen einer<br />

Modellinstanz reagiert. Damit eignen sich EMF-Modelle ideal <strong>für</strong> den Einsatz<br />

in einer MVC-Architektur [GHJV95], in der ein Controller üblicherweise<br />

an Veränderungen seines Modellelements interessiert ist.<br />

• Persistierung: EMF bringt Lösungen zur Persistierung von Modellinstanzen,<br />

zum Beispiel in Form eines XML-Dokuments, mit. Dieser Mechanismus ist einfach<br />

erweiterbar, so dass bei Bedarf eine eigene Realisierung zur Modellserialisierung<br />

und -persistierung eingesetzt werden kann.<br />

• Undo/Redo-Unterstützung: EMF bietet außerdem eine Transaktionskomponente,<br />

über deren Nutzung das Modell u.a. Undo/Redo-Funktionalitäten erlangt.<br />

• Validierung von Modellinstanzen: Mittels dem EMF-Validationsrahmenwerk<br />

können Modellinstanzen bezüglich ihrer Integrität geprüft werden. Darunter fallen<br />

modellintrinsische Beschränkungen wie Kardinalitäten, aber auch explizit<br />

im Rahmen der Entwicklung des Metamodells formulierte semantische Einschränkungen<br />

(constraints).<br />

EMF besteht aus drei Kernbestandteilen, die jeweils in eigenen Eclipse-Plugins enthalten<br />

sind: EMF-Core, EMF-Edit und EMF-Codegen.<br />

3.3.1 EMF-Core<br />

EMF-Core beinhaltet den konzeptionellen und technischen Kern von EMF. Die Kernkonzepte<br />

werden in einem eigenen Metamodell namens Ecore festgehalten. Dieses<br />

43


Modell dient der Repräsentation anderer Modelle in EMF. Ecore selbst ist ein EMF-<br />

Modell und damit sein eigenes Metamodell. Metamodelle, die mittels Ecore-Mechanismen<br />

repräsentiert werden, heißen in der EMF-Nomenklatur Core-Modelle. Dabei<br />

ist die Frage zu stellen, warum EMF sein eigenes Modell zur Metamodellierung benutzt<br />

und nicht das UML-Metamodell. Dies ist zu beantworten damit, dass Ecore einem<br />

Modellierer nur eine kleine und vereinfachte Menge aller UML-Modellierungselemente<br />

zur Verfügung stellt. Die UML bietet beispielsweise Elemente zur Modellierung<br />

dynamischen Verhaltens, während Ecore nur Elemente zur Modellierung einer<br />

statischen Struktur zur Verfügung stellt.<br />

Ecore unterstützt eine Menge von „higher-level“ Konzepten, die über die Konzepte, die<br />

in Java repräsentierte sind, hinausgehen. Dazu gehören bidirektionale Beziehungen,<br />

Containment-Beziehungen und spezielle Datenstrukturen wie Enumerationen 3 . EMF<br />

generiert effizienten und korrekten Java-Code <strong>für</strong> all diese Konstrukte und erspart dem<br />

Entwickler damit Aufwand und Zeit.<br />

Abbildung 3.12: Typhierarchie von Ecore im Überblick<br />

Im Rahmen der Metamodellierung werden die Strukturausprägungen <strong>für</strong> eine Menge<br />

von Modellinstanzen des Metamodells definiert und die Typen von Objekten, die Art<br />

der Daten, die sie beinhalten können sowie die Beziehungen zwischen ihnen, spezifiziert.<br />

Formal geschieht dies mittels der Konzepte, die Ecore dem Modellierer an die<br />

Hand gibt. Die Klassenhierarchie von Ecore ist Inhalt der Abbildung 3.12.<br />

3 Seit Java 5 sind Enumerationen auch Teil der Java Language Specification ([JLS]).<br />

44


Abbildung 3.13: Vereinfachter Ausschnitt aus dem Ecore-Modell<br />

An dieser Stelle sollen die Kernkonzepte dieser Klassenhierarchie vorgestellt werden.<br />

Abbildung 3.13 illustriert in Form einer vereinfachten Darstellung (bestimmte Superklassen<br />

wurden der Übersichtlichkeit halber ausgeblendet) die Beziehungen verschiedener<br />

Ecore-Konzepte untereinander. Beispielsweise besitzen die Klassen EClass,<br />

EAttribute und EReference im vollständigen Ecore-Modell den gemeinsamen<br />

Supertypen ENamedElement, der das name-Attribut, das hier <strong>für</strong> jede Klasse separat<br />

dargestellt wurde, definiert.<br />

Die hier vorgestellten Elemente sind:<br />

• EClass dient der Modellierung von Klassen im Metamodell. Klassen haben<br />

einen Namen und eine Menge beliebiger Attribute und Referenzen. Zur Unterstützung<br />

von Vererbung kann eine Klasse eine beliebige Anzahl anderer Klassen<br />

als Superklassen angeben 4 .<br />

• EAttribute modelliert Attribute einer Klasse. Jedes Attribut hat einen Namen<br />

und einen Typ.<br />

• EDataType stellt den Typen eines Attributes dar. Es repräsentiert Typen, die<br />

zwar in Java definiert sind, nicht aber in EMF. Jeder Datentyp besitzt ebenfalls<br />

einen Namen.<br />

• EReference wird benutzt zur Modellierung von Assoziationsbeziehungen zwischen<br />

Klassen. Jede Referenz stellt ein Ende einer Assoziationsbeziehung dar.<br />

Ähnlich wie Attribute verfügen Referenzen über je einen Namen und einen Typen.<br />

Allerdings muss der Typ dem der EClass am jeweiligen Assoziationsende<br />

entsprechen. Wenn die Assoziation in beide Richtungen navigierbar ist, muss es<br />

dementsprechend zwei dazu korrespondierende Referenzen geben.<br />

Abbildung 3.14 illustriert die vorgestellten Ecore-Elemente anhand eines Ausschnitts<br />

aus dem ExecutionModel-Metamodell, welches als Teil des konzeptuellen Lösungsansatzes<br />

an späterer Stelle (vgl. Abschnitt 4.2) vorgestellt wird. Transition und<br />

4 Im Rahmen der Metamodellierung kann Mehrfachvererbung verwendet werden.<br />

45


Abbildung 3.14: Beispiel <strong>für</strong> Metamodellierung mittels Ecore<br />

EventExecution sind EClass-Instanzen, die als Inhalt ihres name-Attributs jeweils<br />

„Transition“ bzw. „EventExecution“ haben. Zwischen den beiden Elementen<br />

Transition und EventExecution gibt es zwei graphisch repräsentierte Assoziationsbeziehungen,<br />

die jeweils in beide Richtungen navigierbar sind. Jedes der<br />

vier resultierenden Assoziationsenden wird durch eine EReference-Instanz repräsentiert,<br />

deren Typ jeweils EventExecution bzw. Transition ist. Darüber hinaus<br />

sieht man, dass Transition drei Attribute in Form von EAttribute-Instanzen<br />

mit dem Java-Typ Boolean besitzt. Man könnte diese Attribute jeweils in Form einer<br />

EReference mit Typ EBoolean (der eine Spezialisierung von EClass darstellt)<br />

modellieren, aber im Rahmen dieses Beispiels wurde der Attribut-Ansatz gewählt, um<br />

den Unterschied zwischen Attributen und Referenzen zu verdeutlichen. Attribute besitzen<br />

einen Typen, der nicht in EMF repräsentiert wird, während der Typ einer Referenz<br />

eine Spezialisierung von EClass ist (und damit insbesondere von EMF repräsentiert<br />

wird). Standardmäßig besitzt Ecore eine Menge von EDataType-Instanzen<br />

(und damit EClass-Spezialisierungen), die die gebräuchlichsten Java-Typen darstellen,<br />

darunter auch der bereits erwähnte Typ EBoolean als Repräsentation des Java-<br />

Typs Boolean.<br />

public interface EObject extends Notifier {<br />

EClass eClass();<br />

Object eGet(EStructuralFeature feature);<br />

void eSet(EstructuralFeature feature, Object newValue);<br />

}<br />

...<br />

Abbildung 3.15: Auszug aus der EObject-Schnittstelle<br />

Außer der in Ecore festgehaltenen konzeptionellen Basis beinhaltet EMF Core eine<br />

Java-Implementierung von Ecore. Auf Java-Ebene existiert zu jeder der Typen in Abbildung<br />

3.12 eine korrespondierende Schnittstelle und eine Implementierung derselben.<br />

Es gibt zum Beispiel das EObject-Interface und die EObjectImpl-Klasse als<br />

Realisierung dieser Schnittstelle. Diese Schnittstellen und Klassen bilden die Basis <strong>für</strong><br />

46


den im Rahmen der Codegenerierung entstehenden Code eigener Metamodelle. Wie<br />

bereits oben dargestellt, ist jedes Element eines Metamodells ein spezielles EObject<br />

(vgl. Abbildung 3.12). Dieser Sachverhalt spiegelt sich ebenso im resultierenden Modellcode<br />

wider. Der EMF-Codegenerator generiert <strong>für</strong> jedes Metamodellelement eine<br />

Schnittstelle und eine Implementierung in Form einer Klasse, die diese und ggf. weitere<br />

Schnittstellen realisiert. Alle generierten Schnittstellen erweitern die EObject-<br />

Schnittstelle. Da im Metamodell durchaus auch Mehrfachvererbung erlaubt ist, wird<br />

diese auf Java-Ebene mittels Schnittstellen nachgebildet 5 .<br />

Die EObject-Schnittstelle kapselt EMF-spezielle Methoden, die insbesondere während<br />

der Laufzeit genutzt werden können, um Metadaten eines Modellelements zu ermitteln.<br />

Abbildung 3.15 stellt einen Ausschnitt dieser Schnittstelle dar. Hiermit können<br />

statische, strukturelle Informationen abgefragt werden. Beispielsweise die EClass<br />

des Objekts (mittels eClass()-Methode). Auch dynamische Informationen, wie z.B.<br />

der aktuelle Wert eines bestimmten Attributs des Objekts (mittels eGet()-Methode)<br />

lassen sich ermitteln.<br />

3.3.2 EMF Edit<br />

EMF Edit stellt Funktionalität zur Darstellung und Bearbeitung von Modellinstanzen<br />

EMF-basierter Metamodelle bereit. Diese Funktionalität ist spezifisch auf das jeweilige<br />

Metamodell zugeschnitten und wird im Rahmen der Codegenerierung des Metamodells<br />

als separate Komponente erzeugt. Idealerweise dienen die generierten EMF<br />

Edit-Artefakte als Ausgangspunkt <strong>für</strong> die Entwicklung einer kompletten Anwendung<br />

um das generierte Modell herum. Das bedeutet, dass der von EMF Edit generierte<br />

Code zur Modelldarstellung und -bearbeitung nicht nur genutzt, sondern auch modifiziert<br />

wird. Dabei muss EMF Edit bezüglich seines Design und seiner Werkzeuge zum<br />

einen eine gute Integration mit der Umgebung (in unserem Fall der Eclipse-Plattform)<br />

anstreben und zum anderen größtmögliche Flexibilität erreichen, um dem Entwickler<br />

die Erweiterung und Modifikation zu erleichtern. Zu diesem Zweck generiert EMF<br />

Edit <strong>für</strong> jedes Metamodell standardmäßig zwei Plugins. Das eine ist das Edit-Plugin,<br />

das UI-unabhängigen Code beinhaltet und das andere das Editor-Plugin, in dem die<br />

UI-abhängigen Komponenten enthalten sind.<br />

Das UI-unabhängige Plugin beinhaltet von der graphischen Benutzeroberfläche unabhängige<br />

Abstraktionen zur Darstellung und Bearbeitung des Modells. Beispielsweise<br />

ermöglicht das <strong>It</strong>emProvider-Konzept die Nutzung und Bearbeitung von Modellelementen<br />

in einer speziellen Umgebung mit Hilfe eins Adaptionsmechanismus. In EMF<br />

nehmen Adapter grundsätzlich zwei verschiedene Rollen ein. Sie sind gleichermaßen<br />

Beobachter wie Adapter eines Modellelements im Sinne der jeweiligen Entwurfsmuster<br />

(vgl. [GHJV95]). In ihrer Rolle als Adapter können sie Modellelemente um die<br />

im Rahmen von Darstellung und Bearbeitung geforderten Eigenschaften erweitern.<br />

Als Beobachter können sie Zustandsänderungen des Modellelements weiterleiten an<br />

registrierte Listener.<br />

5 Java unterstützt Mehrfachvererbung nur auf abstrakter Ebene zwischen Schnittstellen.<br />

47


Das UI-abhängige Plugin verwendet das Workbench-Rahmenwerk der Eclipse-Plattform,<br />

inklusive JFace und SWT, um eine Benutzeroberfläche zum Erstellen und Bearbeiten<br />

von Modellinstanzen zu realisieren. Dazu gehören unter anderem ein Wizard<br />

zur Erstellung eines neuen Modells und ein Editor zur Bearbeitung eines existierenden<br />

Modells.<br />

3.3.3 EMF Codegen<br />

Der Hauptbestandteil des EMF Codegen Plugins ist der Codegenerator von EMF. Dieser<br />

dient der Erzeugung von Java-Code aus Core-Modellen 6 . Dazu gehören wie vorher<br />

beschrieben <strong>für</strong> jedes Modellelement eine Schnittstelle und eine Klasse, die diese<br />

Schnittstelle realisiert. Die Implementierung ist in der Regel nicht vollständig, da dass<br />

Modell Operationen und abgeleitete Eigenschaften beinhaltet, deren Semantik im Rahmen<br />

der Modellierung nicht im Detail spezifiziert wird. In derartigen Fällen generiert<br />

der Codegenerator leere Methodenrümpfe, die vom Entwickler manuell implementiert<br />

werden können. Jede Methode ist mit einer Metainformation versehen 7 , die aussagt, ob<br />

die Methode generiert wurde oder nicht. Wenn der Entwickler eine Methode manuell<br />

realisiert, ändert er diese Metainformation dementsprechend. Somit ist <strong>für</strong> den Codegenerator<br />

ersichtlich, dass der Methodenrumpf nicht automatisch generiert wurde. Er<br />

berücksichtigt dies in weiteren Durchläufen, indem die nicht-generierten Fragmente<br />

übernommen und nicht überschrieben werden. Dadurch ist es möglich, Modellierung<br />

und Implementierung zeitgleich verzahnt durchzuführen.<br />

Die meisten Informationen, die der Codegenerator <strong>für</strong> die Codeerzeugung benötigt,<br />

sind im Core-Modell gespeichert. Darüber hinaus müssen dem Generator aber noch<br />

andere Informationen mitgeteilt werden, beispielsweise in welche Plugins und Java-<br />

Pakete der Code generiert werden soll. Diese Daten sind nicht Teil des Core-Modells,<br />

können aber vom Benutzer in Form eines sogenannten Generatormodells spezifiziert<br />

werden. Das Generatormodell ist ebenso wie Ecore selbst ein EMF-Modell. In der Tat<br />

ist es so, dass das Generatormodell Zugriff auf alle Daten zur Codeerzeugung bietet,<br />

darunter auch die des Core-Modells. Aus technischer Sicht ist das Generatormodell ein<br />

Dekorator [GHJV95] des Core-Modells. Die Klassen des Generatormodells dekorieren<br />

Ecore Klasse, beispielsweise dient GenClass der Dekoration von EClass. Dieser<br />

Ansatz der Trennung zwischen Core-Modell und Generatormodell gewährleistet, dass<br />

das Core-Modell keine spezifischen Codeerzeugungsinformationen beinhaltet. Nachteil<br />

ist, dass die Konsistenz zwischen beiden Modelle verloren gehen kann. Hier<strong>für</strong><br />

gibt es Mechanismen im Generatormodell, über die das Generatormodell automatisch<br />

an Änderungen im Core-Modell angepasst wird.<br />

Das Eclipse Modeling Framework bietet über die hier vorgestellten Kernplugins hinaus<br />

noch diverse weitere Komponenten. Deren Beschreibung geht ebenso wie eine detailliertere<br />

Beschreibung der oben vorgestellten Plugins über den Umfang dieser Arbeit<br />

hinaus. Weitergehende Informationen sind nachzulesen in [BP06, BSM + 03].<br />

6 Ein mittels Ecore-Mechanismen repräsentiertes Metamodell ist ein Core-Modell.<br />

7 Dies geschieht in Form einer Annotation im Javadoc-Header der Methode.<br />

48


3.4 ViPER<br />

ViPER (Visual Tooling Platform for Model-Based Engineering) [ViP] ist eine Eclipsebasierte<br />

Entwicklungsumgebung <strong>für</strong> den UML-basierten Entwurf kleiner eingebetteter<br />

Systeme. Sie wird derzeit am Lehr- und Forschungsgebiet Informatik 3 der RWTH<br />

Aachen als Forschungsprototyp entwickelt. Zu ihren Bestandteilen gehören UML-<br />

Modelldiagrammeditoren, C-Code Generatoren, ein Toolkit zur natürlichsprachlichen<br />

Beschreibung von Anwendungsfällen sowie die Unterstützung der MeDUSA-Methode,<br />

die ebenfalls am Lehr- und Forschungsgebiet Informatik 3 entwickelt wird. Außer<br />

der Eclipse-Plattform bilden die folgenden weiteren Eclipse Projekte die technische<br />

Grundlage von ViPER:<br />

• Eclipse C/C++ Development Environment (CDT)<br />

• Eclipse Modeling Framework (EMF)<br />

• Eclipse Modeling Framework Technologies (EMFT)<br />

• Eclipse Model Development Tools (MDT)<br />

• Eclipse Graphical Editing Framework (GEF)<br />

• Eclipse Generative Modeling Technologies (GMT)<br />

• Apache Commons Logging<br />

Diese Bestandteile machen zusammen die ViPER-IDE aus:<br />

• ViPER Platform<br />

• ViPER UML2<br />

• ViPER MeDUSA<br />

• ViPER NaUTiluS<br />

Sie werden im Folgenden kurz erläutert.<br />

3.4.1 ViPER Platform<br />

ViPER Platform bildet die Basis der ViPER-IDE. Sie stellt ein offenes Rahmenwerk<br />

zur Implementierung von GEF-basierten graphischen Editoren <strong>für</strong> EMF-basierte Modelle<br />

dar. Zum weiteren Funktionsumfang gehören Mechanismen <strong>für</strong> Modelltransformationen<br />

(Modell-zu-Modell, Modell-zu-Code und Modell-zu-Text) und zur Validierung<br />

von Modellen.<br />

49


ViPER Platform ist weiter untergliedert in Bestandteile, die diese einzelnen Funktionalitäten<br />

kapseln:<br />

• ViPER Core<br />

• ViPER MTF<br />

• ViPER VMF<br />

ViPER Core enthält Basiskomponenten <strong>für</strong> die Arbeit mit EMF-basierten Modellen.<br />

Dies beinhaltet Konstrukte zur deklarativen Spezifikation von Modellmanipulationen,<br />

sowie Konstrukte zur Unterstützung und Vereinfachung der Navigation auf EMF-basierten<br />

Modellen. Außerdem gehören diverse ViPER-spezifische Basisklassen <strong>für</strong> graphische<br />

Elemente wie Wizards oder Kontextmenüs (GUI-Bestandteile im Allgemeinen) zum<br />

Kern von ViPER.<br />

ViPER MTF (Model Transformation Framework) ist ein Rahmenwerk, das dem Entwickler<br />

Basisinfrastruktur zur Transformation und Validierung von Modellen zur Verfügung<br />

stellt. Unter die Modelltransformationen fallen sowohl Modell-zu-Modell Transformationen<br />

als auch die Codegenerierung aus Modellen.<br />

ViPER VMF (Visual Modeling Framework) kapselt Konstrukte und Erweiterungsmöglichkeiten,<br />

die der Implementierung GEF-basierter Editoren <strong>für</strong> EMF-basierte Modelle<br />

dienen. VMF ist vom konzeptionellen Umfang her die größte Einzelkomponente der<br />

ViPER-IDE. Sie ist intern weiter unterteilt in die folgenden Bestandteile:<br />

• ViPER VMF Core<br />

• ViPER VMF GraphModel<br />

• ViPER VMF MCD<br />

• ViPER VMF UI<br />

• ViPER VMF UI Extensible<br />

Für diese Arbeit stellt ViPER VMF allerdings keinen Schwerpunkt dar. Aus diesem<br />

Grund wird an dieser Stelle auf eine detaillierte Beschreibung der Einzelkomponenten<br />

verzichtet. [Wal07, Do08] stellen die einzelnen VMF-Bestandteile in ihren Arbeiten<br />

ausführlicher vor.<br />

3.4.2 ViPER UML2<br />

ViPER UML2 baut auf den Basiskomponenten von ViPER Platform auf und bietet eine<br />

UML2-Entwicklungsumgebung mit graphischen Editoren <strong>für</strong> alle gängigen UML2-<br />

Diagrammtypen.<br />

50


Intern besteht es aus den folgenden drei großen Bestandteilen:<br />

• ViPER UML2 Core stellt grundlegende Bausteine einer UML-Entwicklungsumgebung<br />

zur Verfügung. Dazu gehören beispielsweise diverse UML-spezifische Klassen<br />

sowie eine Reihe von Wizards, die der Erzeugung von UML-Modellen dienen.<br />

• ViPER UML2 Codegen enthält die Implementierung eines Codegenerators auf<br />

Basis von ViPER MTF. Dieser Generator dient der Erzeugung von C-Code aus<br />

UML2-Modellen.<br />

• ViPER UML2 VME (Visual Modeling Environment) stellt die Referenzimplementierung<br />

einer graphischen Modellierungsumgebung auf Basis des ViPER<br />

VMF Rahmenwerks dar. Im Rahmen dieser Referenzimplementierung sind bislang<br />

zehn der insgesamt 13 UML2-Diagrammtypen entstanden.<br />

3.4.3 ViPER MeDUSA<br />

ViPER MeDUSA (Method for UML2-based Design of Embedded Software Applications)<br />

ist eine Design-Methode <strong>für</strong> die Erstellung von Software-Anwendungen eingebetteter<br />

Systeme [LN07]. Die MeDUSA Methode beruht auf Ansätzen der COMET-<br />

Methode [Gom00] und stellt die Use Case- und modellgetriebene Entwicklung in den<br />

Vordergrund. ViPER MeDUSA enthält prototypische Grundsteine <strong>für</strong> die methodengestützte<br />

Entwicklung mit MeDUSA in Form eines Wizards <strong>für</strong> die Subsystem Identification.<br />

Die Subsystem Identification ist eine Teilaktivität des MeDUSA-Prozesses. Die<br />

Durchführung des Gesamtprozesses als Folge von Teilaktivitäten basiert technisch auf<br />

CheatSheets. CheatSheets sind ein Eclipse-spezifisches Konzept, das der Durchführung<br />

von Abläufen dient. Außerdem beinhaltet ViPER MeDUSA eine in das Eclipse-<br />

Hilfesystem integrierte Prozessbeschreibung. [Her07, LN07] beschreiben den zu diesem<br />

Zeitpunkt aktuellen Stand und Inhalt von ViPER MeDUSA im Detail.<br />

3.4.4 ViPER NaUTiluS<br />

ViPER NaUTiluS (Narrative Use Case Description Toolkit for Evaluation and Simulation)<br />

umfasst in seiner Form als Toolkit <strong>für</strong> die natürlichsprachliche Beschreibung<br />

von Anwendungsfällen mehrere Komponenten. Hierzu gehören bislang Funktionalitäten<br />

zum Editieren natürlichsprachlicher Anwendungsfallbeschreibungen sowie zur<br />

Simulation derselben. Die Simulationskomponente ist im Rahmen dieser Arbeit entstanden.<br />

Der Grundstein <strong>für</strong> die Funktionalitäten zum Erstellen und Bearbeiten von<br />

Anwendungsfallbeschreibungen wurde im Zuge von [Wal07] gelegt. Über die bereits<br />

bestehenden Komponenten hinaus ist <strong>für</strong> die Zukunft außerdem die Unterstützung der<br />

Evaluierung von Anwendungsfallbeschreibungen geplant.<br />

ViPER NaUTiluS setzt sich grob zusammen aus den folgenden zwei Teilkomponenten:<br />

51


• ViPER NaUTiluS Core<br />

• ViPER NaUTiluS Simulation<br />

NaUTiluS Core wiederum besteht intern aus einer Menge von Plugins, die verschiedene<br />

Inhalte kapseln:<br />

Abbildung 3.16: Screenshot der NarrativeModel-Perspektive<br />

• sc.viper.nautilus.core.resources umfasst Metamodelle und<br />

UML-Profile <strong>für</strong> die Verwendung mit Instanzen dieser Modelle. Konkret sind<br />

das die Metamodelle von NarrativeModel, ExecutionModel und SimulationModel<br />

8 . Sie werden referenziert von den Generatormodellen (siehe Abschnitt 3.3)<br />

der jeweiligen Modellplugins.<br />

• sc.viper.nautilus.core.executionmodel ist im Zuge dieser Arbeit<br />

entstanden und beinhaltet den mittels EMF generierten Code des Execution-<br />

Models sowie das Generatormodell, welches die EMF-Codegenerierung steuert.<br />

Bestimmte Methoden der Implementierungsklassen wurden nachträglich manuell<br />

implementiert. Außerdem beinhaltet dieses Plugin die Klassenbibliothek zur<br />

Berechnung einer ExecutionModel-Instanz zu einer gegebenen NarrativeModel-<br />

Instanz. Die Arbeitsweise und die technische Realisierung dieser Komponente<br />

werden ausführlich thematisiert in Abschnitt 5.1.<br />

8 ExecutionModel und SimulationModel werden als Teil des konzeptuellen Lösungsansatzes dieser<br />

Arbeit in Kapitel 4 eingeführt.<br />

52


• sc.viper.nautilus.core.narrativemodel kapselt Schnittstellen<br />

und Implementierungsklassen des NarrativeModels. Der Großteil dieses Codes<br />

wurde mit Hilfe von EMF aus der Spezifikation des NarrativeModels generiert.<br />

• sc.viper.nautilus.core.ui.editors beinhaltet einen Editor zur Bearbeitung<br />

von NarrativeModel-Instanzen. Dieser Editor hat seinen Ursprung in<br />

der Arbeit von Andreas Walter [Wal07] und wurde seitdem am Lehrstuhl weiterentwickelt.<br />

Der ehemals monolithische Editor, der die verschiedenen Facetten<br />

der NarrativeModel-Editierung abgedeckt hat (Synchronisation mit Use Case-<br />

Modell, Bearbeitung von NarrativeDescriptions, Bearbeitung von Flüssen), wurde<br />

zerlegt in einen Editor zur Bearbeitung je einer NarrativeDescription und ihrer<br />

Flüsse und eine Menge unterstützender Views. Diese Aufteilung folgt dem<br />

Eclipse UI-Paradigma, wie es in Abschnitt 3.1.3 vorgestellt wurde. Der Screenshot<br />

in Abbildung 3.16 illustriert diesen Sachverhalt anhand der Perspektive zur<br />

Bearbeitung eines NarrativeModels. Oben links erkennt man die ModelView, die<br />

eine modellzentrische Sicht auf den Eclipse Benutzerarbeitsplatz (Workspace)<br />

bietet und es ermöglicht, die interne hierarchische Struktur eines Modells unterhalb<br />

der Dateisystemebene zu navigieren. Die ModelView dient als SelectionProvider<br />

und stellt anderen WorkbenchParts beliebige Modellelemente des<br />

aktuell geöffneten Modells zur Verfügung. Unterhalb der ModelView sieht man<br />

die FlowView und die OutlineView, die einen Überblick über die interne Struktur<br />

einer NarrativeDescription bzw. des zugrundeliegenden Use Case-Modells<br />

bieten. Zentral in der Mitte der Abbildung befindet sich der NarrativeDescriptionEditor,<br />

der als SelectionListener diejenigen NarrativeDescriptions zur Bearbeitung<br />

anzeigt, die ihm von der ModelView zur Verfügung gestellt werden.<br />

Oberhalb des Editors ist die UseCaseNarrativeSyncView platziert, die darüber<br />

informiert, welche Elemente des Use Case-Modells durch Elemente des NarrativeModels<br />

repräsentiert werden. Unterhalb des Editors dargestellt ist die Eclipseeigene<br />

PropertiesView, die die Eigenschaften eines jeden selektierten Elements<br />

der Workbench anzeigt.<br />

NaUTiluS Simulation umfasst zwei Plugins, die beide als Ergebnis dieser Arbeit entstanden<br />

sind:<br />

• sc.viper.nautilus.simulation.simulationmodel kapselt die<br />

EMF-Implementierung des SimulationModels und das zugrundeliegende Generatormodell.<br />

• sc.viper.nautilus.simulation.ui beinhaltet graphische Komponenten,<br />

die der Darstellung und Bearbeitung des SimulationModels dienen. Dazu<br />

gehören neben einem Editor, der der Aufzeichnung des Simulationsablaufs<br />

dient, eine View zur graphischen Darstellung einer ExecutionModel-Instanz (vgl.<br />

Abschnitt 5).<br />

53


Kapitel 4<br />

Konzeptueller Lösungsansatz<br />

Zu Beginn dieses Kapitels wird eine Ausführungssicht auf eine NarrativeModel-Instanz<br />

beschrieben. Diese motiviert die Bildung eines speziellen Metamodells, das im zweiten<br />

Abschnitt dieses Kapitels erläutert wird. Im letzten Teil dieses Kapitels wird schließlich<br />

ein weiteres Metamodell vorgestellt, welches simulationsspezifische Konzepte<br />

kapselt.<br />

4.1 Ausführungssicht auf eine NarrativeModel-Instanz<br />

Im Zuge der simulierten Ausführung eines Anwendungsfalles löst man sich von der<br />

gesamtheitlichen Sicht auf diesen Anwendungsfall und interessiert sich nur noch <strong>für</strong><br />

einzelne Szenarien. Jeder Anwendungsfall besteht aus einer Menge von Verhaltensausprägungen,<br />

die in seiner zugehörigen NarrativeDescription als Flüsse und Beziehungen<br />

zwischen Flüssen modelliert werden. Diese Verhaltensausprägungen kommen<br />

dann während der Ausführung zustande durch die vielfältigen Pfade vom Anfang des<br />

Anwendungsfalles zu seinem Ende. Ein Szenario ist demnach ein bestimmter solcher<br />

Pfad und beschreibt eine komplette Benutzerinteraktion mit dem modellierten System<br />

als Sequenz von Ereignissen (Events des NarrativeModels). Inklusionen und Erweiterungsanker<br />

werden aufgelöst und durch Aktionssequenzen der durch sie ausgelösten<br />

Verhaltensausführung dargestellt.<br />

Wendet man diesen Ansatz nicht nur auf ein einzelnes Szenario sondern auf ein vollständige<br />

NarrativeModel-Instanz an, erhält man eine ausführungsorientierte Sicht auf<br />

diese.<br />

Jede NarrativeModel-Instanz spannt bezogen auf diese Sicht einen Ausführungsgraphen<br />

auf. Dessen Knoten werden dargestellt durch die atomaren Verhaltensatome (also<br />

Aktionen) der Flüsse. Die Kanten zwischen Knoten bilden dann intuitiv die Übergänge<br />

zwischen Aktionen. Diese Übergänge sind nicht explizit als Elemente des Narrative-<br />

Models modelliert, sondern folgen aus der Semantik der Flüsse und ihrer Beziehungen<br />

55


untereinander. Man betrachtet also nur Aktionen auf der feinsten Verhaltensebene. Use<br />

Cases, NarrativeDescriptions und Flüsse haben im Ausführungsgraphen keine explizite<br />

Darstellung, sondern werden in der Ausführung implizit durchlaufen, abhängig davon,<br />

in welchem Fluss die aktuell ausgeführte Aktion definiert wurde. Ein Pfad durch<br />

den Graphen von der ersten bis zur letzten Aktion eines Anwendungsfalles beschreibt<br />

dann jeweils ein Szenario als Sequenz von Aktionen.<br />

Die Kanten des Graphen geben an, welche anderen Aktionen von einer bestimmten<br />

Aktion aus in einem Schritt erreichbar sind. Der einfachste Fall, in dem eine Aktion B<br />

in einem Schritt erreichbar von A ist, liegt vor, wenn beide Aktionen in der Verhaltenssequenz<br />

desselben Flusses hintereinander definiert sind. <strong>Eine</strong> andere Möglichkeit liegt<br />

vor, wenn direkt hinter A eine Inklusion eines Flusses oder eine Erweiterung durch<br />

einen Fluss stattfindet, dessen erste Aktion B ist. Das erste Ereignis eines Ausnahmeflusses<br />

ist erreichbar von jeder Aktion der überwachten Flüsse aus.<br />

Verzweigungsmöglichkeiten, also Knoten mit mehreren ausgehenden Kanten, in diesem<br />

Graphen entstehen als Resultat von Ausnahmeflüssen und Erweiterungsbeziehungen<br />

zwischen Flüssen. Während der Ausführung gibt es an den Erweiterungsankern<br />

die Möglichkeit zu alternativem Verhalten zu verzweigen. Außerdem werden nach<br />

Ausführung einer jeden Aktion die Bedingungen der anliegenden Ausnahmeflüsse<br />

evaluiert. Abhängig von den Resultaten dieser Prüfung wird dann der entsprechende<br />

Ausnahmefluss aktiv.<br />

<strong>Eine</strong> Modellinstanz ohne Elemente, die Verzweigungmöglichkeiten induzieren, besitzt<br />

keinerlei Verhaltensausprägungen, die über den Standardablauf hinausgehen. Der Anwendungsfall<br />

beschreibt dann genau ein Szenario. Während der Ausführung gibt es<br />

keinerlei Entscheidungspunkte, an denen sich Verhalten verzweigen kann.<br />

Zur graphischen Darstellung eines solchen Graphen bieten sich Aktivitätsdiagramme<br />

an. Laut UML-Spezifikation [Obj07b] dienen Aktivitäten zum einen der Modellierung<br />

von Sequenzen von „lower-level“ Verhalten und zum anderen der Bedingungen zur<br />

Steuerung dieses Verhaltens. Jede Aktivität besteht aus einer Menge von Aktionen,<br />

die in ihrer Sequenz während der Ausführung das Verhalten der Aktivität darstellen.<br />

Es liegt damit nahe, die oben beschriebene Sicht auf eine textuelle Anwendungsfallbeschreibung<br />

durch ein Aktivitätsdiagramm darzustellen. Dabei stellt die Aktivität die<br />

durch den auszuführenden Anwendungsfall beschriebene Benutzerinteraktion als Ganzes<br />

dar. Die Aktionen der Aktivität entsprechen den einzelnen Verhaltensatomen der<br />

Benutzerinteraktion. Diese wiederum werden repräsentiert durch Aktionen derjenigen<br />

Flüsse, die im Rahmen der Ausführung des ursprünglichen Anwendungsfalles erreichbar<br />

sind.<br />

Abbildung 4.1 zeigt eine derartige Sicht auf die textuelle Beschreibung der Anwendungsfälle<br />

des Geldautomatenbeispiels aus Abschnitt 2.3. Die Ausführung des Anwendungsfalles<br />

Geld abheben ist hierbei die Gesamtaktivität. Diese besteht aus Aktionen<br />

(Action in der UML), die den Aktionen (Action des NarrativeModels)<br />

der verschiedenen Flüsse des NarrativeModels entsprechen. Use Case-Start und Use<br />

Case-Ende sind hierbei durch die entsprechenden InitialState- und ActivityFinalState-<br />

56


Abbildung 4.1: Aktivitätsdiagramm zum Geldautomatenbeispiel<br />

Knoten des Aktivitätsdiagramms gesondert ausgezeichnet. Man beachte, dass man im<br />

Rahmen der graphische Darstellung die inkludierten und erweiternden Verhaltenssequenzen<br />

auch als <strong>strukturierte</strong> Aktionen darstellen kann (d.h. aus Sicht der Geld abheben-Aktivität<br />

ist die Ausführung von Authentifizieren atomar). Zur Veranschaulichung<br />

der Ausführungssicht ist die in Abbildung 4.1 gewählte Darstellung allerdings besser<br />

geeignet.<br />

4.2 ExecutionModel<br />

Als Grundlage <strong>für</strong> die technische Umsetzung der Simulation, bietet es sich an, die<br />

oben geschilderte Ausführungssicht auf eine NarrativeModel-Instanz in einem eigenen<br />

Metamodell festzuhalten. Die Besonderheit der Ausführungssicht ist, dass die Strukturinformationen<br />

des NarrativeModels aufgelöst werden und eine atomare Sicht auf<br />

einzelne Ausführungsschritte in Form von Aktionen eingenommen wird. Die anderen<br />

Ereignisarten wie Inklusionen und Erweiterungsanker werden aufgelöst zu Sequenzen<br />

von Aktionen.<br />

Die Ausführungssicht ist konzeptionell verschieden von der NarrativeModel-Sicht.<br />

Ziel der Modellierung von textuellen Anforderungsbeschreibungen ist es, Verhalten<br />

in den da<strong>für</strong> vorgesehenen Strukturen zu beschreiben. Diesem Ansatz liegen bereits<br />

gewisse Modellierungsprinzipien zugrunde, z.B. das Prinzip des Erzielens höchstmöglicher<br />

Wiederverwendung von Verhalten. Die Ausführungssicht löst diese Abstraktio-<br />

57


nen wieder auf und bricht sie hinunter auf Sequenzen von möglichen „lower-level“<br />

Aktionen. Damit ist die Ausführungssicht konzeptionell anders als diejenige Sicht, die<br />

während des Modellierens des NarrativeModels eingenommen wird.<br />

Das ExecutionModel ist das Metamodell, welches der Repräsentation der Verhaltenssicht<br />

auf das NarrativeModel dient. Zu jeder NarrativeModel-Instanz kann eine ExecutionModel-Instanz<br />

generiert werden. Diese ist dann die Grundlage <strong>für</strong> die Simulation.<br />

4.2.1 Zentrale Elemente<br />

Das ExecutionModel hat zwei zentrale Konzepte, die sich aus der ausführungsorientierten<br />

Darstellung eines NarrativeModels als Graph ergeben. Die Knoten des Graphen<br />

stellen Verhaltensatome dar, die Kanten zwischen den Knoten die Übergänge von einem<br />

Verhaltensatom zum anderen. Dieser Sachverhalt wird im ExecutionModel durch<br />

die zwei Konzepte EventExecution und Transition abgebildet. EventExecutions<br />

entsprechen den Knoten des Graphen und kapseln die simulierte Ausführung<br />

von Events des NarrativeModels. Transitionen stellen die Kanten des Graphen dar und<br />

modellieren damit die Übergänge zwischen je zwei EventExecutions.<br />

Abbildung 4.2: Grobe Struktur des ExecutionModels<br />

Inhalt der Abbildung 4.2 sind die beiden Metaklassen EventExecution und Transition.<br />

Jede EventExecution referenziert genau ein Event des NarrativeModels.<br />

Dabei kann ein Event selbst durchaus durch mehrere EventExecutions referenziert<br />

werden. Man sieht außerdem, dass eine EventExecution immer eine oder mehrere<br />

Vorgänger- und Nachfolger-Transitionen besitzt. Jede Transition wiederum hat genau<br />

eine oder keine Vorgänger- und Nachfolger-EventExecution. <strong>Eine</strong> Transition besitzt<br />

keinen Vorgänger bzw. Nachfolger, wenn sie in das Modell hinein- bzw. aus dem Modell<br />

heraus führt (Use Case-Start, Use Case-Ende). Die Metaklasse Step stellt eine<br />

Generalisierung von EventExecution und Transition dar und beschreibt, dass<br />

sowohl EventExecutions als auch Transitionen einen Ausführungsschritt darstellen.<br />

58


EventExecutions und ExecutionContexts<br />

In Abbildung 4.2 sieht man außerdem die zu Transitionen und EventExecutions gehörenden<br />

Konzepte ExecutionContextChange und ExecutionContext. Jede<br />

EventExecution besitzt einen ExecutionContext, der den aktuellen Ausführungskontext<br />

charakterisiert. Der Ausführungskontext beinhaltet eine Liste aller NarrativeDescriptions<br />

und Flusskontexte (Context aus NarrativeModel), die bis zum Erreichen<br />

des durch die aktuelle EventExecution dargestellten Ereignisses durchlaufen wurden.<br />

Mehrere EventExecutions haben denselben ExecutionContext, wenn zum einen ihre<br />

referenzierten Ereignisse als Teil der Verhaltenssequenz des selben Flusses definiert<br />

wurden und zum anderen dieser Fluss während der Ausführung jeweils auf dem selben<br />

Weg erreicht wurde (d.h., über die selbe Folge von Transitionen und EventExecutions).<br />

Abbildung 4.3: Event repräsentiert<br />

von zwei EventExecutions<br />

Abbildung 4.4: Reduzierende<br />

Kontextwechsel<br />

Abbildung 4.3 zeigt die Situation, dass ein Fluss F2 aus einem Fluss F1 von zwei<br />

verschiedenen Positionen aus inkludiert wird. In diesem Fall besitzt das dazugehörige<br />

ExecutionModel zwei Entsprechungen in Form von EventExecutions <strong>für</strong> das Ereignis<br />

A in Fluss F2. Es ist wichtig, zwischen Ereignissen, die auf verschiedenen Wegen erreichbar<br />

sind, zu unterscheiden, weil die Rücksprungspunkte aus einem inkludierten<br />

oder erweiternden Fluss zurück in den Ursprungsfluss abhängig sind von den Punkten,<br />

aus denen das Zusatzverhalten ursprünglich zur Ausführung kam. Die beiden Event-<br />

Executions, die A darstellen, haben jeweils auch verschiedene Ausführungskontexte.<br />

Transitionen und ExecutionContextChanges<br />

Transitionen koppeln zwei EventExecutions und können bezogen auf den Übergang<br />

von einer zur anderen EventExecution einen Kontextwechsel (Metaklasse ExecutionContextChange)<br />

induzieren. In diesem Fall sind beide über die Transition<br />

gekoppelten EventExecutions mit unterschiedlichen ExecutionContexts assoziiert. Induziert<br />

eine Transition keinen Kontextwechsel, ist sie eine diesbezüglich invariante<br />

Transition. Ein Kontextwechsel kann expandierend sein, d.h., die Liste der Flusskontexte<br />

vergrößert sich vom ExecutionContext der Vorgänger-EventExecution zu dem<br />

59


der Nachfolger-EventExecution. Anders ausgedrückt, wird durch eine expandierende<br />

Transition ein neuer Fluss betreten. Das Gegenteil ist die reduzierende Transition,<br />

durch die ein Fluss verlassen wird und die die Ausführung zu dem ursprünglichen<br />

Vorgängerfluss zurückkehren lässt. <strong>Eine</strong> Transition heißt also reduzierend, wenn sie<br />

ein oder mehrere reduzierende Kontextwechsel induziert.<br />

Die Abbildung 4.4 illustriert, in welchem Fall eine Transition mehrere reduzierende<br />

Kontextwechsel zur Folge hat. Dargestellt ist die Situation, in der der Fluss F1 an der<br />

Position I1 den Fluss F2 inkludiert. Dieser wiederum inkludiert von I2 aus den Fluss<br />

F3. Der Fluss F3 führt nur die Aktion A aus. Der Nachfolger der A-EventExecution 1<br />

ist in diesem Fall die B-EventExecution 2 innerhalb F1. Wäre die Inklusion I2 in F2<br />

nicht an letzter Position in der Verhaltenssequenz, hätte die B-EventExecution einen<br />

Nachfolger in F2. Die Transition, die den Übergang von B-EventExecution zu A-<br />

EventExecution darstellt, induziert somit zwei reduzierende Kontextwechsel. Der Verlauf<br />

des Kontrollflusses durch die Flüsse ist in der Abbildung mittels gestrichelter Linie<br />

kenntlich gemacht.<br />

Abbildung 4.5: Verfeinerung der ExecutionContextChange-Metaklasse<br />

Die abstrakte ExecutionContextChange-Metaklasse wird bezüglich ihrer Eigenschaft,<br />

die eine Ausführungskontextreduktion oder -expansion bewirkt, in ExecutionContextExpansion<br />

oder ExecutionContextReduction spezialisiert<br />

(siehe Abbildung 4.5).<br />

ExecutionContextExpansion hat ein Attribut namens trigger, welches eine<br />

Referenz auf ein Event-Element des NarrativeModels darstellt. Dies wird in Fällen<br />

benötigt, in denen ein Fluss an verschiedenen Stellen denselben anderen Fluss inkludiert<br />

oder von demselben anderen Fluss erweitert wird. In diesen Fällen sind all diese<br />

Inklusionen oder Erweiterungsanker mit demselben Kontext (Context des NarrativeModels)<br />

des inkludierten oder erweiternden Flusses verbunden. Daher hält man<br />

den trigger als Zusatzinformation in Form desjenigen Ereignisses, das die expandierende<br />

Transition ausgelöst hat, fest. Somit kann man unterscheiden, ob der inkludier-<br />

1 die EventExecution, die die Ausführung von A darstellt<br />

2 die EventExecution, die die Ausführung von B darstellt<br />

60


te oder erweiternde Fluss auf verschiedenen Wegen erreicht wurde. Im Falle einer<br />

Erweiterung ist der trigger also ein ExtensionAnchor, im Falle einer Inklusion<br />

eine Inclusion. Auch bei expandierenden Transitionen, die in einen Ausnahmefluss<br />

führen, greift dieser Mechanismus. Der trigger ist dann eine Action. Ohne die<br />

trigger-Zusatzinformation wären beispielsweise die Inklusionen I1 und I2 in Abbildung<br />

4.3 bezüglich ihrer induzierten Kontextwechsel nicht unterscheidbar, da beide<br />

auf NarrativeModel-Ebene denselben Übergang vom Kontext des Flusses F1 in den<br />

Kontext des Flusses F2 bewirken.<br />

Analog zum trigger-Attribut in ExecutionContextExpansion besitzt ExecutionContextReduction<br />

ein mergeEvent-Attribut. Dieses ist ebenfalls eine Referenz<br />

auf eine Event-Instanz und wird benötigt, um eindeutig die Rücksprungsbedingung<br />

zu bestimmten, unter der eine Transition stattfindet.<br />

4.2.2 Transitionstypen<br />

Abbildung 4.6: Eigenschaften der Transition-Metaklasse<br />

Wie bereits beschrieben spricht man von einer kontextinvarianten Transition, wenn<br />

sie den Übergang zwischen zwei EventExecutions desselben Ausführungskontexts bewirkt.<br />

Damit findet aus Sicht der NarrativeModel-Struktur (mit den Strukturelementen<br />

Model, NarrativeDescription, Flow, Event) insbesondere auch nur ein Übergang<br />

zwischen zwei Ereignissen eines Flusses statt. Expandierende Transitionen können in<br />

diesem Sinne aber auch Übergange zwischen Ereignissen verschiedener Flüsse oder<br />

gar zwischen verschiedenen Flüssen in verschiedenen NarrativeDescriptions bewirken.<br />

Transitionen, über die ein Anwendungsfall gestartet oder beendet wird, über-<br />

61


schreiten sogar die Modellgrenze. Die Information, welche Art von Übergang durch<br />

eine Transition induziert wird, steckt in der TransitionType-Enumeration (Abbildung<br />

4.6). Jede Transition bewirkt einen Übergang einer der vier Arten (Event, Flow,<br />

Description, Model). Klar ist, dass eine Model-Transition gleichzeitig eine Description-Transition<br />

ist und die wiederum eine Flow-Transition. Übergänge aller Art sind<br />

Event-Transitionen.<br />

Außerdem wird bei Transitionen unterschieden danach, ob sie Modellvariationen oder<br />

semantische Variationen darstellen. Im Falle der Modellvariationen wird zudem weiter<br />

differenziert nach ihrer Art. Variationspunkte sind Stellen im ExecutionModel, an<br />

denen sich der Kontrollfluss verzweigen kann. Jede EventExecution, die mehr als eine<br />

nachfolgende Transition besitzt, induziert somit einen Variationspunkt. Diese Punkte<br />

kommen zustande als Resultat von Erweiterungen und Ausnahmeflüssen, die vom<br />

Standardablauf abweichende Verhaltensalternativen anbieten. Verzweigungsmöglichkeiten,<br />

die über eben diese modellintrinsischen Beziehungen wie Erweiterung und<br />

Ausnahmebehandlung zustande kommen, sind Modellvariationen. Im Gegensatz dazu<br />

resultieren semantische Variationen nicht aus Elementen des NarrativeModels. Semantische<br />

Variationen sind Gegenstand der Behandlung des folgenden Abschnitts.<br />

Ob eine Transition eine Modellvariation oder eine semantische Variation darstellt,<br />

kann über die isSemanticVariation-Eigenschaft von Transition ermittelt werden.<br />

Im Falle der Modellvariation ist die Frage nach dem zugrundeliegenden NarrativeModel-Konzept<br />

von Interesse. Hier bestehen die Möglichkeiten der Extension und der Exception,<br />

die in ModelVariationType festgehalten werden (siehe Abbildung 4.6).<br />

Invariante Transitionen stellen grundsätzlich Modellvariationen vom Typen None dar.<br />

4.2.3 Semantische Variationen<br />

Abbildung 4.7: Semantische Variation durch Inklusion abstrakten Verhaltens<br />

62


An semantischen Variationspunkten stehen Verzweigungsmöglichkeiten zur Auswahl,<br />

die nicht durch NarrativeModel-intrinsische Semantik (also Erweiterungen und Ausnahmen),<br />

sondern durch andere Ursachen bedingt sind. Abbildung 4.7 illustriert dies<br />

an einem Beispiel: der Akteur Actor1 ist primärer Akteur des abstrakten Use Cases<br />

Entry. Entry definiert abstraktes Verhalten, das nicht ausgeführt werden kann. Allerdings<br />

gibt es hier drei Spezialisierungen des Entry Use Cases, die allesamt konkret und<br />

damit ausführbar sind: Use Case 1, Use Case 2 und Use Case 3. An dieser Stelle liegt<br />

ein semantischer Variationspunkt vor. Das Modell ist ausführbar, da es ein oder mehrere<br />

konkrete Spezialisierungen von Entry gibt. Tatsächlich kann aber nur eine der drei<br />

gegebenen konkreten Use Cases zur Ausführung kommen. Die drei Start-Transitionen,<br />

die in die verschiedenen Use Cases hineinführen, sind also Alternativen und jede <strong>für</strong><br />

sich eine mögliche semantische Variation. Die Situation, dass abstraktes Verhalten zur<br />

Ausführung kommt, ist natürlich nicht auf dieses Szenario beschränkt. Auch Inklusionen<br />

abstrakter Anwendungsfälle, Erweiterungen durch abstrakte Use Cases und abstrakte<br />

Ausnahmeflüsse sind vorstellbar. Solange es mindestens eine Konkretisierung<br />

eines abstrakten Anwendungsfalles gibt, stellt dies allerdings aus Sicht des Execution-<br />

Models kein Problem dar.<br />

Allerdings sind semantische Variationen insofern problematisch, als dass sie konzeptionell<br />

kein Alternativverhalten im ursprünglichen Sinne darstellen. Die Wahl einer<br />

Alternative ist nicht an bestimmte modellintrinsische Bedingungen gekoppelt, sondern<br />

resultiert aus einer anderen Ebene der Modellierung. Fraglich ist zudem, zu welchem<br />

Zeitpunkt die Auswahl einer konkreten Verhaltensalternative erfolgen soll.<br />

Es spricht einiges da<strong>für</strong>, semantische Variationspunkte bereits vor der Durchführung<br />

der Simulation aufzulösen, indem man <strong>für</strong> jedes ursprünglich abstrakte Verhalten eine<br />

konkrete Alternative „bindet“. In diesem Sinne eliminiert man jegliches abstraktes<br />

Verhalten und erhält eine Instanz des Ausgangsmodells, die ausschließlich konkretes<br />

Verhalten beschreibt. Folgt man diesem Ansatz, kann problemlos mit Abhängigkeiten<br />

zwischen mehreren Variationspunkten umgegangen werden. Die Entscheidung <strong>für</strong> eine<br />

Alternative an einem Variationspunkt bedingt möglicherweise die Auswahl einer<br />

bestimmten Lösung an einem anderen Variationspunkt. Diese Semantik geht verloren,<br />

wenn man die semantische Variation erst im Zuge der Simulationsausführung auflöst.<br />

In diesem Kontext stellt sich eine weitere Frage. Wenn im Laufe der Simulationsausführung<br />

ohne Auflösung der Variation im Vorfeld, ein semantischer Variationspunkt<br />

mehrfach erreicht wird; darf der Benutzer eine andere, als die im ersten Durchlauf<br />

gewählte Alternative, <strong>für</strong> die Fortsetzung der Simulation wählen?<br />

Zu diesem Zeitpunkt sind die hier aufgeworfenen Fragen noch nicht befriedigend und<br />

umfassend beantwortet. Vermutlich wird das ExecutionModel künftig noch um eine<br />

Menge möglicher Bindings zu erweitern sein. Ein Binding ordnet dann jedem semantischen<br />

Variationspunkt eine Transition aus der Menge der zu diesem Punkt gehörenden<br />

Transitionen zu. Vor Ausführung der Simulation muss dann ein konkretes Binding gewählt<br />

werden, auf dessen Grundlage die Simulation durchgeführt wird. Ein aktiviertes<br />

Binding schränkt dann die Transitionsmöglichkeiten an einem semantischen Variationspunkt<br />

im ExecutionModel auf eine konkrete Auswahl ein.<br />

63


4.2.4 Endlichkeit der ExecutionModel-Berechnung<br />

Abbildung 4.8: Schleife modelliert mittels Erweiterung<br />

Beim Aufbau des ExecutionModels aus dem NarrativeModel entsteht immer ein endliches<br />

Modell. Problematisch in dieser Hinsicht sind Schleifen. Diese werden allerdings<br />

während der Berechnung des ExecutionModels aufgelöst. Abbildung 4.8 zeigt den<br />

Fluss F1 und den diesen erweiternden Fluss F2. Erweitert wird F1 an der Position<br />

EP2. Nach Ausführung von F2 setzt der Kontrollfluss in F1 an EP1 fort. Dieses derart<br />

im NarrativeModel modellierte Verhalten resultiert im ExecutionModel in genau<br />

fünf EventExecutions. Vier EventExecutions repräsentieren dabei die vier Ereignisse<br />

in F1 und eine EventExecution die Aktion A in F2. Die kontextreduzierende Transition<br />

hinter A-EventExecution führt zu derselben C-EventExecution, die auch von<br />

B-EventExecution erreicht wird, wenn der alternative Ablauf über F2 an EP1 nicht<br />

zur Ausführung kommt. Aus der statischen Darstellung von C-EventExecution im ExecutionModel<br />

lässt sich nicht ablesen, ob dem Erreichen von C bereits mehrere Ausführungen<br />

von F2 vorangegangen sind oder nicht. Während der Simulation selbst ist<br />

diese Information jedoch vorhanden, vorausgesetzt man zeichnet die Schrittsequenz<br />

auf, über die man C erreicht hat (in Form einer Folge von Transitionen und EventExecutions).<br />

4.3 SimulationModel<br />

Das SimulationModel kapselt die <strong>für</strong> die Simulation notwendigen Konzepte, die auf<br />

denen des ExecutionModels aufbauen. Darunter fallen zum einen Mechanismen zum<br />

Aufzeichnen von Simulationsabläufen und zum anderen Elemente, um den aktuellen<br />

Zustand der Simulation zu speichern. In der Anfangsphase der Metamodellierung waren<br />

einige der Elemente, die jetzt im SimulationModel zu finden sind, ebenfalls dem<br />

ExecutionModel zugeordnet. Konzeptionell stellen sie aber nur eine Anwendung des<br />

ExecutionModels dar und gehören semantisch nicht zu der im ExecutionModel ausgedrückten<br />

Ausführungssicht. Folgerichtig sind diese Elemente jetzt Teil eines separaten<br />

Metamodells, dem SimulationModel.<br />

Abbildung 4.9 zeigt das gesamte SimulationModel. Das Wurzelement des Modells ist<br />

64


Abbildung 4.9: Struktur des SimulationModels<br />

die Metaklasse Simulation. <strong>Eine</strong> Simulation wird immer auf Grundlage eines ExecutionModels<br />

durchgeführt, daher die executionModel-Referenz in Simulation. Zu<br />

jeder Simulation gehören beliebig viele Trace-Elemente. <strong>Eine</strong>s dieser Elemente kann<br />

als aktuelle Trace der Simulation ausgezeichnet sein. <strong>Eine</strong> Trace dient dem Speichern<br />

des Simulationsablaufs. Während dem Ablauf der Simulation wählt der Benutzer eine<br />

Folge von Transitionen und EventExecutions aus dem ExecutionModel, über die er das<br />

Modell durchläuft. Jeder solcher „Lauf“ wird in einer eigenen Trace festgehalten. Dies<br />

geschieht in Form von TraceElement-Instanzen, die jeweils einen Step 3 des ExecutionModels<br />

kapseln. Jede Trace kann grundsätzlich beliebig viele derartige Elemente<br />

umfassen. Jeweils eines dieser Elemente ist das aktuelle Element der Trace. <strong>Eine</strong> Trace<br />

kann durchaus mehrere Elemente beinhalten, die jeweils denselben ExecutionModel-<br />

Step kapseln. Dies geschieht wenn der Benutzer während der Simulation Schleifen<br />

durchläuft und eine bestimmte EventExecution mehrfach besucht. In der zugrundeliegenden<br />

ExecutionModel-Instanz wird wie bereits erwähnt nicht unterschieden, ob ein<br />

Element während der Ausführung zum ersten Mal erreicht wird oder im Zuge einer<br />

Schleife bereits mehrmals besucht wurde. Die Trace kann aber sehr wohl Schleifen<br />

beinhalten.<br />

Neben den Metaklassen Simulation, Trace und TraceElement gibt es noch<br />

die DemarcationPoint-Metaklasse. Diese dient dazu, einzelne Elemente der Trace<br />

gesondert mit Namen auszuzeichnen. Auf diesem Wege kann der Benutzer im Laufe<br />

der Simulation bestimmte Elemente kennzeichnen, um beispielsweise die Trace zu einem<br />

späteren Zeitpunkt bis zu diesem Punkt „zurückzuspulen“.<br />

3 Zur Erinnerung: EventExecution und Transition sind Step-Spezialisierungen.<br />

65


4.3.1 Semantik der Trace-Operationen<br />

Neben den bereits vorgestellten strukturellen Beziehungen der Trace zu den anderen<br />

Elementen des Metamodells, verfügt sie außerdem noch über drei Operationen. Diese<br />

dienen der Manipulation der Trace und haben im Einzelnen die folgende Semantik:<br />

Abbildung 4.10: Funktionsweise der record-Operation einer Trace<br />

• record(Step) dient dem Hinzufügen eines Elements zur Trace. Dabei wird der<br />

gegebene Step in Form einer TraceElement-Instanz gekapselt und hinter<br />

dem aktuellen Element der Trace hinzugefügt. Wenn das aktuelle Element der<br />

Trace nicht gleichzeitig auch das letzte Element der Trace ist (als Resultat von<br />

Navigationsoperationen auf der Trace), werden diejenigen Elemente die hinter<br />

dem aktuellen Element stehen aus der Trace entfernt und an ihrer Stelle das<br />

neue Element hinzugefügt. Das neue Element wird in jedem Fall das neue aktuelle<br />

Element der Trace. Abbildung 4.10 illustriert den geschilderten Sachverhalt<br />

<strong>für</strong> eine Trace mit vier Elementen, wobei Element 2 das aktuelle Element der<br />

Trace ist. Element 5 wird der Trace mittels record-Operation hinzugefügt. Dadurch<br />

werden die Elemente 3 und 4 aus der Trace entfernt und 5 ist das neue<br />

aktuelle Element hinter dem bis dahin aktuellen Element 2.<br />

• toPrevious und toNext versetzen das aktuelle Element auf das Element, welches<br />

dem bis dato aktuellen Element in der Liste aller Elemente der Trace vorhergeht<br />

bzw. nachfolgt. Gibt es ein derartiges Element nicht, haben die Operationen keinen<br />

Effekt.<br />

66


Kapitel 5<br />

Technische Umsetzung<br />

Eingeleitet wird dieses Kapitel durch eine Beschreibung der Arbeitsweise des Algorithmus<br />

zur Berechnung einer ExecutionModel-Instanz. Darauf folgt die Darstellung<br />

der technischen Umsetzung der <strong>Simulationsumgebung</strong>.<br />

Die <strong>Simulationsumgebung</strong> setzt sich aus mehreren graphischen Komponenten zusammen.<br />

Jede dieser Komponenten ist verantwortlich <strong>für</strong> einen Aspekt der Simulation.<br />

Den Kern der <strong>Simulationsumgebung</strong> bildet ein Editor zur Aufzeichnung der Simulation<br />

selbst. Dieser Editor arbeitet auf Basis einer Instanz des SimulationModels (vgl.<br />

Abschnitt 4.3). Darüber hinaus gibt es Views zur Darstellung von simulationsspezifischen<br />

Zusatzinformationen. Konkret gibt es die folgenden Komponenten:<br />

• Die FlowView, die der Visualisierung der statischen Struktur einer NarrativeDescription<br />

dient. Dies wird umgesetzt durch die graphische Darstellung der Flüsse<br />

dieser NarrativeDescription, sowie der Beziehungen zwischen den Flüssen.<br />

• Die ExecutionModelView realisiert die graphischen Darstellung einer ExecutionModel-Instanz.<br />

Dies geschieht mittels navigierbarer Aktivitätsdiagramme.<br />

• Der Simulator dient zur Aufzeichnung von Traces, bzw. allgemeiner zum Bearbeiten<br />

einer Simulation-Instanz des SimulationModels.<br />

Im Folgenden werden die verschiedenen Komponenten ausführlich vorgestellt und ihre<br />

technische Realisierung beschrieben. Zum Schluss wird die Integration der Teile zu<br />

einem funktionsfähigen Ganzen behandelt.<br />

5.1 Berechnung des ExecutionModels<br />

Wie in Abschnitt 4.2 beschrieben, stellt eine ExecutionModel-Instanz die Ausführungssicht<br />

auf eine NarrativeModel-Instanz dar. Die Erzeugung einer ExecutionModel-<br />

67


Instanz auf Grundlage einer existierenden NarrativeModel-Instanz ist Inhalt dieses Abschnitts.<br />

Die hier im Folgenden vorgestellten Schnittstellen und Klassen sind Teil des<br />

sc.viper.nautilus.core.executionmodel-Plugins.<br />

public interface ExecutionModelBuilder {<br />

ExecutionModel buildFrom(NarrativeModel narrativeModel);<br />

}<br />

public interface EventExecutionSuccessorStrategy {<br />

List getNewSuccessors(EventExecution eventExecution);<br />

boolean supports(EventExecution eventExecution);<br />

}<br />

Abbildung 5.1: ExecutionModelBuilder- und EventExecutionSuccessorStrategy-Schnittstellen<br />

Die Aufgabe der Berechnung übernimmmt eine Realisierung der ExecutionModelBuilder-Schnittstelle<br />

(Abbildung 5.1). Dabei erhält der Algorithmus als einzige<br />

Eingabe ein NarrativeModel und gibt als einzige Ausgabe ein ExecutionModel zurück.<br />

Der Kern der Referenzimplementierung der ExecutionModelBuilder-Schnittstelle<br />

besteht aus verschiedenen Implementierungen einer weiteren Schnittstelle, der<br />

EventExecutionSuccessorStrategy. Deren Signatur ist ebenfalls in Abbildung<br />

5.1 zu sehen. Diese Schnittstelle definiert die Methode getNewSuccessors zur<br />

Berechnung der Nachfolger einer gegebenen EventExecution. Diese Methode gibt als<br />

Ergebnis die Menge der Nachfolger-EventExecutions zurück. Der Vorgänger wird mittels<br />

Transitionen mit seinen Nachfolgern gekoppelt.<br />

public boolean supports(EventExecution eventExecution) {<br />

return eventExecution.getEvent() instanceof Action<br />

|| eventExecution.getEvent() instanceof ExtensionAnchor;<br />

}<br />

Abbildung 5.2: Implementierung der supports-Methode in DirectSuccessor-<br />

Strategy<br />

Jede Implementierung der EventExecutionSuccessorStrategy-Schnittstelle<br />

unterstützt die Nachfolgerberechnung <strong>für</strong> einen speziellen Typ EventExecution. Über<br />

die supports-Methode wird ermittelt, ob eine Strategie <strong>für</strong> die Ermittlung der Nachfolger<br />

einer gegebenen EventExecution zuständig ist. Die verschiedenen Strategien<br />

differenzieren nach Art des durch die EventExecution referenzierten NarrativeModel-<br />

Events. Für jede Event-Spezialisierung gibt es eine Strategie.<br />

Beispielsweise berechnet die DirectSuccessorStrategy, die Nachfolger <strong>für</strong><br />

EventExecutions, die Actions oder ExtensionAnchors kapseln (siehe Implementierung<br />

der supports-Methode in Abbildung 5.2). Diese Strategie berechnet den regulären<br />

Nachfolger einer Aktion oder eines Erweiterungsankers. Das ist genau der Nachfolger,<br />

der den Standardablauf ausmacht und in der Regel im selben Fluss wie der Vorgänger<br />

liegt. Der reguläre Nachfolger einer EventExecution, die ein Ereignis an der<br />

letzten Position eines Flusses kapselt, liegt, über eine reduzierende Transition erreich-<br />

68


ar, im „Vorgängerfluss“. Auf die Erweiterungsanker bezogen, ist ein regulärer Nachfolger<br />

derjenige Nachfolger, der erreicht wird, wenn keine Alternative wirksam wird.<br />

Für die Berechnung von alternativen Nachfolgern 1 sind eigene Strategien verantwortlich,<br />

nämlich InternalExtensionSuccessorStrategy bzw. External-<br />

ExtensionSuccessorStrategy <strong>für</strong> interne bzw. externe Erweiterungsanker.<br />

Im Falle einer EventExecution, die das letzte Ereignis eines Flusses darstellt, delegiert<br />

DirectSuccessorStrategy die Nachfolgerberechnung an eine Helferstrategie,<br />

namens DirectMergeSuccessorStrategy. Diese ist verantwortlich <strong>für</strong> die Bestimmung<br />

eines Nachfolgers, der bezogen auf die Ausführungssequenz von Flüssen in<br />

einem Fluss „vor“ dem aktuellen Fluss liegt. Damit ist ein Fluss gemeint, aus dem heraus<br />

der aktuelle Fluss - direkt oder indirekt - über eine Sequenz verschiedener anderer<br />

Flüsse zur Ausführung kam. Bildlich gesprochen wird der Stack des Ausführungskontextes<br />

durch eine reduzierende Transition zwischen aktueller EventExecution und<br />

Nachfolger abgebaut.<br />

An dieser Stelle werden alle Nachfolgerstrategien noch einmal kurz vorgestellt:<br />

• DirectSuccessorStrategy und DirectMergeSuccessorStrategy<br />

dienen, wie oben bereits geschildert, der Berechnung eines regulären Nachfolgers<br />

<strong>für</strong> eine gegebene Action- oder ExtensionAnchor-EventExecution. Es<br />

gibt immer genau einen (oder keinen) regulären Nachfolger bezogen auf den<br />

Standardablauf. Im Falle der DirectSuccessorStrategy wird der Vorgänger an<br />

seinen einzigen Nachfolger immer über eine invariante Transition gekoppelt. Im<br />

Falle der DirectMergeSuccessorStrategy geschieht diese Kopplung immer über<br />

eine reduzierende Transition.<br />

• ExternalInclusionSuccessorStrategy sowie InternalInclusionSuccessorStrategy<br />

sind verantwortlich <strong>für</strong> die Nachfolgerberechnung<br />

von ExternalInclusion- und InternalInclusion-EventExecutions. Sie berechnen<br />

in diesem Sinne auch den Standardablauf, da eine Inklusion das Verhalten<br />

eines anderen Flusses unbedingt zur Ausführung bringt. Auch hier gibt es zu einer<br />

Inclusion-EventExecution jeweils nur einen Nachfolger, der vom Vorgänger<br />

aus über eine expandierende Transition erreicht wird.<br />

• Analog gibt es zur Ermittlung der Nachfolger von Erweiterungsankern die beiden<br />

Klassen ExternalExtensionSuccessorStrategy und InternalExtensionSuccessorStrategy.<br />

Diese bestimmen zu einer internen<br />

oder externen ExtensionAnchor-EventExecution die im Rahmen von Alternativabläufen<br />

erreichbaren Nachfolger. Dies können grundsätzlich beliebig viele<br />

sein. Jeder gefundene Nachfolger wird mittels expandierender Transition an die<br />

ExtensionAnchor-EventExecution gekoppelt.<br />

• Die ExceptionSuccessorStrategy dient der Bestimmung von Nachfolgern<br />

einer Action-EventExecution, die in Ausnahmeflüssen liegen. Das ist abhängig<br />

vom aktuellen Ausführungskontext und kann <strong>für</strong> eine Action-EventExe-<br />

1 Ein alternativer Nachfolger ist nicht Teil des Standardablaufs.<br />

69


cution in beliebig vielen Nachfolgern resultieren. Diese sind dann alle mittels<br />

expandierender Transition erreichbar.<br />

• Die NullSuccessorStrategy erwartet als Eingabe-EventExecution eine<br />

Null-Referenz (null in Java). Sie gibt dann diejenigen EventExecutions zurück,<br />

über die in das Modell „eingestiegen“ werden kann. Das sind die Event-<br />

Executions, die in einem konkreten Fluss, der über einen InteractionContext verfügt,<br />

an erster Position stehen.<br />

Der ExecutionModelBuilder baut das ExecutionModel ausgehend von der Ausgabe der<br />

NullSuccessorStrategy inkrementell auf. Die Ausgabe-EventExecutions der NullSuccessorStrategy<br />

werden der Reihe nach in die supports-Methoden der anderen Strategien<br />

hineingegeben. Wenn eine Strategie einen bestimmten Typ EventExecution unterstützt,<br />

wird ihre getNewSuccessors-Methode aufgerufen. Die neugewonnenen Nachfolger<br />

werden dann auf dieselbe Weise weiter verarbeitet, bis irgendwann keine neuen<br />

Nachfolger mehr gefunden werden. Zu diesem Zeitpunkt ist das ExecutionModel dann<br />

komplett aufgebaut und kann anschließend mittels EMF-Mechanismen im Dateisystem<br />

persistiert werden.<br />

Abbildung 5.3: Funktionsweise von Nachfolgerstrategien<br />

Abbildung 5.3 illustriert die Arbeitsweise der verschiedenen Strategien anhand eines<br />

einfachen Beispiels. Die Quadrate symbolisieren EventExecutions, die Pfeile stellen<br />

Transitionen zwischen EventExecutions dar. Die EventExecutions ohne Beschriftung<br />

sind einfache Aktionen. EI ist eine externe Inklusion, EP1 ein externer Erweiterungsanker.<br />

Jede Transition ist beschriftet mit derjenigen Nachfolgerstrategie, mittels der<br />

die jeweilige Transition im ExecutionModel erzeugt wurde.<br />

Interpretiert man das in Abbildung 5.3 dargestellte Beispiel als eine komplette ExecutionModel-Instanz,<br />

stellt man fest, dass dieses Modell genau zwei Szenarien aufspannt.<br />

Zum einen gibt es das Szenario, welches den Standardablauf darstellt und mittels der<br />

Transitionsfolge {a, b, d, c, b, c} zustande kommt. Das andere Szenario beinhaltet<br />

einen Alternativablauf und stellt sich als Transitionsfolge wie folgt dar: {a, b, d, c, b,<br />

e, c, c}.<br />

70


5.2 FlowView<br />

Wichtiger Bestandteil einer benutzerfreundlichen <strong>Simulationsumgebung</strong> ist eine Visualisierungskomponente<br />

<strong>für</strong> die statische Struktur eines NarrativeModels. Mittels dieser<br />

kann sich ein Benutzer den Strukturzusammenhang des zugrundeliegenden Modell<br />

vergegenwärtigen und sich somit einen Überblick über die modellierten Inhalte verschaffen.<br />

Zu diesem Zweck wurde im Rahmen dieser Arbeit die sogenannte FlowView entwickelt.<br />

Die FlowView stellt die interne Struktur einer NarrativeDescription graphisch<br />

dar. Dazu werden die Flüsse der NarrativeDescription mit ihren Ereignissen visualisiert.<br />

Die Inklusions- und Erweiterungsbeziehungen zwischen Flüssen einer NarrativeDescription<br />

werden in Form von Kanten dargestellt.<br />

Abbildung 5.4: Screenshot der FlowView<br />

Abbildung 5.4 beinhaltet einen Screenshot der FlowView. Diese zeigt zwei Flüsse einer<br />

NarrativeDescription, die über eine interne Erweiterungsbeziehung miteinander<br />

verbunden sind. Die „IEA“-Quadrate stehen <strong>für</strong> interne Erweiterungsanker, die leeren<br />

Quadrate stellen Aktionen dar. Wenn man den Mauszeiger über eines der Quadrate<br />

eines Ereignisses eines Flusses bewegt, werden Detailinformationen zum Ereignis<br />

eingeblendet. In der Abbildung ist dies <strong>für</strong> den zweiten Erweiterungsanker illustriert.<br />

Der Fluss hat den Namen Authentifizieren Standard und der Anker heißt hinter PIN<br />

Eingabe. Die Pfeile zwischen den Flüssen geben die tatsächliche Richtung des möglichen<br />

Kontrollflusses an und nicht die Richtung der zugrundeliegenden Beziehung.<br />

Die Erweiterungsbeziehung ist von erweiterndem zu erweitertem Use Case gerichtet,<br />

der Kontrollfluss läuft genau entgegengesetzt. Im Falle des Beispiels kann der Kontrollfluss<br />

also vom Erweiterungsanker hinter PIN Eingabe in den Fluss auf der rechten<br />

Seite übergehen.<br />

Inhalt des Screenshots in Abbildung 5.5 ist die Ausgabe der FlowView im Falle einer<br />

komplexeren NarrativeDescription. Das Bild stellt die selbe Situation zweimal dar.<br />

Links werden alle Kanten, die mögliche Kontrollflusswechsel zwischen Flüssen sym-<br />

71


Abbildung 5.5: Screenshot der FlowView<br />

bolisieren, angezeigt. Diese Darstellung kann <strong>für</strong> große Modelle ziemlich unübersichtlich<br />

werden. Aus diesem Grund bietet die FlowView die Möglichkeit, verschiedene<br />

Kantenarten bei Bedarf auszublenden. Auf der rechten Seite des Bildes ist die interne<br />

Struktur der NarrativeDescription erneut visualisiert, diesmal ohne Rücksprungskanten.<br />

Durch diese Maßnahme wird die Übersichtlichkeit deutlich erhöht. Generell lassen<br />

sich auch die Aussprungskanten ausblenden. Der Benutzer der View kann somit immer<br />

die Sichtweise auf den Kontrollfluss einnehmen, die ihn gerade interessiert.<br />

5.2.1 Integration der FlowView in die Eclipse-Plattform<br />

Die FlowView ist technisch realisiert als Eclipse-View, d.h. als Implementierung der<br />

IViewPart-Schnittstelle.<br />

Für die graphische Darstellung kommt das GEF Rahmenwerk (siehe Abschnitt 3.2)<br />

zum Einsatz.<br />

Die FlowView ist sowohl SelectionListener als auch SelectionProvider (vgl. Abschnitt<br />

3.1.3). In ihrer Rolle als SelectionListener verarbeitet sie alle NarrativeDescriptions,<br />

die ihr von anderen SelectionProvidern zur Verfügung gestellt werden. Selektiert ein<br />

anderes WorkbenchPart eine NarrativeDescription, wird die FlowView hierüber informiert<br />

und stellt die auf diese Art erhaltene NarrativeDescription graphisch dar.<br />

72


In der graphischen Darstellung der FlowView kann mittels Mausklick ein Ereignis<br />

eines Flusses selektiert werden. Diese Selektion wird anderen SelectionListenern zur<br />

Verfügung gestellt.<br />

5.2.2 Graphische Anordnung der Flüsse<br />

Die Anordnung der Flüsse in der graphischen Darstellung resultiert aus einer Heuristik,<br />

die anstrebt, Überschneidungen der Beziehungen zwischen Flüssen in Form sichüberkreuzender<br />

Kanten möglichst zu vermeiden. Daraus resultiert, dass Flüsse mit Interaktionskontext<br />

immer links dargestellt werden und sich inkludierte und erweiternde<br />

Flüsse nach rechts hin auffächern.<br />

5.3 ExecutionModelView<br />

Die ExecutionModelView dient der graphischen Visualisierung einer ExecutionModel-<br />

Instanz. Praktisch geschieht dies mittels einer Darstellung in Form navigierbarer Aktivitätsdiagramme.<br />

Diese Darstellungsform reflektiert die Ausführungssicht, wie sie ein<br />

ExecutionModel auf eine NarrativeModel-Instanz beschreibt. Anders als bei der Flow-<br />

View stehten nicht mehr Strukturinformationen im Vordergrund, sondern Ablaufmöglichkeiten<br />

des Verhaltens, das im Use Case-Modell und dem auf diesem basierenden<br />

NarrativeModel enthalten ist.<br />

In Abschnitt 4.1 wurde das Gesamtmodell des Geldautomaten (aus dem Beispiel in<br />

Abschnitt 2.3) in Form eines Aktivitätsdiagramm dargestellt. Die ExecutionModel-<br />

View stellt allerdings nicht das gesamte Ausführungsmodell dar, sondern jeweils einen<br />

Ausschnitt in Form je einer Aktivität. Die Navigation zwischen verschiedenen Ausschnitten<br />

des zugrundeliegenden Modells verschafft einen allumfassenden Überblick<br />

über das Gesamtmodell. Die Idee der Darstellung eines kompletten Modells in einem<br />

Diagramm wurde aus Gründen der Übersichtlichkeit <strong>für</strong> unpraktikabel befunden.<br />

Die einzelnen Aktivitäten, die von der ExecutionModelView angezeigt werden, stellen<br />

<strong>für</strong> je einen NarrativeModel-Fluss die in diesem Fluss möglichen Aktionsalternativen<br />

dar. Die Aktionsknoten einer Aktivität kapseln EventExecutions und Transitionen des<br />

ExecutionModels. Mittels derjenigen Aktionsknoten, die Transitionen symbolisieren,<br />

kann zwischen der Darstellung verschiedener Aktivitäten navigiert werden, was weiter<br />

unten noch erläutert wird. Genau genommen werden nicht die Aktionsmöglichkeiten<br />

je eines Flusses anzeigt. Dies würde nämlich implizieren, dass die Strukturinformationen,<br />

die aus dem NarrativeModel abgefragt werden können, <strong>für</strong> diese Darstellung<br />

ausreichend sind. Stattdessen werden die Aktionsmöglichkeiten je eines Execution-<br />

Contexts des ExecutionModels visualisiert. Jeder Fluss des NarrativeModels hat mindestens<br />

einen ExecutionContext, der den Kontext seiner Ausführung beschreibt. Wenn<br />

der Fluss in der Ausführung auf verschiedenen Pfaden erreichbar ist, sind auch mehrere<br />

möglich. Anschaulicher ist allerdings die Sprechweise, nach der der Verhaltensablauf<br />

eines Flusses dargestellt wird.<br />

73


Erweiterungen, Inklusionen und Verzweigungen zu Ausnahmeflüssen werden jeweils<br />

aus Sicht des lokalen Flusses atomar als je eine Aktion dargestellt. Derartige Aktionen,<br />

die die Ausführung einer Verhaltenssequenz (bzw. eines anderen Flusses) kapseln,<br />

sind graphisch durch ein Symbol, das wie ein umgedrehter Dreizack aussieht, kenntlich<br />

gemacht. Durch Doppelklick des Benutzer auf eine solche Aktion stellt die View<br />

deren gekapselte Verhaltenssequenz in Form einer eigenen Aktivität dar. Der Benutzer<br />

bekommt auf diese Weise den Inhalt des aufgerufenen Flusses angezeigt. Über einen<br />

Zurück-Knopf hat er die Möglichkeit, in den Ursprungsfluss zurückzukehren. Der Benutzer<br />

kann so durch die Kontexte einer ExecutionModel-Instanz navigieren und sich<br />

leicht einen Überblick über das Modell verschaffen.<br />

Abbildung 5.6: Screenshot der ExecutionModelView<br />

Abbildung 5.7: Screenshot der ExecutionModelView<br />

Abbildung 5.6 zeigt die ExecutionModelView in Aktion. Die abgebildete Aktivität<br />

illustriert die Aktionsmöglichkeiten des Flusses Standardfluss, der in der NarrativeDescription<br />

von UseCase definiert ist. Der dargestellte Fluss besitzt nur einen Erweiterungsanker,<br />

an dem Verhalten eingefügt werden kann. In diesem Fall kann konkret der<br />

Fluss Erweiterungsfluss, der zur selben NarrativeDescription gehört, ausgeführt werden.<br />

Bewegt der Benutzer den Mauszeiger über die Fragezeichen an den Kanten, wer-<br />

74


den die Bedingungen eingeblendet, unter denen sich der Kontrollfluss entsprechend<br />

verlagert. Der Standardablauf von Standardfluss ist durch die beiden unbeschrifteten<br />

Kanten dargestellt, die vom Startknoten zum Endknoten der Aktivität führen. Im Falle<br />

eines Doppelklicks auf die Aktion mit dem umgekehrten Dreizack werden die Ablaufmöglichkeiten<br />

des Flusses Erweiterungsfluss als Inhalt einer neuen Aktivität visualisiert.<br />

In der Menüleiste der View sind Knöpfe enthalten, mittels derer durch die Darstellung<br />

navigiert werden kann. Auf dem Screenshot ist nur der Zurück-Knopf funktionsfähig,<br />

der Vorwärts-Knopf ist ausgegraut. Der Vorwärts-Knopf ist nur dann aktiviert,<br />

wenn vorher mindestens einmal der Zurück-Knopf betätigt wurde. Intuitiv entspricht<br />

die Navigationsmechanik der eines Web-Browsers. Des Weiteren kann mittels der Lupen<br />

in der Menüleiste die Darstellung vergrößert bzw. verkleinert werden. Mit Hilfe<br />

des Layout-Knopfes ganz links kann zwischen der vertikalen und horizontalen Darstellung<br />

einer Aktivität umgeschaltet werden. Je nach gewählter Darstellungsart werden<br />

die Knoten, die den Standardablauf einer Aktivität ausmachen, von links nach rechts<br />

(horizontal) bzw. von oben nach unten (vertikal) angeordnet. Alternativabläufe und<br />

Ausnahmen werden als vom Standardablauf abweichende Verzweigungen rechts neben<br />

oder unterhalb des Standardablaufs dargestellt. Abbildung 5.7 zeigt die bereits aus<br />

der Vorgängerabbildung bekannte Aktivität, diesmal allerdings in horizontaler Darstellung.<br />

Zur Verdeutlichung der Funktionsweise der ExecutionModelView im Falle eines komplexeren<br />

Modells zeigt Abbildung 5.8 eine aufgefächerte Darstellung der relevanten<br />

Aktivitäten des Geldautomatenbeispielmodells. Im Zuge der Visualisierung der<br />

ExecutionModel-Instanz wird als erstes die links oben abgebildete Aktivität NarrativeModel:<br />

Geldautomat dargestellt. Im Falle des Geldautomatensystems gibt es nur<br />

eine Möglichkeit, eine Ausführung eines Anwendungsfalles auszulösen. Dementsprechend<br />

gibt es hier nur einen Einstiegspunkt, der bei Doppelklick in die Darstellung<br />

des Flusses Geld abheben Standard hineinführt. Diese Aktivität ist Inhalt der rechten<br />

Spalte der Abbildung. In der linken Spalte sind außerdem noch die Aktivitäten Authentifizieren<br />

Standard und Quittung drucken Standard zu sehen, die beide aus Geld<br />

abheben Standard heraus erreichbar sind.<br />

Der Darstellung einer ExecutionModel-Instanz in Form des navigierbaren Aktivitätdiagramms<br />

liegen zwei hauptsächliche Motivationen zugrunde:<br />

1. Intuitive Darstellung: Aktivitätsdiagramme gehören zu den bekanntesten Vertretern<br />

der verschiedenen Diagrammtypen der UML. Sie sind den meisten Modellierern<br />

vertraut. Selbst Benutzern, die noch keinerlei Kontakt mit Aktivitätsdiagrammen<br />

hatten, erschließt sich ihre Semantik intuitiv.<br />

2. Semantik von Aktivitäten und Aktionen: Die Semantik der eingesetzten Elemente<br />

zur Darstellung von EventExecutions und Transitionen des Execution-<br />

Models entspricht genau der Semantik der Elemente, die sie repräsentieren.<br />

UML-Aktionen werden eingesetzt, um Action-EventExecutions 2 darzustellen.<br />

2 <strong>Eine</strong> Action-EventExecution ist eine EventExecution die eine NarrativeModel Action kapselt.<br />

75


Abbildung 5.8: Das Geldautomatenbeispiel als Menge von Aktivitäten<br />

76


<strong>Eine</strong> andere Art von UML-Aktion wird benutzt, um die Ausführung einer kompletten<br />

Verhaltenssequenz graphisch zu repräsentieren. <strong>Eine</strong> Aktivität selbst ist<br />

nichts anderes als eine Verhaltenssequenz.<br />

5.3.1 Integration der ExecutionModelView in die Eclipse-Plattform<br />

Die ExecutionModelView ist technisch realisiert als Eclipse-View, d.h. als Implementierung<br />

der IViewPart-Schnittstelle.<br />

Für die graphische Darstellung kommt das GEF Rahmenwerk (siehe Abschnitt 3.2)<br />

zum Einsatz.<br />

Abbildung 5.9: Metaklassen zur Modellierung von Aktivitäten<br />

Die Modellelemente der verschiedenen EditParts sind dabei nicht etwa Elemente des<br />

ExecutionModels sondern Elemente des UML-Modells. Insbesondere sind dies Activity,<br />

ActivityEdge und verschiedene Spezialisierungen von Activity-<br />

Node.<br />

Abbildung 5.9 bietet einen Überblick über die eingesetzten Modellelemente und ihre<br />

Struktur. Das zentrale Element ist die Activity-Metaklasse. Activity ist eine<br />

Spezialisierung von Behavior und dient damit der Darstellung von dynamischen<br />

Verhaltenssequenzen. <strong>Eine</strong> Activity besitzt eine Menge von Knoten (Metaklasse ActivityNode)<br />

und eine Menge von Kanten (Metaklasse ActivityEdge) zwischen<br />

ihren Knoten (siehe auch Abschnitt 2.1.1). Zwei Verfeinerungen von Activity-<br />

Node sind im Rahmen der Realisierung der ExecutionModelView besonders interessant:<br />

• Action: <strong>Eine</strong> Aktion ist ein Knoten, der einen einzelnen Schritt der Verhaltens-<br />

77


sequenz einer Aktivität darstellt. Es gibt atomare Schritte in Form von SendSignalAction-Instanzen<br />

und solche Schritte, die wiederum eine andere Verhaltenssequenz<br />

kapseln (Metaklasse CallBehaviorAction). Letztere werden<br />

graphisch mit dem umgekehrten Dreizacksymbol dargestellt.<br />

• ControlNode: Ein Kontrollknoten ist ein Knoten, der der Steuerung des Kontrollflusses<br />

dient. Konkret gibt es DecisionNode-Instanzen an denen sich<br />

Verhalten verzweigt (ein DecisionNode besitzt immer mehr als eine ausgehende<br />

Kante) und MergeNode-Instanzen, an denen mehrere Kontrollflüsse zusammengeführt<br />

werden (d.h. mehrere Kanten führen in eine MergeNode hinein). Jede<br />

Aktivität muss über genau einen Startknoten in Form einer InitialNode-<br />

Instanz verfügen. Zu den Knoten einer Activity können außerdem Instanzen von<br />

ActivityFinalNode gehören. Die Ausführung einer Activity endet, wenn<br />

der Kontrollfluss in einen derartigen Knoten hineinführt. Startknoten haben keine<br />

eingehenden Kanten, Endknoten keine ausgehenden Kanten.<br />

Der Visualisierung einer ExecutionModel-Instanz voraus geht notwendigerweise die<br />

Transformation des ExecutionModels in eine Aktivität, bzw. in eine hierarchische<br />

Struktur einer Menge von Aktivitäten. Die hierarchische Struktur kommt mittels Call-<br />

BehaviorAction-Instanzen, die als Knoten zu einer Aktivität gehören, zustande.<br />

Über ihre behavior-Assoziation referenziert eine CallBehaviorAction das Verhalten,<br />

deren Ausführung sie kapselt. Im Falle der ExecutionModelView ist das gekapselte<br />

Verhalten immer eine andere Aktivität, die der Ausführung je eines Flusses entspricht.<br />

Im Rahmen der graphischen Darstellung einer ExecutionModel-Instanz wird jede Action-EventExecution<br />

durch eine SendSignalAction repräsentiert. CallBehaviorActions<br />

werden genutzt, um expandierende Transitionen zu visualisieren. EventExecutions,<br />

die die Ausführung anderer NarrativeModel-Events als Actions kapseln, bieten keinen<br />

Mehrwert <strong>für</strong> die graphische Darstellung. Verzweigendes Verhalten wird mittels<br />

DecisionNodes visualisiert. Dass dieser Verzweigung im ExecutionModel ein Erweiterungsanker<br />

zugrunde liegt, an dem alternatives Verhalten ansetzt, ist hierbei unerheblich.<br />

Ebenso wenig werden reduzierende Transitionen explizit repräsentiert. Jede<br />

Aktivität hat in der ExecutionModelView genau einen Endknoten, der alle möglichen<br />

reduzierenden Transitionen darstellt.<br />

Im Zuge der Transformation eines ExecutionModels in eine Aktivitätshierarchie werden<br />

Stereotypen eingesetzt, um einer Aktivität denjenigen ExecutionContext zuzuordnen,<br />

den sie repräsentiert. Analog ermöglicht ein anderer Stereotyp die Zuordnung von<br />

Transitionen und EventExecutions auf Aktionen und von Transitionen auf Kanten. Damit<br />

ist an den Elementen, die das Aktivitätsdiagramm ausmachen, hinterlegt, welche<br />

Elemente des ExecutionModels sie repräsentieren. Der diesem Ansatz technisch zugrundeliegende<br />

UML-Profilmechanismus wurde in Abschnitt 2.1.1 vorgestellt.<br />

Diese auf derartige Weise an Aktivitäten, Knoten und Kanten hinterlegte Informationen<br />

werden von dem Algorithmus, der <strong>für</strong> die graphische Anordnung der Knoten einer<br />

Aktivität verantwortlich ist, genutzt, um zu ermitteln, welche Knoten den Standardablauf<br />

darstellen.<br />

78


Die ExecutionModelView ist SelectionProvider und SelectionListener (vgl. Abschnitt<br />

3.1.3). Selektiert man eine Aktion, wird anderen WorkbenchParts das repräsentierte<br />

ExecutionModel-Element zur Verfügung gestellt. Stellt hingegen ein anderes WorkbenchPart<br />

ein ExecutionModel-Element zur Verfügung, welches zu diesem Zeitpunkt<br />

in der aktuell dargestellten Aktivität durch eine Aktion oder eine Kante repräsentiert<br />

wird, hebt die ExecutionModelView die Aktion oder die Kante farblich hervor.<br />

5.4 Simulator<br />

Das zentrale Element der <strong>Simulationsumgebung</strong> ist der Simulator. Dieser dient der<br />

Aufzeichnung von neuen Traces und der Bearbeitung existierender Traces. Der Simulator<br />

besteht aus zwei Komponenten, die gemeinsam seine Funktionalität ausmachen.<br />

Die erste Komponente ist ein Editor, mittels dem ein Benutzer eine Trace aufzeichnet.<br />

Die zweite Komponente ist eine View, die eine Simulation-Instanz (das Wurzelement<br />

des SimulationModels, siehe Abschnitt 4.3) und ihre Traces visualisiert.<br />

5.4.1 TraceEditor<br />

Der Editor zum Aufzeichnen von Traces heißt TraceEditor. Im Editor steuert der Benutzer<br />

die simulierte Ausführung einer ExecutionModel-Instanz. Da<strong>für</strong> wählt er aus<br />

einer Menge von Schritten (Steps des ExecutionModels, also Transitionen und Event-<br />

Executions), die ihm der Editor zur Auswahl gibt, einen aus. Daraufhin wird der selektierte<br />

Schritt als neuer aktueller Schritt in die Trace aufgenommen und eine neue<br />

Bildschirmmaske mit den entsprechenden Nachfolgern des jetzt aktuellen Schrittes<br />

aufgebaut. Aus dieser Menge wählt der Benutzer wiederum einen Schritt aus. Dies<br />

geschieht solange, bis der Benutzer ein komplettes Szenario vom Anfang eines Use<br />

Cases bis zu dessen Ende in Form einer Folge von Schritten in der Trace gespeichert<br />

hat. Auf Modellebene wird jeder Schritt, der der Trace hinzugefügt wird, durch eine<br />

eigene TraceElement-Instanz gekapselt.<br />

Abbildung 5.10 zeigt eine Abfolge von Bildschirmmasken des TraceEditors <strong>für</strong> das<br />

Geldautomatenbeispiel aus Abschnitt 2.3. Wird der Editor auf einer Modelldatei 3 , die<br />

eine Simulation enthält, geöffnet, muss eine Trace angegeben werden, die in der Folge<br />

bearbeitet werden soll. Hier<strong>für</strong> kann eine bereits bestehende Trace gewählt werden,<br />

oder es kann eine neue Trace angelegt werden. Startet man das Geldautomatenbeispiel<br />

mit einer neuen Trace, wird die zweite abgebildete Bildschirmmaske angezeigt. Hier<br />

hat der Benutzer ebenso wie in der dritten Maske nur einen Schritt zur Auswahl. Die<br />

vierte Maske stellt eine Situation dar, an der sich Verhalten verzweigen kann. Die erste<br />

Option stellt den Standardablauf dar. Im konkreten Fall kann der Benutzer mittels<br />

Inklusion in den Verhaltensablauf des Flusses Authentifizieren Standard übergehen.<br />

Alternativ geht der Kontrollfluss in den Ausnahmefluss Kunde bricht ab über. Die Bedingung<br />

unter der dies stattfindet ist in eckigen Klammern angegeben.<br />

3 Diese kann man mittels Wizard zu einer existierenden ExecutionModel-Instanz erstellen.<br />

79


Abbildung 5.10: Screenshot einer Folge von Bildschirmmasken des TraceEditors<br />

5.4.2 SimulationView<br />

Der TraceEditor ermöglicht immer nur eine sehr lokale Bearbeitung einer Trace. An einem<br />

Punkt kann man aus einer Menge möglicher Nachfolgeschritte einen Bestimmten<br />

auswählen. Die SimulationView hingegen bietet eine umfassende Sicht auf die im aktiven<br />

Editor bearbeitete Simulation. Sie stellt eine Simulation-Instanz graphisch in<br />

Form eines Baumes, der eine Menge von Traces enthält, dar. Die Traces werden ebenfalls<br />

hierarchisch visualisiert. Während eine Trace im SimulationModel eine Liste von<br />

Elementen beinhaltet, ist es <strong>für</strong> ihre graphische Darstellung intuitiver, stattgefundene<br />

Kontextwechsel durch Einrückungen hervorzuheben.<br />

80


Abbildung 5.11: Screenshot der Darstellung zweier Traces in der SimulationView<br />

Abbildung 5.11 illustriert diesen Sachverhalt am Geldautomatenbeispiel. Dargestellt<br />

sind zwei vollständige Traces, von Anfang bis Ende des Anwendungsfalles. Die erste<br />

Trace durchläuft den Standardablauf des Anwendungsfalles Geld abheben. Die hierarchische<br />

Struktur der Elemente gibt an, an welchen Stellen der Simulation sich der<br />

Kontrollfluss in einen neuen Ausführungskontext verlagert hat. Im Falle des Standardablaufs<br />

war dies nur an zwei Stellen der Fall. Das erste Mal, wenn der Benutzer in<br />

die Simulation des Flusses Geld abheben Standard einsteigt und das zweite Mal, wenn<br />

Geld abheben Standard den Fluss Authentifizieren Standard inkludiert. Die zweite<br />

Trace in Abbildung 5.11 stellt ein vom Standardablauf abweichendes Szenario dar.<br />

Bei der PIN-Eingabeaufforderung gibt der Kunde zweimal eine falsche Nummer ein.<br />

Erst im dritten Anlauf gelingt ihm die korrekte Eingabe seiner PIN.<br />

5.4.3 Integration in die Eclipse-Plattform<br />

Sowohl TraceEditor als auch SimulationView nutzen SWT <strong>für</strong> die Darstellung ihrer<br />

graphischen Benutzeroberflächen. Beide Komponenten sind sowohl SelectionListener<br />

als auch SelectionProvider. Die SimulationView zeigt immer die Simulation des aktuellen<br />

TraceEditors an. Hierbei ist immer das letzte einer Trace hinzugefügte Element<br />

im Baum selektiert. Wählt der Benutzer in der SimulationView ein Element der Trace<br />

aus, springt der TraceEditor zu dieser Stelle der Simulation und zeigt die Auswahlmöglichkeiten,<br />

die sich aus dem selektierten Element der SimulationView ergeben,<br />

an. Die zu einem vergangenen Zeitpunkt getroffene Auswahl ist dabei standardmäßig<br />

vorselektiert. Entscheidet sich der Benutzer jetzt <strong>für</strong> eine andere Auswahl, werden alle<br />

Elemente, die auf das in der SimulationView Selektierte folgen, aus der Trace ent-<br />

81


public interface ChoiceLogic {<br />

}<br />

List getStartChoices(ExecutionModel executionModel);<br />

List getChoicesAfter(Step step);<br />

Abbildung 5.12: ChoiceLogic-Schnittstelle<br />

fernt und stattdessen das neue Element hinzugefügt. Hierdurch ist es möglich, bereits<br />

existierende Traces nach Belieben zu verändern. Mittels der SimulationView kann der<br />

Benutzer einfach zu der Position in der Trace springen, an der er Änderungen vornehmen<br />

möchte.<br />

Den Schritten, die der Benutzer im Rahmen der Simulation in einer Trace speichert,<br />

liegen wie bereits erwähnt Transitionen und EventExecutions des ExecutionModels<br />

zugrunde. Der TraceEditor gibt dem Benutzer nach jeder getroffenen Entscheidung<br />

ein oder mehrere Folgeschritte zur Auswahl. Dabei zeigt der TraceEditor aber nur Elemente<br />

an, die tatsächlich <strong>für</strong> die Simulation relevant sind. Beispielsweise wäre es <strong>für</strong><br />

den Benutzer sehr mühsam, wenn er jede invariante Transition 4 zwischen zwei Event-<br />

Executions desselben Ausführungskontextes der aktuellen Trace durch eine eigene Benutzerinteraktion<br />

hinzufügen müsste. Dass eine Transition zwischen zwei Aktionen eines<br />

Flusses stattfindet, stellt <strong>für</strong> den Benutzer keinen Mehrwert an Informationen dar.<br />

Invariante Transitionen sind lediglich Elemente, die aus der Modellbildung des ExecutionModels<br />

resultieren. Aus diesem Grund stellt der TraceEditor dem Benutzer nur<br />

bestimmte Schritte zur Auswahl zur Verfügung. Dazu gehören EventExecutions, die<br />

eine Aktion kapseln und expandierende und reduzierende Transitionen. Realisiert wird<br />

diese Filterung durch eine Implementierung der ChoiceLogic-Schnittstelle, die in<br />

Abbildung 5.12 vorgestellt wird. Neben invarianten Transitionen werden standardmäßig<br />

Auswahlen, die nur Rücksprungspunkte darstellen, übersprungen. Ein interner Erweiterungsanker,<br />

der nur als Rücksprungsanker aus einem anderen Fluss heraus dient,<br />

ist als Simulationsschritt nicht relevant.<br />

5.5 Integration der graphischen Einzelkomponenten<br />

In den vorangegangen Abschnitten dieses Kapitels wurden die verschiedenen Komponenten<br />

der <strong>Simulationsumgebung</strong> vorgestellt. Die in diesem Rahmen beschriebenen<br />

Views und der Editor sind jeweils verantwortlich <strong>für</strong> eine spezielle Facette, die<br />

die Durchführung der Simulation betrifft. FlowView und ExecutionModelView dienen<br />

der Visualisierung der zugrundeliegenden NarrativeModel- und ExecutionModel-<br />

Instanzen. TraceEditor und SimulationView sind verantwortlich <strong>für</strong> die Durchführung<br />

der Simulation selbst.<br />

4.2.1).<br />

4 <strong>Eine</strong> invariante Transition ist der Übergang zwischen zwei Events eines Flusses (vgl. Abschnitt<br />

82


In diesem Abschnitt wird erläutert, wie die verschiedenen Komponenten im Rahmen<br />

des Eclipse UI-Paradigmas (siehe Abschnitt 3.1.3) zusammenarbeiten, um eine benutzerfreundliche<br />

Simulationsdurchführung zu ermöglichen.<br />

Abbildung 5.13: Screenshot der <strong>Simulationsumgebung</strong><br />

Abbildung 5.13 zeigt eine Anordnung der verschiedenen Komponenten in der Eclipse-<br />

Workbench. Zentrales Element ist der TraceEditor, der umrahmt wird von den verschiedenen<br />

Views. Diese Anordnung folgt dem üblichen Eclipse UI-Paradigma, nach<br />

dem ein Editor im Zentrum steht und von diversen unterstützenden Views flankiert<br />

wird. Der TraceEditor stellt den Views in seiner Funktion als SelectionProvider verschiedene<br />

Elemente zur Verfügung. Wenn, wie im Screenshot abgebildet, eine der vorgegebenen<br />

Auswahlmöglichkeiten selektiert wird, setzt der TraceEditor eine mehrteilige<br />

Selektion zusammen. Diese beinhaltet neben der aktuellen Simulation-Instanz<br />

auch die durch die aktuelle Auswahl repräsentierte Step-Instanz des ExecutionModels<br />

sowie eine Event-Instanz des NarrativeModels. Betätigt der Benutzer den „OK“-<br />

Knopf des TraceEditors, um das selektierte Element der Trace hinzuzufügen, stellt der<br />

TraceEditor den anderen WorkbenchParts die aktuelle Trace zur Verfügung. Daraufhin<br />

können die Views zusätzliche Kontextinformationen anzeigen. Sowohl FlowView<br />

als auch ExecutionModelView markieren dabei in ihren jeweiligen Darstellungen das<br />

jeweils relevante Element, das mit der Auswahl des TraceEditors korrespondiert. Die<br />

Eclipse-eigene PropertiesView nutzt den EMF-Adapter Mechanismus, um die Eigenschaften<br />

der zuletzt zur Verfügung gestellten Selektion anzuzeigen. Rückkopplungen<br />

der unterstützenden Views in den TraceEditor mittels ihrer Selektionen sind zu diesem<br />

Zeitpunkt nur von der SimulationView aus möglich (siehe Abschnitt 5.4.3).<br />

83


Mittels SelectionListener- und SelectionProvider-Mechanismen wird also eine Integration<br />

der verschiedenen Simulationskomponenten angestrebt, um eine graphische<br />

Benutzeroberfläche zu realisieren, die konform zu den bekannten Eclipse-Paradigmen<br />

ist.<br />

84


Kapitel 6<br />

Evaluierung<br />

Im Rahmen dieser Arbeit ist ein Werkzeug zur Ausführungssimulation natürlichsprachlicher<br />

Anwendungsfallmodelle enstanden. <strong>Eine</strong> Evaluierung der Umgebung kann bezüglich<br />

einer inhaltlichen Beurteilung erfolgen, die sich mit der Erfüllung der fachlichen<br />

Anforderungen beschäftigt, oder kann der Frage nachgehen, inwiefern die Implementierung<br />

dieser Arbeit softwaretechnischen Anforderungen genügt.<br />

6.1 Inhaltliche Evaluierung<br />

Mangels einer formalen Anforderungsspezifikation fällt eine systematische Evaluierung<br />

schwer. Allerdings wurden im ersten Kapitel dieser Arbeit eine Reihe von Zielsetzungen<br />

formuliert, die <strong>für</strong> eine Beurteilung herangezogen werden können.<br />

Ein Ziel dieser Arbeit ist es, die Anforderungsanalyse mittels <strong>Simulationsumgebung</strong><br />

zu unterstützen. Leider ist es zu diesem Zeitpunkt nicht angemessen, eine umfassende<br />

Beurteilung bezüglich dieses Gesichtspunkts vorzunehmen. Ob das Werkzeug die<br />

erwünschte Leistung tatsächlich erbringt, müssen die Praxis und etwaige weitere Forschung<br />

zeigen. Bereits jetzt ist allerdings abzusehen, dass durch Einsatz der Simulation<br />

ein besseres Systemverständnis erlangt werden kann.<br />

<strong>Eine</strong> weitere Zielsetzung bestand darin, im Laufe der Simulation Artefakte, die als<br />

Grundlage zur qualitativen Evaluierung der modellierten Anwendungsfallbeschreibungen<br />

genutzt werden können, zu gewinnen. In dieser Arbeit ist als wichtigstes Artefakt<br />

die ExecutionModel-Instanz, die auf Basis einer NarrativeModel-Instanz berechnet<br />

wird und dessen Ausführungssicht beschreibt, zu erwähnen. Zukünftige Untersuchungen<br />

werden zeigen müssen, inwiefern es geeignete Metriken gibt, die auf Basis dieses<br />

Modells zulässige Qualitätsaussagen oder Aussagen anderer Art treffen.<br />

Als zweites Artefakt entsteht während der Durchführung der Simulation eine SimulationModel-Instanz,<br />

die eine Menge von Traces beinhaltet. Die darin enthaltenen Informationen<br />

können in Zukunft möglicherweise genutzt werden, um Hotspots zu identi-<br />

85


fizieren. Hotspots sind Verhaltensbestandteile eines Anwendungsfalls, die übermäßig<br />

häufig zur (simulierten) Ausführung kommen, beispielsweise als Resultat von Schleifen.<br />

Auf diese Weise kann man bereits im Zuge der Spezifikation zentrale Verhaltensbestandteile<br />

des Zielsystems identifizieren und diesen in den sich anschließenden<br />

Phasen der Entwicklung entsprechend Beachtung schenken.<br />

Der konzeptionelle Unterbau der simulierten Ausführung von Anwendungsfällen auf<br />

Basis des ExecutionModels ist sicherlich fundiert. Ein offener Punkt betrifft die semantischen<br />

Variationen im ExecutionModel. An semantischen Variationspunkten stehen<br />

Verhaltensalternativen zur Auswahl, die nicht aus der Semantik von Elementen<br />

des NarrativeModels resultieren und infolgedessen einer gesonderten Behandlung bedürfen.<br />

Abschnitt 4.2.3 schildert die Problematik und zeigt einen möglichen Ansatz<br />

zur Lösung auf.<br />

Die restlichen Zielsetzungen betrafen die Benutzeroberfläche selbst. Bezüglich dieser<br />

Anforderungen kann ein durchgehend positives Fazit gezogen werden. Erwünscht war<br />

eine graphische Darstellung der Aktionsmöglichkeiten während der Simulation. Dies<br />

wird von der ExecutionModelView in Form von navigierbaren Aktivitätsdiagrammen<br />

realisiert. Außerdem gefordert war eine graphische Benutzeroberfläche, die sich an<br />

den etablierten Eclipse Prinzipien in diesem Bereich orientiert. Der Aufbau der Benutzeroberfläche<br />

der <strong>Simulationsumgebung</strong> folgt dem Eclipse UI-Paradigma, nach der<br />

ein zentraler Editor durch eine Menge Views, die Zusatzinformationen zu dem aktuellen<br />

Inhalt des Editors anzeigen, unterstützt wird. Dieser Ansatz ermöglicht dem<br />

Benutzer eine flexible und individuelle Anordnung seiner Workbench. Abhängig von<br />

den <strong>für</strong> ihn relevanten Informationen, kann der Benutzer die diversen Views in ihrer<br />

Darstellungsgröße- und Platzierung variieren, oder bei Bedarf auch komplett entfernen.<br />

Hierdurch wird eine benutzerfreundliche Benutzeroberfläche realisiert, die zudem<br />

noch individuell auf die Bedürfnisse des Benutzers angepasst werden kann.<br />

Die einzelnen Komponenten der <strong>Simulationsumgebung</strong> decken die von ihnen geforderte<br />

Zielfunktionalität ab. Im Folgenden werden allerdings noch Ideen zur Verbesserung<br />

der einzelnen Teile vorgestellt.<br />

6.1.1 Verbesserungsmöglichkeiten FlowView<br />

Derzeit ist die FlowView lediglich geeignet, dem Benutzer einen groben Überblick<br />

über die interne Struktur einer einzelnen NarrativeDescription zu verschaffen. Für<br />

die Zukunft ist angedacht, auch externe Beziehungen zwischen Flüssen verschiedener<br />

NarrativeDescriptions in der FlowView darzustellen und navigierbar zu machen.<br />

Demnach arbeitet die FlowView nicht mehr alleine auf Grundlage einer NarrativeDescription,<br />

die sie in ihrer Funktion als SelectionListener zur Verfügung gestellt bekommt,<br />

sondern kann selbst zwischen den verschiedenen NarrativeDescriptions eines<br />

NarrativeModels navigieren.<br />

Die graphische Darstellung von Ausnahmeflüssen ist derzeit ebenfalls noch nicht optimal.<br />

Wünschenswert wäre es, Ausnahmeflüsse graphisch als solche zu kennzeichnen<br />

86


und ihre Beziehungen zu den Bezugsflüssen zu visualisieren.<br />

Darüber hinaus sollten wichtige Zusatzinformationen, wie der Name eines Flusses,<br />

Teil der permanenten graphischen Darstellung sein und nicht erst auf Veranlassung<br />

von Benutzerinteraktionen eingeblendet werden.<br />

6.1.2 Verbesserungsmöglichkeiten ExecutionModelView<br />

Der primäre Zweck der ExecutionModelView ist die Visualisierung der verschiedenen<br />

Ablaufmöglichkeiten, die in einem ExecutionModel erfasst sind. Diese Anforderung<br />

wird zu diesem Zeitpunkt bereits erfolgreich umgesetzt. Darüber hinaus ist es erstrebenswert,<br />

dem Benutzer der View noch einen Mehrwert durch weitere Informationen<br />

zu bieten. Interessant ist es in diesem Zusammenhang, eine Brücke zurück zu den zugrundeliegenden<br />

NarrativeModel-Elementen zu schlagen.<br />

Als weitere mögliche Entwicklungsrichtung kann die Integration mit anderen Komponenten<br />

der ViPER-Plattform herangezogen werden. Vorstellbar ist beispielsweise eine<br />

Funktionalität zum Export der Aktivitätshierarchie, die aus einer ExecutionModel-<br />

Instanz gewonnen wurde, als UML-Modell. Damit können die Aktivitäten gesondert<br />

im ViPER-Aktivitätsdiagrammeditor weiterbearbeitet werden.<br />

6.1.3 Verbesserungsmöglichkeiten Simulator<br />

Zu diesem Zeitpunkt ist die Visualisierung der Auswahlmöglichkeiten im TraceEditor<br />

sehr rudimentär. Über die aktuell dargestellten Informationen hinaus sind weitere Kontextinformationen<br />

<strong>für</strong> den Benutzer interessant, z.B. wie häufig der derzeitig aktuelle<br />

Schritt bereits im Zuge der aktuellen Trace besucht wurde.<br />

Die SimulationView könnte neben ihrer Rolle als SelectionProvider weitere Benutzerinteraktionen<br />

ermöglichen. Beispielsweise könnten mittels Kontextmenü Aktionen<br />

zur Verfügung gestellt werden mit deren Hilfe sich Traces löschen oder der Simulation<br />

hinzufügen lassen.<br />

Die SimulationView könnte möglicherweise ersetzt werden durch den Einsatz einer<br />

Eclipse-eigenen View. Hier bietet sich die bereits in Abschnitt 3.1.3 vorgestellte OutlineView<br />

an. Die OutlineView stellt eine Übersicht des Inhalts des jeweils aktuellen<br />

Editors an. Sie verfügt über Mechanismen, die eine flexible Einbettung neuer Editoren<br />

ermöglichen. Der jetzige Inhalt der SimulationView könnte damit als Teil der Outline-<br />

View dargestellt werden.<br />

87


6.2 Softwaretechnische Evaluierung<br />

Im Zuge der technischen Umsetzung dieser Arbeit wurden diverse Rahmenwerke eingesetzt,<br />

die einen konzeptionellen Rahmen vorgeben.<br />

Aus der Realisierung der Arbeit innerhalb der Eclipse-Plattform folgt zwingend eine<br />

Strukturierung der verschiedenen Komponenten in Form von Plugins. Gemäß dem<br />

Seperation of Concerns Entwurfsprinzip sind ExecutionModel und SimulationModel<br />

jeweils Inhalt separater Plugins. Die diversen Views und der Editor sind ebenfalls auf<br />

verschiedene Plugins aufgeteilt.<br />

Der Einsatz von GEF <strong>für</strong> die Realsierung der Views zieht die Verwendung einer MVC-<br />

Architektur nach sich. Dieser Ansatz dient der Entkopplung des Modells von seiner<br />

graphischen Darstellung und Benutzerinteraktionen mittels Controller-Mechanismus.<br />

Durch die Nutzung von EMF zur Erzeugung des Modellcodes verfügt das Modell über<br />

Funktionalitäten, die bei manueller Implementierung des Modells aufwändig und fehleranfällig<br />

selbst zu realisieren wären. Dazu gehören u.a. ein Notifikationsmechanismus,<br />

der über Änderungen am Modell informiert, sowie eine Undo/Redo-Funktionalität.<br />

Wo die Architektur nicht durch ein Rahmenwerk bestimmt war, wurden Entwurfsmuster<br />

eingesetzt, um eine höchstmögliche Qualität des Designs und der Realisierung zu<br />

erzielen. Als Beispiel dient die Implementierung der ExecutionModel-Berechnung wie<br />

in Abschnitt 5.1 beschrieben. Hier wurde das Strategiemuster eingesetzt, um die komplexe<br />

Aufgabe der Modelltransformation in überschaubare Teilprobleme zu zerlegen<br />

und austauschbare Algorithmen in Form von Strategien zu realisieren. Da dieser Algorithmus<br />

einen zentralen Teil dieser Arbeit darstellt, wurde er außerdem ausführlich<br />

getestet. Die Testfälle <strong>für</strong> diesen Algorithmus decken zu diesem Zeitpunkt 90 Prozent<br />

seiner Anweisungen ab.<br />

Die Darstellung der ExecutionModelView selbst geschieht auf Grundlage einer Hierarchie<br />

von Aktivitäten. Hier wurden Profile eingesetzt, um die Darstellung der Aktivitäten<br />

weitgehend von den diesen zugrundeliegenen Elementen des ExecutionModels zu<br />

entkoppeln. Darstellungsaspekte, die von den Elementen des ExecutionModels selbst<br />

abhängen, wurden als konkrete Implementierungen generischer Schnittstellen gekapselt.<br />

Dank dieser Vorgehensweise ist eine gute Änderbarkeit der ExecutionModelView<br />

gewährleistet.<br />

Querschnittsaufgaben, die diverse Komponenten dieser Arbeit betreffen, wurden als<br />

abstrakte Konzepte in den Kern der ViPER-Plattform aufgenommen:<br />

• Abhängig von der Selektion des aktiven TraceEditors heben ExecutionModel-<br />

View und FlowView in ihren jeweiligen graphischen Darstellungen ein dazu<br />

passendes Element farblich hervor. Dieses „highlighting“ eines Elements ist<br />

konzeptionell verschieden von der Selektion eines Elements. Selektion impliziert,<br />

dass die Views ihrerseits das selektierte Element wiederum anderen Work-<br />

88


enchParts zur Verfügung stellen. Dies ist allerdings in diesem Kontext unerwünscht.<br />

Im Rahmen dieser Arbeit wurde das Highlighting-Konzept in Form<br />

einer generischen Implementierung <strong>für</strong> Views, die mittels GEF realisiert werden,<br />

wiederverwendbar gekapselt.<br />

• Alle Views und der TraceEditor sind SelectionListener und/oder SelectionProvider.<br />

Diese beiden Mechanismen wurden im Konzept der WorkbenchIntegration<br />

zusammengeführt und ihre Nutzung mittels Helferklassen vereinfacht.<br />

Die WorkbenchIntegration-Kapselung erlaubt außerdem die generische<br />

Realisierung der „Link to Editor“-Funktionalität einer View. Dies ist ein Eclipse-<br />

Konzept nach dem sich Views mittels Knopfdruck von Editoren entkoppeln lassen.<br />

Das bedeutet, dass eine entkoppelte View nicht mehr auf die Selektionen<br />

des Editors reagiert und auch umgekehrt dem Editor keinerlei Auswahlen mehr<br />

zur Verfügung stellt.<br />

• Generische Funktionalitäten <strong>für</strong> den Umgang mit EMF-Modellen aus einer View<br />

oder einem Editor heraus wurden in abstrakten Superklassen abgelegt. Hierbei<br />

gibt es jeweils eine Typhierarchie <strong>für</strong> Editoren und Views. Die Editor-Superklasse<br />

kapselt beispielsweise eine generische Implementierung zum Speichern der<br />

aktuell geöffneten EMF-Ressource.<br />

Im Laufe der Entstehung der Realisierung wurden Refaktorisierungen durchgeführt,<br />

die hauptsächlich auf die Verbesserung der Wartungsmöglichkeiten abzielten. Beispielsweise<br />

wurde der ursprünglich relativ komplizierte Algorithmus zur Berechnung<br />

der Aktivitätshierarchie zu einer ExecutionModel-Instanz komplett ersetzt durch einen<br />

simpleren und damit besser verständlichen Algorithmus.<br />

89


Kapitel 7<br />

Zusammenfassung und Ausblick<br />

Im Rahmen dieser Arbeit wurden Konzeption und Entwicklung eines Werkzeugs zur<br />

simulierten Ausführung von Anwendungsfällen <strong>für</strong> die ViPER-IDE beschrieben. Dabei<br />

wurde zunächst das theoretische Fundament in Form des UML-Metamodells und<br />

des NarrativeModels vorgestellt. Das NarrativeModel ist ein Metamodell <strong>für</strong> <strong>strukturierte</strong><br />

natürlichsprachliche Anwendungsfallbeschreibungen.<br />

In der Folge wurden die technischen Grundlagen <strong>für</strong> die Realisierung der <strong>Simulationsumgebung</strong><br />

erläutert. Hier stand die Beschreibung der Eclipse-Plattform und ihrer<br />

zentralen Konzepte im Mittelpunkt. Des Weiteren wurden verschiedene Rahmenwerke<br />

vorgestellt, die <strong>für</strong> die Realisierung dieser Arbeit von besonderem Interesse sind.<br />

Abgeschlossen wurde dieses Kapitel mit einer Betrachtung der ViPER-IDE und ihrer<br />

diversen Komponenten. Besonderes Augenmerk wurde hierbei auf die Beschreibung<br />

von ViPER NaUTiluS gelegt. NaUTiluS ist die Komponente, die sich mit der natürlichsprachlichen<br />

Beschreibung von Use Cases sowie deren Evaluierung und Simulation<br />

befasst.<br />

Danach wurde der konzeptuelle Lösungsansatz erläutert, in dessen Rahmen zwei Metamodelle<br />

entstanden sind. Das ExecutionModel bildet konzeptionell die Ausführungssicht<br />

auf das NarrativeModel. Es löst die im NarrativeModel vorhandenen Strukturinformationen<br />

auf und nimmt eine atomare Sicht auf einzelne Ausführungsschritte ein.<br />

Das ExecutionModel stellt die Grundlage <strong>für</strong> die Ausführung der Simulation dar. Als<br />

weiteres Metamodell wurde das SimulationModel vorgestellt, das die Konzepte der<br />

Simulation selbst kapselt.<br />

Auf Basis der konzeptuellen Grundlagen wurde die technische Realisierung beschrieben.<br />

Diese umfasst neben dem Algorithmus zur Berechnung einer ExecutionModel-<br />

Instanz aus einer NarrativeModel-Instanz heraus außerdem die verschiedenen graphischen<br />

Komponenten der <strong>Simulationsumgebung</strong>. Zu diesen Komponenten gehören die<br />

FlowView zur Visualisierung der statischen Struktur einer NarrativeDescription und<br />

die ExecutionModelView zur graphischen Darstellung und Veranschaulichung einer<br />

ExecutionModel-Instanz in Form navigierbarer Aktivitätsdiagramme. Zur Durchführung<br />

der Simulation selbst dient der Simulator, der sich wiederum zusammensetzt aus<br />

91


dem TraceEditor und der SimulationView. Zuletzt wurden die Integration des Editors<br />

und der einzelnen Views in die Eclipse-Workbench beschrieben. Hierbei wurde<br />

der Mechanismus der SelectionProvider und SelectionListener eingesetzt, um aus den<br />

Einzelkomponenten eine funktionsfähige <strong>Simulationsumgebung</strong> zusammenzusetzen.<br />

Die darauf folgende Evaluierung unterzog die erzielten Resultate dieser Arbeit einer<br />

Bewertung. Dabei wurde eine Beurteilung sowohl bezüglich der anfänglich formulierten<br />

Anforderungen auf der einen Seite und der allgemein erstrebenswerten softwaretechnischen<br />

Prinzipien und Qualitäten auf der anderen Seite vorgenommen.<br />

Weitergehende Schritte, die auf den Resultaten dieser Arbeit basieren, können in mehrere<br />

Richtungen unternommen werden. Forschungsbedarf besteht in dem Bereich der<br />

Evaluierung von Use Cases und ihrer textuellen Beschreibungen. Für eine gegebene<br />

NarrativeModel-Instanz könnte die dazugehörige ExecutionModel-Instanz als Basis<br />

<strong>für</strong> den Einsatz von Metriken dienen. Für diesen Zweck müssen geeignete Metriken<br />

konzipiert werden. Denkbar sind beispielsweise Metriken, die der Einschätzung der<br />

Komplexität des modellierten Systems dienen. Frühzeitige Komplexitätsabschätzungen<br />

können einen Anhaltspunkt <strong>für</strong> das Projektmanagement liefern, ob das Zielsystem<br />

mit den zur Verfügung stehenden Ressourcen realisierbar ist. Grundlage <strong>für</strong> diese Metrik<br />

könnte beispielsweise das Verhältnis zwischen der Anzahl der EventExecutions in<br />

einem ExecutionModel zur Anzahl der Events im zugrundeliegenden NarrativeModel<br />

sein. Je größer das Verhältnis, desto höher vermutlich die Komplexität des Systems 1 .<br />

Auf der praktischen Seite wird eine Kombination der <strong>Simulationsumgebung</strong> mit der<br />

bereits existierenden Perspektive zur Bearbeitung von NarrativeModel-Instanzen (vgl.<br />

Abschnitt 3.4.4) angestrebt. Orientiert an der Java-Debug-Perspektive in Eclipse, soll<br />

hierdurch eine Funktionalität entstehen, die es ermöglicht, Modellierung und Simulation<br />

zu verzahnen und so das Modell zu „debuggen“. Voraussetzung <strong>für</strong> die Umsetzung<br />

dieser Idee ist, dass die Berechnung einer ExecutionModel-Instanz aus einer gegebenen<br />

NarrativeModel-Instanz inkrementell erfolgt. Damit ist gemeint, dass Änderungen<br />

an der NarrativeModel-Instanz isoliert werden und ausschließlich die von den Änderungen<br />

betroffenen Elemente der ExecutionModel-Instanz neuberechnet werden. Es<br />

soll somit an dieser Stelle vermieden werden, eine komplett neue ExecutionModel-<br />

Instanz zu generieren, wenn die repräsentierte NarrativeModel-Instanz modifiziert wird.<br />

Der derzeitige Algorithmus zur Berechnung des ExecutionModels (siehe Abschnitt<br />

5.1) unterstützt dies zu diesem Zeitpunkt nicht. Die <strong>für</strong> diesen Zweck notwendigen<br />

Modifikationen sind nach einer ersten groben Abschätzung allerdings relativ überschaubar.<br />

1 Ein Event wird durch mehrere EventExecutions repräsentiert, wenn dieser Event in der Ausführung<br />

über verschiedene Wegen erreichbar ist.<br />

92


Literaturverzeichnis<br />

[BP06] BOLDT, NICK und MARCELO PATERNOSTRO: Introduction to the Eclipse<br />

Modeling Framework. Online, 2006.<br />

[BS02] BITTNER, KURT und IAN SPENCE: Use Case Modeling. Addison Wesley<br />

Object Technology, 2002.<br />

[BSM + 03] BUDINSKY, FRANK, DAVID STEINBERG, ED MERKS, RAYMOND EL-<br />

LERSICK und TIMOTHY J. GROSE: Eclipse Modeling Framework: A Developer’s<br />

Guide. Addison Wesley, 2003.<br />

[Coc00] COCKBURN, ALISTAIR: Writing Effective Use Cases. Addison Wesley,<br />

2000.<br />

[CR06] CLAYBERG, ERIC und DAN RUBEL: Eclipse: Building Commercial-<br />

Quality Plug-ins, 2nd Edition. Addison Wesley Professional, 2006.<br />

[DI06] Diagram Interchange, http://www.omg.org/docs/formal/06-04-04.pdf, 2006.<br />

[Do08] DO, HUY: Entwicklung eines Sequenzdiagramm-Editors <strong>für</strong> die ViPER<br />

Plattform. Diplomarbeit, RWTH Aachen, 2008.<br />

[Ecla] The Eclipse Project, http://www.eclipse.org.<br />

[Eclb] Eclipse Workbench: Using the Selection Service,<br />

http://www.eclipse.org/articles/Article-WorkbenchSelections/article.html.<br />

[Eclc] Inside the Workbench: A guide to the workbench internals,<br />

http://www.eclipse.org/articles/Article-UI-Workbench/workbench.html.<br />

[Ecld] Draw2d Programmer’s Guide, http://help.eclipse.org/help33.<br />

[Ecle] GEF Programmer’s Guide, http://help.eclipse.org/help33.<br />

[EMF] Eclipse Modeling Framework Project, http//www.eclipse.org/emf.<br />

[GEF] Graphical Editing Framework, http://www.eclipse.org/gef.<br />

[GHJV95] GAMMA, ERICH, RICHARD HELM, RALPH JOHNSON und JOHN M.<br />

VLISSIDES: Design Patterns: Elements of Reusable Object-Oriented Software.<br />

Addison Wesley, 1995.<br />

93


[Gom00] GOMAA, HASSAN: Designing Concurrent, Distributed, and Real-Time Applications<br />

with UML. Addison Wesley, 2000.<br />

[Her07] HERMANNS, MARCEL: Erweiterung der ViPER Umgebung zur methodengestützten<br />

Entwicklung mit MeDUSA. Diplomarbeit, RWTH Aachen, 2007.<br />

[Jac87] JACOBSON, IVAR: Object Oriented Development in an Industrial Environment.<br />

In: OOPSLA, Seiten 183–191, 1987.<br />

[JLS] The Java Language Specification, http://java.sun.com/docs/books/jls.<br />

[LL06] LUDEWIG, JOCHEN und HORST LICHTER: Software Engineering - Grundlagen,<br />

Menschen, Prozesse, Techniken. dpunkt.verlag, 2006.<br />

[LN07] LICHTER, HORST und ALEXANDER NYSSEN: MeDUSA - Method for<br />

UML2-based Design of Embedded Software Applications. 2007.<br />

[Mae] Maestro Download Page, http://mars.telascience.org/softwaredownload.<br />

[ML05] MCAFFER, JEFF und JEAN-MICHEL LEMIEUX: Eclipse Rich Client Platform:<br />

Designing, Coding and Packaging Java Applications. Addison Wesley<br />

Professional, 2005.<br />

[Obj03a] OBJECT MANAGEMENT GROUP: UML2.0 OCL Specification,<br />

http://www.omg.org/docs/ptc/03-10-14.pdf, 2003.<br />

[Obj03b] OBJECT TECHNOLOGY INC.: Eclipse Platform Technical Overview.<br />

http://www.eclipse.org/whitepapers/eclipse-overview.pdf, 2003.<br />

[Obj07a] OBJECT MANAGEMENT GROUP: UML Infrastructure Specification,<br />

http://www.omg.org/spec/UML/2.1.2, 2007.<br />

[Obj07b] OBJECT MANAGEMENT GROUP: UML Superstructure Specification,<br />

http://www.omg.org/spec/UML/2.1.2, 2007.<br />

[OMG] Object Management Group, http://www.omg.org.<br />

[OSG] OSGi Alliance, http://www.osgi.org.<br />

[Rat] IBM Rational Rose, http://www.ibm.com/software/rational.<br />

[SWT] The Standard Widget Toolkit, http://www.eclipse.org/swt.<br />

[UML] Unified Modeling Language, http://www.uml.org.<br />

[ViP] ViPER, http://www.viper.sc.<br />

[Wal07] WALTER, ANDREAS: Ein Use Case-Modellierungswerkzeug <strong>für</strong> die ViPER-<br />

Plattform. Diplomarbeit, RWTH Aachen, 2007.<br />

94

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!