Übersicht Inhaltsverzeichnis Vorwort 1 Einführung 2 Klassendiagramme 3 Object Constraint Language 4 Objektdiagramme 5 Statecharts 5.1 Eigenschaften von Statecharts 5.2 Automatentheorie und Interpretation 5.3 Zustände 5.4 Transitionen 5.5 Aktionen 5.6 Statecharts im Kontext der UML 5.7 Zusammenfassung 6 Sequenzdiagramme A Sprachdarstellung durch Syntaxklassendiagramme B Java C Die Syntax der UML/P D Anwendungsbeispiel: Internet-basiertes Auktionssystem Literatur |
5.4 TransitionenEine Transition beschreibt einen Ausschnitt des Objektverhaltens. Wenn das Objekt im Quellzustand der Transition ist und die Schaltbedingung erfüllt, dann kann die Transition durchgeführt werden. Dabei wird eine Aktion ausgeführt und der Zielzustand der Transition eingenommen. Dieser Abschnitt beschäftigt sich im Detail mit Stimuli und Schaltbedingungen, die zur Ausführung einer Transition führen. Im nächsten Abschnitt werden die Aktionen diskutiert. Abbildung 5.21 zeigt ein Statechart mit den bereits aus Abbildung 5.13 bekannten Zustandsübergängen für die Klasse Auction. Es zeigt, wie Vorbedingungen für Transitionen definiert werden, und dass Transitionen Zustandshierarchien beliebig überschreiten können. 5.4.1 Bedingungen innerhalb der ZustandshierarchieDie mit start() markierte Transition führt vom Zustand AuctionReady in den Subzustand AuctionRegularOpen. Neben der explizit angegebenen Vorbedingung gibt es eine zusätzliche Vorbedingung, die aus dem Quellzustand AuctionReady resultiert. Die vollständige Vorbedingung für diese Transition ist also:
timePol.status == TimingPolicy.READY_TO_GO && Die zur Schließung einer Auktion führende Transition finish() hat den Quellzustand AuctionOpen. Da dieser Zustand durch seine Subzustände vollständig partitioniert ist (©), ist es äquivalent, stattdessen zwei Transitionen von den beiden Subzuständen ausgehen zu lassen. Die beiden in den Abbildungen 5.22 und 5.23 dargestellten Äquivalenzen beschreiben dies als allgemeine Regeln. 5.4.2 Start- und Endzustand in der ZustandshierarchieDie im Statechart in Abbildung 5.21 beschriebene Transition start() hat als Zielzustand den Subzustand AuctionRegularOpen. Alternativ ist es möglich, diese Transition nur zum Superzustand AuctionOpen zu führen. Dann ist jedoch zunächst nicht beschrieben, in welchem der beiden Subzustände die Auktion nach Ausführung dieser Transition tatsächlich ist. In Abbildung 5.24 wird daher modelliert, dass eine Auktion nach ihrem Start zunächst in der regulären Phase läuft. Dies wird durch Verwendung einer Startzustandsmarkierung innerhalb eines hierarchisch partitionierten Zustands vorgenommen. Die mit den Abbildungen 5.21 und 5.24 angedeutete Äquivalenz lässt sich allgemein wie in Abbildung 5.25 gezeigt ausdrücken. Diese Regel kann auch mehrfach angewandt werden, wenn der initiale Subzustand seinerseits wieder durch mehrere Subzustände verfeinert wurde. In analoger Weise ist es auch möglich, Endzustandsmarkierungen innerhalb hierarchischer Zustände zu verwenden. Diese dienen dazu, zu beschreiben, wann Transitionen, die vom Superzustand wegführen, ausgeführt werden dürfen. Abbildung 5.26 demonstriert die zugehörige Regel. Weil jedoch die Übersichtlichkeit des Statecharts sehr schnell darunter leidet, wird empfohlen, Markierungen für Start- und Endzustände nur sehr sparsam einzusetzen. Aus demselben Grund sollte die Hierarchiebildung bei Automaten sorgsam eingesetzt werden. Beinhaltet ein Superzustand keine Start- und Subzustände, so ist dies äquivalent dazu, dass alle Subzustände auch Startzustände sind. Das gleiche gilt bei fehlenden Endzuständen. Abbildung 5.27 illustriert diese Äquivalenzen. 5.4.3 Stimuli für TransitionenArten von StimuliNachdem der Zusammenhang zwischen Transitionen und der Zustandshierarchie hergestellt ist, wird in diesem Abschnitt diskutiert, welche Ereignisse zur Auslösung von Transitionen führen können. Es werden fünf verschiedene Kategorien von Stimuli, die zur Auslösung einer Transition führen, unterschieden:
Gemäß der zum Beispiel aus Implementierungen von Corba [OH98] oder von verteilten Architekturmodellen [HRR10, GHK+08] bekannten Vorgehensweise bei der Implementierung von nachrichtenbasierter Kommunikation kann angenommen werden, dass das Management der Nachrichten, also zum Beispiel die Pufferung und die Übertragung durch ein geeignetes Framework, in der Laufzeitumgebung realisiert wird. Für das empfangende Objekt macht es dementsprechend keinen Unterschied, ob ein Methodenaufruf asynchron oder als normaler Methodenaufruf übermittelt wird. Im Statechart wird deshalb auch keine Unterscheidung zwischen beiden Arten von Stimuli getroffen. Es ergeben sich deshalb die in Abbildung 5.28 dargestellten Arten von Stimuli für Transitionen. ObjektrekursionIn Abschnitt 5.2.7 wurde bereits bei flachen Automaten diskutiert, dass diese für die Darstellung rekursiver Aufrufstrukturen nicht geeignet sind. Bei Statecharts manifestiert sich dieses Problem in der Form, dass die Implementierung zwar objektrekursive Aufrufe durchführen kann, die Modellierung durch Statecharts dies aber nicht adäquat berücksichtigt. Objektrekursion tritt immer dann auf, wenn eine gerade in Abarbeitung befindliche Methode eines Objekts direkt oder indirekt zum Aufruf einer weiteren Methode desselben Objekts führt. Zwar ist es möglich, in den nachfolgend noch diskutierten prozedural formulierten Aktionen weitere Methodenaufrufe durchzuführen, die ihrerseits Transitionen auslösen, jedoch entstehen dadurch eine Reihe semantischer Probleme. Zum einen ist es unklar, in welchem Zustand sich das Objekt tatsächlich befindet, wenn der rekursive Methodenaufruf stattfindet. Es kann den Quellzustand bereits verlassen und den Zielzustand bereits erreicht haben oder sich in einem nicht definierten Zwischenzustand befinden. Zum anderen ist unklar, ob der rekursive Methodenaufruf nicht zu weiteren Zustandsveränderungen führt, so dass der im Statechart dargestellte Zielzustand nicht dem tatsächlich erreichten Objektzustand entspricht. Um einerseits dem Problem zu entgehen, andererseits aber die gerade auch in Entwurfsmustern [Pre95] häufig verwendete Objektrekursion explizit zuzulassen, wird die aus der Praxis heraus motivierte Beobachtung genutzt, dass die Methoden eines Objekts meistens in zwei Ebenen eingeteilt werden können.
Die Bestimmung der Top-Level-Methoden eines Objekts kann durch explizite Angabe (zum Beispiel unter Verwendung eines geeigneten Stereotyps) oder durch Extraktion der in einem Statechart explizit als Stimuli verwendeten Methoden erfolgen. Ob diese Methoden tatsächlich keine Objektrekursion durchführen, kann durch eine Datenflussanalyse auf Basis des Programmcodes festgestellt werden.5 5.4.4 SchaltbereitschaftNachdem das Aussehen der Stimuli für eine Transition und das Zusammenspiel von Transitionsvorbedingungen mit der Zustandshierarchie festgelegt wurden, lässt sich nun präzise definieren, wann eine Transition schaltbereit ist. Dazu müssen die folgenden Bedingungen erfüllt sein:
Es kann vorkommen, dass eine Vorbedingung in keiner Situation erfüllt werden kann. In diesem Fall ist die Transition sinnlos, da sie nie durchgeführt wird. Ist eine Transition schaltbereit, so bedeutet dies nicht notwendigerweise, dass diese Transition auch durchgeführt wird. Es ist möglich, dass mehrere Transitionen gleichzeitig schaltbereit sind. Dies ist nicht verboten, sondern im Gegenteil unter Umständen explizit erwünscht, um, wie bereits in Abschnitt 5.2 besprochen, den Entwicklern die Möglichkeit zu geben, Entwurfsentscheidungen zunächst aufzuschieben und entweder den Implementierern oder sogar der Implementierung zur Laufzeit zu überlassen. Nichtdeterminismus im Statechart bedeutet normalerweise nicht, dass die Implementierung nichtdeterministisch ist. Meistens werden die zur Aufhebung dieses Nichtdeterminismus notwendigen Entscheidungen zur rechten Zeit getroffen. Überlappende Schaltbereitschaft bedeutet also im Wesentlichen eine Unterspezifikation, die sich in verschiedenen Varianten ausprägen kann. Abbildung 5.29 zeigt zwei erlaubte Situationen überlappender Schaltbereiche. In beiden Fällen (a) und (b) sind jeweils beide Alternativen möglich und können je nach Art der beigefügten Aktion oder des weiteren Verhaltens des Zielzustands zu sehr unterschiedlichem Gesamtverhalten des modellierten Objekts führen. Um Unterspezifikation, wie die in Abbildung 5.29 gezeigte, zu beheben, gibt es mehrere Möglichkeiten. Neben der offensichtlichen Variante, eine der beiden Transitionen zu streichen, gibt es die Möglichkeit, die beiden überlappenden Schaltbereiche durch eine Verstärkung der Vorbedingungen beider Transitionen in disjunkte Schaltbereiche zu überführen. Eine weitere Möglichkeit zur Auflösung von Unterspezifikation, die sich vor allem bei Transitionen unterschiedlicher Hierarchieebenen eignet, wie in Abbildung 5.29 (b) dargestellt, ist die Verwendung von Prioritäten. Im Gegensatz zu klassischen Statecharts [Har87] und der auf objektorientierte Systeme angepassten Form der Statecharts [HG97] werden keine impliziten Prioritäten verwendet, also weder die innere Transition vor der äußeren, noch umgekehrt, bevorzugt. Die Vergabe von Prioritäten kann zum Beispiel durch einen Stereotyp der Form ≪prio=4≫ erfolgen, der mit einem ganzzahligen Wert behaftet ist. Nicht nur aus Kompatibilität zu bisherigen Statechart-Dialekten ist die Verwendung eines Stereotyps der Form ≪prio:inner≫ oder ≪prio:outer≫ sinnvoll, um inneren oder äußeren Transitionen den Vorrang zu geben. Abbildung 5.30 illustriert die Wirkung dieser beiden Stereotypen. Tabelle 5.31 führt die beiden Stereotypen ein.
5.4.5 Unvollständiges StatechartDer Fall mehrerer gleichzeitig für eine Situation zur Verfügung stehender schaltbereiter Transitionen wurde im letzten Abschnitt ausführlicher diskutiert. Es kann jedoch auch der umgekehrte Fall eintreten, dass es für einen ankommenden Stimulus in einem bestimmten Zustand keine Transition gibt, die diesen Stimulus verarbeiten kann. Ein solches Statechart wird als unvollständig angesehen. Es gibt analog zu den Automaten (Abschnitt 5.2.5) mehrere Interpretationsmöglichkeiten für diese Situation, die teilweise erhebliche Unterschiede bedeuten:
Wie in Abschnitt 5.2.6 diskutiert, ergeben sich damit Unterschiede in der Interpretation des Lebenszyklus eines Objekts. In den ersten beiden Interpretationen wird der Lebenszyklus als maximal möglich, in der letzten als minimal zugesichert verstanden. Dies ist besonders für die in Abschnitt 5.6.2 diskutierten Transformationen wesentlich. Die ersten beiden Interpretationen der Unvollständigkeit sind sinnvoll, wenn das Statechart für die Implementierung gedacht ist. Tatsächlich ist das Ignorieren unverarbeitbarer Stimuli nur ein Sonderfall der expliziten Fehlerbehandlung. Gibt es eine einheitliche Fehlerbehandlung, so kann diese durch Hinzufügen eines mit dem Stereotyp ≪error≫ markierten Zustands als entry-Aktion modelliert werden. Der Stereotyp ≪error≫ wird eingesetzt, wenn explizite Transitionen zum Abfangen von Fehlern zum Beispiel aus Gründen der Übersichtlichkeit nicht gewünscht sind. Abbildung 5.32 zeigt eine Einsatzmöglichkeit. Die Verwendung eines expliziten Fehlerzustands wie in Abbildung 5.32 hat jedoch den Nachteil, dass nur eine allgemeine gleichförmige Fehlerbehandlung möglich ist. Eine Rückkehr in den Ausgangszustand kann so nicht modelliert werden. Für alternative Behandlungen von Fehlersituationen können weitere Stereotypen, wie zum Beispiel ≪completion:ignore≫, für das ganze Statechart aber auch für einzelne Zustände eingesetzt werden. Aus pragmatischen Gründen werden die normalen Fehlersituationen, in denen die Schaltbereitschaft für einen Stimulus fehlt, vom Empfang einer Exception unterschieden. Für die Behandlung von Exception-Stimuli steht zusätzlich der Stereotyp ≪exception≫ zur Verfügung, der als einziger auftretende Exceptions abfängt. Statecharts werden im Verlauf des Entwicklungsprozesses definiert und können zwischendurch unvollständig sein, ohne dass für diese Unvollständigkeit eine Fehlerbehandlung intendiert wäre. Des Weiteren können Statecharts absichtlich unvollständig sein, wenn sie zum Beispiel zur Definition von Tests verwendet werden. Die für Tests intendierte Semantik von Statecharts besagt, dass in Fällen in denen das Statechart eine Aussage trifft, dieses Verhalten vom Objekt erfüllt werden muss. Trifft das Statechart keine Aussage, so hat das Objekt jedoch völlige Freiheit. Die dritte der oben genannten Möglichkeiten zur Interpretation von Unvollständigkeit eignet sich daher vor allem zum Einsatz von Statecharts in Tests. Mit dem Stereotyp ≪completion:chaos≫ kann dieses Verhaltensmuster für ein ganzes Statechart festgelegt werden. Die Tabellen 5.33, 5.34 und 5.35 führen die drei genannten neuen Stereotypen zur Behandlung von Unvollständigkeit in Statecharts ein.
Die in diesem Abschnitt vorgeschlagenen Interpretationen zur Behandlung von unvollständigen Statecharts können, wie aus der Automatentheorie bekannt, auch durch eine explizite Vervollständigung der Transitionen vorgenommen werden. Bei einem mit dem Stereotyp ≪completion:ignore≫ markierten Statechart sind alle unvollständigen Zustände durch Schleifen zu ergänzen. Diese Schleifen beginnen und enden jeweils im gleichen Zustand, verarbeiten alle noch nicht anderweitig verarbeiteten Stimuli, produzieren aber keine Zustandsänderung oder Ausgabe. Bei Verwendung eines Fehlerzustands müssten diese Transitionen nicht auf ihren Ursprungszustand zurückgeführt werden, sondern in den markierten Fehlerzustand münden. Bei einer Chaos-Vervollständigung mit ≪completion:chaos≫ wären sehr viel mehr Transitionen einzuführen, da sie von allen unvollständigen Zuständen in alle Zustände des Statecharts führen können. Die Aktionen dieser Transitionen haben beliebige Freiheit. Sie können den Zustand des modellierten Objekts sowie seiner Umgebung frei verändern, Objekte neu anlegen, etc. Auch nichtterminierende Aktionen sind bei der Chaos-Vervollständigung nicht ausgeschlossen. Während die ersten beiden Formen der Vervollständigung für eine Implementierung durchaus sinnvoll sind, ist aufgrund der Explosion an Transitionen offensichtlich, dass eine Chaos-Vervollständigung ein gedankliches Experiment zur Erklärung der Bedeutung eines Statecharts ist, nicht jedoch zur Implementierung ausgeführt werden sollte.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||