Würfelspiel kleines Projekt in Rational Rose Lars Hofer, Admir Kulin 1. Kurzbeschreibung und allgemeine Hinweise Bei diesem Projekt wurde ein kleines Spiel modelliert, welches einen Würfel darstellt und von nur einer Person gespielt werden kann. Um doch ein wenig Komplexität zu erreichen, um damit entsprechende Beziehungen und Zusammenhänge der einzelnen Diagramme und Sichten in Rational Rose zu erläutern, wurde eine QuasiClient/Server-Komponente und eine Komponente, die das tatsächliche Spielen durchführt (das Würfeln) realisiert. In diesem Projekt wurde aber weder Bedacht auf Mehrbenutzer-Spielmöglichkeit noch auf RMI(Kommunikation gelegt). Wichtig ist, das Projekt von vornherein als Java-Projekt zu spezifizieren, da dadurch die notwendigen Einstellungen vorgenommen und alle für Java notwendigen Klassen inklusive deren Packages vordefiniert werden. Beim späteren Laden des Projektes sollten die Frage „Load Subunits of x.mdl?“ mit „ja“ quittiert werden, um auch hier alle für Java notwendigen Package- und Klassendefinitionen zu erhalten. Ob Java als Projektsprache eingestellt ist, kann durch den Eintrag in Tools (Hauptmenü) | Options... | Notation | Default Language kontrolliert werden. Hier sollte „Java“ stehen. Ausgehend vom Use Case Model wurden für die in der Use Case View vorkommenden, statisch dargestellten Anwendungsfälle ein Activity Diagram erstellt, dass den zeitlichen Ablauf dieser Anwendungsfälle aus der Sicht des Spielers veranschaulicht. Anhand der Use Case View und des Activity Diagram kann man sich schon überlegen, welche Klassen bzw. Komponenten man für das Class Diagram in der Logical View bzw. welche Komponenten und Packages für die Component Diagramme in der Component View benötigt. Wichtig ist hier, dass es für jede Komponente der Component View mindestens eine public-Klasse geben muss, die den selben Namen wie eine der Komponenten (entspricht einer *.java-Datei) hat. Hat man die auf jeden Fall notwendigen Klassen (bzw. Komponenten) eingeführt, so kann man anhand eines Sequence Diagrams und der Statecharts überlegen, welche Methoden (Operationen) und KlasssenVariablen (Attribute) notwendig sind, um die unter den Klassen ablaufenden Messages und Interaktionen zu realisieren. Diese Methoden und Klassenvariablen werden dann in den Class Diagrammen genauer spezifiziert (Typ, Rückgabewerte,...). Wenn es notwendig erscheint, weitere Klassen, Methoden oder Variablen für diese Klassen einzuführen, so können diese dann auch dazu genutzt werden, dass Sequence-Diagramm zu verfeinern, oder überhaupt neue Konzepte darzustellen. Dies Änderung dort, im Sequence-Diagramm können wieder zu Änderungen in den anderen Diagrammen, möglicherweise sogar im Use-Case-Model führen. Hat dieser iterative Prozess eine bestimmte Detail-Ebene erreicht und das Modell für das erste ausreichend spezifiziert erscheint, kann man für die Klassen durch Rational Rose ein Gerüst in Java erstellen (Java Codegenerierung) und auf diesem Code basierend die tatsächliche Implementierung durchführen. Sollten bei der Implementierung und tatsächlichen Realisierung die Einführung weiterer Klassen, Methoden oder Variablen notwendig sein, so können diese durch Reverse Engineering in das Rational Rose Modell übernommen werden. Zu letzt werden die notwendige Hardware und Komponenten (im großen, z.B. Client, Server,...) im Deployment Diagram dargestellt. 2. Use Case View In der Use Case View werden alle für den Ablauf notwendigen Aktoren (Actors) dargestellt, die Anwendungsfälle (Use Cases), die auftreten können, eingeführt und die Relationen (Associations) zwischen den Aktoren und den Use-Cases und den Use-Cases untereinander erstellt. Bei diesem einfachen Modell hat nur ein Spieler die Anwendungsfällen „Anmelden“, „Spielen“ und „Abmelden“ vor sich. Beim Anmelden gibt der Spieler seinen Namen bekannt Wurde ein korrekter Name eingegeben (entspricht hier einer nicht leeren Zeichenfolge), so wird der Spieler zum Spiel weitergeleitet, wo er aufgeforder wird, zu würfeln („w“ eingeben), oder das Spiel wieder zu verlassen („q“ eingeben). Wenn der Spieler sich für eine Spielaktion entscheidet, dann wird einfach eine Zufallszahl zwischen 1 und 6 ausgegeben und der Spieler erneut aufgefordert, zu würfeln, oder das Spiel zu verlassen. Hat er sich dagegen zum Verlassen entschieden, wird der Spieler mit einer bestimmten Meldung vom System abgebemeldet. Diese Sachverhalte lassen sich in den Documentations der Aktoren, der Use Cases und möglicherweise auch der Assoziationen beschreiben (Aufruf z.B. durch Kontextmenü (rechte Maustaste) eines Diagramm-Elementes und dann Open Specification... | General | Documentation: ) Um zwischen diesen statischen Zusammenhängen der Anwendungsfälle zeitliche Abfolgen darzustellen, wird ein Activity Diagram erstellt. 3. Activity Diagram Das Activity Diagram zeigt dynamische Abläufe der in der Use Case View modellierten Anwendungsfälle. Da dies meist ebenfalls aus der Sicht des Aktors, in diesem Fall des Spielers erfolgt, wurde ein Diagramm für das Activity Diagram durch das Kontextmenü für den Spieler (rechte Maustaste) und dann Subdiagrams | new Activity Diagram hinzugefügt. Hier werden dann ausgehend von einem Startzustand alle möglichen Aktivitäten (Activities), Zustände (States), mögliche Verzweigungen (Decisions) und auch die Übergänge (Transistions) zwischen diesen Elementen bis hin zu einem Endzustand modelliert, um die alle möglichen Zeitabläufe des Uses Case Models darzustellen. Wichtig ist hier, die jeweiligen Aktionen, die durch einen Aktor, durch das System oder andere Teile durchgeführt werden, durch das sogenannte Swimlane zu trennen Für jeden identifizierten Aktor oder jedes Systemteil (im grossen gesehen) sollte ein weiteres Swimlane (Button in der Toolleiste), also eine neue Spalte angelegt werden. In dem Diagramm für dieses Beispiel wurde das Anmelden, die Überprüfung des eingegebenen Namens, das eigentliche Spielen (Würfeln) und das Abmelden modelliert. Anhand der Use Case View und der Activity Diagram können jetzt die notwendigen Klassen zur Realisierung dieser Modelle identifiziert und im Class Diagram der Logical View angelegt werden. 4. Class Diagram Die im Use Case Model bestimmten Klassen werden nun im Class Diagram angelegt und deren Assoziationen untereinander hergestellt. Bei komplexeren Systemen kann es notwendig sein, gleich von vornherein Packages einzuführen. Diese werden dann auf Java-Packages abgebildet. Im Class Diagram bzw. in der zu diesem Diagramm gehörenden Baumunterstruktur des Logical-View-Zweiges sollten auch die Packages (und somit auch die dazugehörenden Klassen) sichtbar sein; sie sind unbedingt notwendig, um die bekannten Java-Klassen für das eigenen Projekt (als Variablentyp, Rückgabewert,...) einzusetzten. In diesem Beispiel wurde ein Package „Wuerfelspiel“ angelegt und in diesem zwei Klassen: „Verwaltung“ und „Spiel“: Hinweis: Die in diesem Bild ersichtlichen und zu den Klassen gehörenden Methoden und Variablen wurden erst später im Zuge des Sequenzdiagrammes eingeführt. Durch Doppelklick auf eine Klasse oder über das Kontextmenü Open Specification... läßt sich diese dann genauer bestimmen. Zum Beispiel läßt sich die Sichtbarkeit der Klasse, ob ein Default Constructor generiert werden soll (wurde für die Klasse „Spiel“ abgeschaltet), welche Klasse diese Klasse erweitert und welche Interfaces sie implementiert, festlegen und es können Kommentare im Java-Doc-Format für diese Klasse generiert werden: Für jede in diesen Klassendiagrammen vorkommende public-Klasse sollte sofort eine Komponente in der Component View angelegt werden, die denselben Namen der Klasse trägt und der *.java-Datei entspricht, in der diese Klasse dann generiert wird. Nachdem mit Hilfe des Sequence Diagrams für die Klassen die Methoden angelegt und spezifiziert wurden, können auch zur Speicherung notwendiger Daten die Klassen-Variablen durch das Kontextmenü für eine Klasse (im Logical View Teilbaum) und durch New | Attribute und Angabe des Namens angelegt werden. Durch Doppelklick auf Variable wird dann diese genauer spezifiziert (Typ,...): 5. Sequence Diagram Um ein Sequenzdiagramm mit verschachtelten durchnumerierten Sequenzen und Objektaktivitäten zu erhalten, muß unter Tools (Hauptmenü) | Options... | Diagram diese Einstellung vorgenommen werden (aktiviert): [x] Sequence Numbering [x] Hierarchical Messages [x] Focus of control Um einerseits die zeitlichen Abläufe zwischen den Klassen ähnlich wie die zeitlichen Abläufe beim Use Case Model durch das Activity Diagram darzustellen und andererseits dafür notwendige Methoden der Klassen zu bestimmen, wird ein Sequence Diagram angelegt: Zuerst werden die für die Darstellung notwendigen Aktoren (Spieler) aus dem Use Case Model und die Klassen (Objekte) aus dem Class Diagram in das Sequence Diagram gezogen. Objekte die viele Interaktionen untereinander durchführen, sollten relativ nahe zusammen stehen. Zwischen den Objekten werden nun die Interaktionen eingezeichnet und benannt. Kann man diese Interaktion gleich als Methodenaufruf eines Objektes festlegen, so geht man folgendermaßen vor, um für die entsprechenden Klasse gleich diese Methode anzulegen (diese wird dann bei der Klasse in der Baumteilstruktur des Logical Views eingehängt): Zuerst wird die Interaktion (Object Message) zwischen den beiden interagierenden Klassen angelegt. Durch das Kontextmenü (rechte Maustaste) und <new operation> kann eine neue Methode angelegt und spezifiziert werden: Schon bei Klassen vorhandene Methoden können durch einen Doppelklick auf dies Message, die ihrem Aufruf entspricht, um ihre Spezifikation zu öffnen und über General | Name bestimmt werden Durch Drücken der Taste „F5“ kann zum automatisch generierten Collaboration Diagram gewechselt werden. 6. Collaboration Diagram Das Collaboration Diagram zeigt dieselben Beziehungen (Messages / Methodenaufrufe) der Objekte im Sequence Diagram, aber nicht in zeitlicher, sonder in statisch Sicht: 7. Statechart Um ein detailierteres Bild über die schon vorhandenen Methoden zu bekommen, oder überhaupt neue Methoden und auch notwendige Klassenvariablen zu identifizieren , werden für alle Klassen durch das Kontextmenü (recht Maustaste) in der Baumteilstruktur in der Logical View durch New | Statechart Statecharts hinzugefügt. Ähnlich wie das Activty Diagram für die Anwendungsfälle des Use Case Models, zeigt das Statechart alle möglichen Zustände (States), die ein Objekt während seiner Lebenszeit einnimmt. Dabei werden von einem Startzustand ausgehend, alle möglichen Zwischenzustände bis zum Endzustand und die Übergänge (State Transistions), also Ursachen für Zustandswechsel modelliert. Für bestimmte Zustände werden, wenn notwendig mehrere interne Aktionen bestimmt, die dann beim Betreten (entry), während (do) oder beim Verlassen (exit) des Zustandes, oder bei Vorhandensein eines bestimmten Ereignisses (on event) durchgeführt werden sollen: Die Aktionen werden durch Doppelklick auf den Zustand und Actions und dann durch das Kontextmenü (rechte Maustaste) und Insert und dann Doppelklick auf „Type“ und über Detail | When der Typ der Aktion bestimmt und über Detail | Name der Name (Beschreibung) der Aktion angegeben. 8. Component View In den Component Diagrams der Component View wird die physische Seite des Modells dargestellt. In diesem Fall sind das Java-Packages (Packages) oder *.java-Dateien (Components), wobei die Abhängigkeiten zwischen diesen Komponenten hergestellt werden, wobei bei sich die Beziehung des Class Diagrams hier wiederspiegeln. Hier ist das Java-Package für das Würfelspiel gezeigt: Die Packages (auch verschachtelte) werden durch das Kontextmenü der Component View oder des übergeordneten Packages durch New | Package hinzugefügt. Da bei Java nur eine public-Klasse in einer *.java-Datei definiert sein kann, muß für jede im Class Diagram vorhandene public-Klasse eine Komponente mit demselben Namen in der Component View erzeugt werden. Die Beziehung zwischen den Klassen aus der Logical View und den Komponenten der Component View wird durch Hineinziehen der Klassen aus der Logical View auf die entsprechende Komponenten hergestellt. Dass diese Beziehung vorhanden ist, sieht man daran, dass der Komponentenname in Klammern dem Klassenname in der Logical View folgt. Sollten Komponenten (Klassen) in einem Java-Package vorhanden sein, so müssen diese auch in dem Package über das Kontextmenü des entsprechenden Packages durch New | Component hinzugefügt werden. Durch Doppelklick auf eine Komponente wird diese genauer spezifiziert. Hier können die Imports für diese Java-Komponente (diese Java-Datei) und dergleichen bestimmt werden: 9. Deployment View Das Deployment View stellt das Mapping von Prozessen zur Hardware dar. Zum Beispiel, welcher Prozess (Client, Server,...) auf welcher Maschine läuft und wie diese von einander abhängig sind. In diesem Beispiel wurde nur gezeigt, dass dieses Spiel mit keinem anderen Komponente (z.B. über RMI) kommunziert und daher nur von einer JVM abhängig ist: 10. Codegenerierung Wenn für alle Klassen, Methoden und Attribute und auch Komponenten die notwendigen Spezifikationen durchgeführt und die Beziehungen der Klassen bzw. der Komponenten untereinander modelliert wurden, kann die Codegenerierung für die Gerüste der Klassen erfolgen. Zuerst muss aber ein CLASSPATH angegeben werden, unter dem die Packages und *.java-Dateien erstellt werden sollen. Dies erfolgt durch: Tools | Java | Project Specification... Im oberen Teil Enviroment Settings: sollte der von Windows übernommene CLASSPATH stehen. Ist dieser nicht vorhanden muss in jeden Fall unter Directories: ein gültiger Pfad angegeben werden: Zur Codegenierung werden dann in der Baumunterstruktur der Logical View alle Klassen markiert und dann per Kontextmenü (rechte Maustaste) und Java | Generate Java die Codegenerierung gestartet. Beim ersten mal muss noch der CLASSPATH auf die Packages gemappt werden: Eventuell bei der Codegenerierung aufgetretene Warnungen oder Fehler werden im Log-Fenster aufgelistet und sollten auf jeden Fall beachtet werden: Der für eine Klasse generierte Code kann durch das Kontextmenü einer Klasse und Java | Browse Java Source angezeigt und bearbeitet (Implementierung) werden. Der generierte Code schaut in etwa so aus: 11. Implementierung Bei der Implementierung darf nur Code in den schon vorhandenen Methoden eingefügt werden. Z.B.: Sollten neue Variablen oder neue Methoden eingefügt werden, so müssen diese durch Reverse Engineering Rational Rose bekannt gemacht werden. 12. Ressourcen Das Rational Rose Modell ist zu finden auf: ebola.ifs.univie.ac.at/~hofer/rational/Spiel.mdl die dazugehörenden Java-Dateien auf: ebola.ifs.univie.ac.at/~hofer/rational/Wuerfelspiel/Verwaltung.java ebola.ifs.univie.ac.at/~hofer/rational/Wuerfelspiel/Spiel.java Und dieses Dokument unter: ebola.ifs.univie.ac.at/~hofer/rational/Wuerfelspiel.doc