Zustandsmaschinen werden verwendet, um das dynamische Verhalten eines Modellelements und noch spezifischer die
ereignisgesteuerten Aspekte des Systemverhaltens zu modellieren (siehe Konzept:
Ereignisse und Signale). Zustandsmaschinen werden insbesondere verwendet, um zustandsabhängiges Verhalten oder
Verhalten zu definieren, das je nach Zustand des Modellelements variiert, zu definieren. Modellelemente, dessen
Verhalten nicht mit dem Zustand des Elements variiert, erfordern keine Zustandsmaschine für die Beschreibung ihres
Verhaltens. Diese Elemente sind in der Regel passive Klassen, die primär für die Verwaltung von Daten zuständig sind.
Zustandsmaschinen müssen verwendet werden, um das Verhalten aktiver Klassen zu modellieren, die Aufrufereignisse und
Signalereignisse verwenden, um ihre Operationen zu implementieren (als Übergänge in der Zustandsmaschine der Klasse).
Eine Zustandsmaschine setzt sich aus Zuständen zusammen, die durch Übergänge verbunden sind. Ein Zustand ist eine
Bedingung eines Objekts, in dem er eine Aufgabe ausführt oder auf ein Ereignis wartet. Ein Übergang ist eine Beziehung
zwischen zwei Zuständen, der durch ein Ereignis ausgelöst wird, der bestimmte Aktionen oder Auswertungen ausführt und
der zu einem bestimmten Endzustand führt. Die Elemente einer Zustandsmaschine sind in Abbildung 1 dargestellt.
Abbildung 1. Darstellung einer Zustandsmaschine
Sie können sich einen einfachen Editor als finite Zustandsmaschine mit den Zuständen Leer, Warten auf
Befehl und Warten auf Text vorstellen. Die Ereignisse Datei laden, Text einfügen, Zeichen
einfügen und Speichern und verlassen bewirken Übergänge in der Zustandsmaschine. Die Zustandsmaschine für
den Editor ist in Abbildung 1 dargestellt.
Abbildung 2. Die Zustandsmaschine für einen einfachen Editor
Ein Zustand ist eine Bedingung eines Objekts, in dem er eine Aufgabe ausführt oder auf ein Ereignis wartet. Ein Objekt
kann für eine begrenzte Zeit in einem Zustand verbleiben. Ein Zustand hat mehrere Eigenschaften:
Name
|
Eine Zeichenfolge, anhand der dieser Zustand von anderen Zuständen unterschieden wird. Ein Zustand kann
auch anonym sein, d. h. er hat keinen Namen.
|
Eintritts-/Austrittsaktionen
|
Aktionen, die beim Eintritt in einen und Austritt aus einem Zustand ausgeführt werden.
|
Interne Übergänge
|
Übergänge, die keine Zustandsänderung bewirken.
|
Unterzustände
|
Die verschachtelte Struktur eines Zustands mit disjunkten (sequenziell aktiven) oder parallelen
(gleichzeitig aktiven) Unterzuständen.
|
Verzögerte Ereignisse
|
Eine Liste mit Ereignissen, die in diesem Zustand nicht bearbeitet werden, aber für die Bearbeitung
durch ein Objekt in einem anderen Zustand zurückgestellt und in eine Warteschlange gestellt werden.
|
Wie in Abbildung 1 gezeigt, können für die Zustandsmaschine eines Objekts zwei Sonderzustände definiert werden. Der
Anfangszustand gibt den Ausgangspunkt für die Zustandsmaschine bzw. den Unterzustand an. Ein Anfangszustand wird als
gefüllter schwarzer Kreis dargestellt. Der Endzustand zeigt den Abschluss der Ausführung der Zustandsmaschine oder den
Abschluss des übergeordneten Zustands an. Ein Endzustand wird als gefüllter schwarzer Kreis in einem nicht gefüllten
Kreis angezeigt. Anfangs- und Endzustände sind in Wirklichkeit Pseudozustände. Beide können mit Ausnahme eines Namens
dieselben Eigenschaften wie ein normaler Zustand haben. Ein Übergang von einem Anfangszustand in einen Endzustand kann
das vollständige Komplement von Features einschließlich einer Wächterbedingung und einer Aktion, aber kein
Auslöseereignis haben.
Ein Übergang ist eine Beziehung zwischen zwei Zuständen, die anzeigt, dass ein Objekt im ersten Zustand bestimmte
Aktionen ausführt und dann in einen zweiten Zustand wechselt, wenn ein bestimmtes Ereignis eintritt und bestimmte
Bedingungen erfüllt sind. Bei einer solchen Zustandsänderung wird der Übergang "ausgelöst". Bis der Übergang ausgelöst
wird, ist das Objekt im "Quellenzustand". Nachdem der Übergang ausgelöst wurde, ist das Objekt im "Zielzustand". Ein
Übergang hat mehrere Eigenschaften:
Quellenzustand
|
Der durch den Übergang betroffene Zustand. Wenn ein Objekt im Quellenzustand ist, kann ein
Ausgangsübergang ausgelöst werden, wenn das Objekt das Auslöserereignis empfängt und die
Wächterbedingung, sofern vorhanden, erfüllt ist.
|
Ereignisauslöser
|
Das Ereignis, das den Übergang auslöst (vorausgesetzt, dass die Wächterbedingung erfüllt ist), wenn es
vom Objekt im Quellenzustand empfangen wird.
|
Wächterbedingung
|
Ein Boolescher Ausdruck, der ausgewertet wird, wenn der Übergang durch den Empfang des
Ereignisauslösers ausgelöst wird. Wenn die Auswertung des Booleschen Ausdrucks true ergibt, wird der
Übergang ausgelöst. Ist das Ergebnis der Auswertung false, wird der Übergang nicht ausgelöst. Falls
kein anderer Übergang vorhanden ist, der durch dasselbe Ergebnis ausgelöst werden könnte, geht das
Ereignis verloren.
|
Aktion
|
Eine ausführbare atomare Berechnung, die direkt mit das Objekt, das Eigner der Zustandsmaschine ist,
oder indirekt andere Objekten bearbeiten kann, die für das Objekt sichtbar sind.
|
Zielzustand
|
Der Zustand, der nach Abschluss des Übergangs aktiv ist.
|
Ein Übergang kann mehrere Quellen haben. In diesem Fall stellt der Übergang eine Verknüpfung mehrerer paralleler
Zustände sowie mehrerer Ziele und damit eine Verzweigung zu mehreren parallelen Zuständen dar.
Im Kontext einer Zustandsmaschine ist ein Ereignis das Vorkommen eines Stimulus, das einen Zustandsübergang auslösen
kann. Ereignisse können Signalereignisse, Aufrufereignisse, das Vergehen von Zeit oder eine Änderung eines Zustands
sein. Ein Signal oder ein Aufruf kann Parameter haben, deren Werte für den Übergang verfügbar sind, einschließlich
Ausdrücken für die Wächterbedingungen und die Aktion. Auslöserlose Übergänge sind ebenfalls möglich. Diese werden durch
einen Übergang ohne Ereignisauslöser dargestellt. Diese Übergänge, auch Abschlussübergänge genannt, werden implizit
ausgelöst, wenn der zugehörige Quellenzustand seine Aufgabe ausgeführt hat.
Eine Wächterbedingung wird ausgewertet, nachdem das Auslöseereignis für den Übergang eingetreten ist. Es kann mehrere
Übergänge aus demselben Quellenzustand mit demselben Ereignisauslöser geben, solange die Wächterbindungen nicht
überlappen. Eine Wächterbedingung wird nur einmal und zwar, wenn das Ereignis eintritt, für den Übergang ausgewertet.
Der Boolesche Ausdruck kann auf den Zustand des Objekts verweisen.
Eine Aktion ist eine ausführbare atomare Berechnung, d. h. sie kann nicht durch ein Ereignis unterbrochen werden und
wird deshalb bis zur Fertigstellung ausgeführt. Eine Aufgabe hingegen kann von anderen Ereignissen unterbrochen werden.
Aktionen können Operationsaufrufe (an den Eigner der Zustandsmaschine sowie andere sichtbare Objekte), das Erstellen
und Löschen eines anderen Objekts oder das Senden eines Signals an ein anderes Objekt beinhalten. Wenn ein Signal
gesendet wird, wird dem Signalnamen das Schlüsselwort 'send' vorangestellt.
Eintritts- und Austrittsaktionen ermöglichen, dass dieselbe Aktion bei jedem Eintritt bzw. Austritt in den Zustand
verteilt werden kann. Durch die Eintritts- und Austrittsaktionen erfolgt dieser Vorgang sauber, ohne die Aktionen
explizit in jeden Eingangs- oder Ausgangsübergang stellen zu müssen. Eintritts- und Austrittsaktionen können keine
Argumente und Wächterbedingungen haben. Die Eintrittsaktionen auf der Ausgangsebene einer Zustandsmaschine für ein
Modellelement können Parameter haben, die die Argumente darstellen, die die Maschine empfängt, wenn das Element
erstellt wird.
Mit internen Übergängen können Ereignisse in der Zustandsmaschine bearbeitet werden, ohne den Zustand zu verlassen. Auf
diese Weise wird das Auslösen von Eintritts- oder Austrittsaktionen verhindert. Interne Übergänge können Ereignisse mit
Parametern und Wächterbedingungen haben und stellen im Wesentlichen Interrupt-Handler dar.
Verzögerte Ereignisse sind Ereignisse, deren Bearbeitung so lange zurückgestellt wird, bis ein Zustand aktiv wird, in
dem das Ereignis nicht mehr zurückgestellt wird. Wenn dieser Zustand aktiv wird, wird das Ereignis ausgelöst und kann
Übergänge so auslösen, als wäre es gerade erst eingetreten. Die Implementierung von verzögerten Ereignissen setzt das
Vorhandensein einer internen Warteschlange von Ereignissen voraus. Wenn ein Ereignis eintritt, aber als verzögertes
Ereignis aufgelistet ist, wird es in die Warteschlange gestellt. Ereignisse werden aus dieser Warteschlange genommen,
sobald das Objekt einen Zustand erreicht, in dem diese Ereignisse nicht mehr zurückgestellt werden.
Ein einfacher Zustand ist ein Zustand, der keine Unterstruktur hat. Ein Zustand, der Unterzustände (verschachtelte
Zustände) hat, ist ein zusammengesetzter Zustand. Unterzustände können bis zu einer beliebigen Ebene verschachtelt
werden. Eine verschachtelte Zustandsmaschine kann maximal einen Anfangszustand und einen Endzustand haben.
Unterzustände werden verwendet, um komplexe, flache Zustandsmaschinen zu vereinfachen, und zeigen, dass gewisse
Zustände nur in einem bestimmten Kontext möglich sind (übergeordneter Zustand).
Abbildung 3. Unterzustände
Von einer Quelle außerhalb eines übergeordneten zusammengesetzten Zustands kann ein Übergang den zusammengesetzten
Zustand oder einen Unterzustand als Ziel haben. Wenn das Ziel der zusammengesetzte Zustand ist, muss die verschachtelte
Zustandsmaschine einen Anfangszustand haben, an den die Steuerung nach dem Eintritt in den zusammengesetzten Zustand
und nach der Verteilung der Eintrittsaktion (sofern vorhanden) übergeben wird. Wenn das Ziel der verschachtelte Zustand
ist, wird die Steuerung an den verschachtelten Zustand übergeben, nachdem die Eintrittsaktion des zusammengesetzten
Zustands (sofern vorhanden) und anschließend die Eintrittsaktion des verschachtelten Zustands (sofern vorhanden)
verteilt wurde.
Ein Übergang, der von einem zusammengesetzten Zustand ausgeht, kann als Quelle den zusammengesetzten Zustand oder einen
Unterzustand haben. In beiden Fällen verlässt die Steuerung zuerst den verschachtelten Zustand (und die zugehörige
Austrittsaktion, sofern vorhanden, wird verteilt) und anschließend den zusammengesetzten Zustand (und die zugehörige
Austrittsaktion, sofern vorhanden, wird verteilt). Ein Übergang, dessen Quelle der zusammengesetzte Zustand ist,
unterbricht die Aufgabe der verschachtelten Zustandsmaschine.
Sofern nicht anders angegeben, beginnt beim Eintritt eines Übergangs in einen zusammengesetzten Zustand die Aktion der
verschachtelten Zustandsmaschine wieder beim Anfangszustand (sofern das direkte Ziel des Übergangs kein Unterzustand
ist). Historienzustände erlauben der Zustandsmaschine, erneut in den letzten aktiven Unterzustand vor dem Verlassen des
zusammengesetzten Zustands zu wechseln. Ein Beispiel für einen Historienzustand ist in Abbildung 3 dargestellt.
Abbildung 4. Historienzustand
Zustandsmaschinen sind ein gängiges Mittel, um das Verhalten eines Objekts in seinem Lebenszyklus zu modellieren. Sie
werden insbesondere dann benötigt, wenn Objekt zustandsabhängiges Verhalten aufweisen. Zu den Objekten, die
Zustandsmaschinen haben können, gehören Klassen, Subsysteme, Anwendungsfälle und Schnittstellen (um Zustände
zuzusichern, die von einem Objekt erfüllt werden müssen, das die Schnittstelle realisiert). Bei Echtzeitsystemen werden
Zustandsmaschinen auch für Kapseln und Protokolle verwendet (um Zustände zuzusichern, die von einem Objekt erfüllt
werden müssen, das das Protokoll realisiert).
Nicht alle Objekte erfordern Zustandsmaschinen. Wenn das Verhalten eines Objekts einfach ist, z. B. dass das Objekt
einfach Daten speichert oder abruft, ist das Verhalten des Objekts zustandsunabhängig und seine Zustandsmaschine
relativ uninteressant.
Zur Modellierung der Lebensdauer eines Objekts gehören drei Dinge: die Ereignisse angeben, auf die ein Objekt antworten
kann, die Antwort auf diese Ereignisse und die Auswirkung des Geschehenen auf das aktuelle Verhalten. Außerdem muss bei
der Modellierung der Lebensdauer eines Objekts die Reihenfolge festgelegt werden, in der das Objekt sinnvoll auf
Ereignisse reagieren kann, angefangen vom Zeitpunkt, zu dem das Objekt erstellt wird, bis hin zu dem Zeitpunkt, zu dem
das Objekt gelöscht wird.
Gehen Sie zum Modellieren der Lebensdauer eines Objekts wie folgt vor:
-
Legen Sie den Kontext für die Zustandsmaschine fest, egal ob es sich um eine Klasse, einen Anwendungsfall oder das
System als Ganzen handelt.
-
Wenn der Kontext eine Klasse oder ein Anwendungsfall ist, stellen Sie die Nachbarklassen, einschließlich
der übergeordneten Klassen und der Klassen zusammen, die durch Assoziationen oder Abhängigkeiten erreichbar
sind. Diese Nachbarklassen sind potenzielle Ziele für Aktionen und für den Einschluss in
Wächterbedingungen.
-
Wenn der Kontext das System als Ganzes ist, grenzen Sie den Schwerpunkt auf ein Verhalten des Systems ein
und machen Sie sich dann Gedanken über die Lebensdauer der Objekte, die zu diesem Aspekt gehören. Die
Lebensdauer des gesamten Systems ist einfach zu groß, um einen sinnvollen Schwerpunkt zu bilden.
-
Legen Sie den Anfangs- und den Endzustand für das Objekt fest. Wenn es Vorbedingungen oder Nachbedingungen für den
Anfangs- und den Endzustand gibt, definieren Sie auch diese.
-
Bestimmen Sie die Ereignisse, auf die das Objekt reagiert. Sie finden diese Ereignisse in den Schnittstellen des
Objekts. Bei Echtzeitsystemen sind diese auch in den Protokollen des Objekts zu finden.
-
Ordnen Sie die übergeordneten Zustände, angefangen beim Anfangszustand bis hin zum Endzustand, fest, die das Objekt
annehmen kann. Verbinden Sie diese Zustände durch Übergänge, die durch die entsprechenden Ereignisse ausgelöst
werden. Fahren Sie fort, indem Sie diese Übergänge hinzufügen.
-
Identifizieren Sie jede Eintritts- und jedes Austrittsaktion.
-
Erweitern oder vereinfachen Sie die Zustandsmaschine mit Unterzuständen.
-
Stellen Sie sicher, dass alle Ereignisse, die Übergänge in der Zustandsmaschine auslösen, Ereignissen entsprechen,
die von den vom Objekt realisierten Schnittstellen erwartet werden. Prüfen Sie außerdem, ob alle Ereignisse, die
von den Schnittstellen des Objekts erwartet werden, in der Zustandsmaschine berücksichtigt werden. Bei
Echtzeitsystemen müssen Sie entsprechende Prüfungen für die Protokolle einer Kapsel vornehmen. Suchen Sie
schließlich nach Stellen, an denen Sie Ereignisse explizit ignorieren möchten (z. B. verzögerte Ereignisse).
-
Stellen Sie sicher, dass alle Aktionen in der Zustandsmaschine durch Beziehungen, Methoden und Operationen des
übergeordneten Objekts unterstützt werden.
-
Verfolgen Sie die Zustandsmaschine und vergleichen Sie sie mit den erwarteten Abfolgen von Ereignissen und
Antworten. Suchen Sie nach unerreichbaren Zuständen und Zuständen, in denen die Maschine blockiert.
-
Wenn Sie die Zustandsmaschine neu anordnen oder umstrukturieren, müssen Sie sicherstellen, dass die Semantik nicht
geändert wurde.
-
Wenn Sie die Möglichkeit haben, verwenden Sie die visuelle Semantik der Zustandsmaschine, anstatt detaillierten
Übergangscode zu schreiben. Lösen Sie beispielsweise nicht einen Übergang bei mehreren Signalen aus und verwenden
dann Detailcode, um den Steuerungsablauf je nach Signal anders zu verwalten. Verwenden Sie getrennte Übergänge, die
von getrennten Signalen ausgelöst werden. Vermeiden Sie bedingte Logik in Übergangscode, der zusätzliches Verhalten
verbirgt.
-
Benennen Sie Zustände danach, auf was Sie warten oder was während des Zustands passiert. Denken Sie daran, dass ein
Zustand kein 'Zeitpunkt' ist, sondern ein Zeitraum, in dem die Zustandsmaschine auf etwas wartet. Beispiel eignet
sich der Name 'WartenAufEnde' besser als 'Ende' und 'ZeitplanungEinerAufgabe' besser als 'Zeitlimit'. Benennen Sie
Zustände nicht so, als wären sie Aktionen.
-
Benennen Sie alle Zustände und Übergänge in einer Zustandsmaschine einheitlich. Damit wird das Debugging auf
Quellenebene einfacher.
-
Verwenden Sie Zustandsvariablen (Attribut zum Steuern des Verhaltens) mit Vorsicht. Verwenden Sie sie nicht, um
sich das Erstellen neuer Zustände zu sparen. Zustandsvariablen können verwendet werden, wenn es nur wenige Zustände
mit wenig oder keinem zustandsabhängigen Verhalten oder wenig oder gar kein Verhalten gibt, das parallel zum oder
unabhängig vom Objekt erbracht wird. Wenn es sich um komplexes, zustandsabhängiges Verhalten mit potenziell
parallelem Charakter handelt oder wenn Ereignisse, die verarbeitet werden müssen, nicht aus dem Objekt mit der
Zustandsmaschine stammen, können Sie eine Kollaboration von zwei oder mehr aktiven Objekten (möglicherweise
definiert als Komposition) verwenden. In Echtzeitsystemen sollte komplexes, zustandsabhängiges, paralleles
Verhalten mit einer Kapsel modelliert werden, die unterordnete Kapseln enthält.
-
Wenn es mehr als 5 ± 2 Zustände in einem Diagramm gibt, können Sie Unterzustände verwenden. Zehn Zustände in einem
vollkommen regulären Muster können in Ordnung sein, aber zwei Zustände mit 40 Übergängen zwischen ihnen müssen
offensichtlich neu überdacht werden. Stellen Sie sicher, dass die Zustandsmaschine verständlich ist.
-
Benennen Sie Übergänge danach, was das Ereignis auslöst und/oder was während des Übergangs passiert. Wählen Sie
Namen, die der Verständlichkeit zuträglich sind.
-
Wenn Sie einen Auswahlscheitelpunkt sehen, müssen Sie sich fragen, ob Sie die Zuständigkeit für diese Auswahl an
eine andere Komponente delegieren können, so dass sie dem Objekt als eindeutige Signalgruppe präsentiert werden
kann (z. B. anstelle einer Auswahl von Nachricht-> Daten> x), oder ob Sie dem Sender oder einem anderen
zwischengeschalteten Akteur die Entscheidung überlassen sollen, der dann ein Signal mit der Entscheidung explizit
im Signalnamen senden soll (verwenden Sie z. B. Signale mit den Namen istVoll und istLeer anstelle von Signalen mit
den Namen Wert und Nachrichtendatenprüfen).
-
Benennen Sie die beim Auswahlscheitelpunkt zu beantwortete Frage beschreibend, z. B. 'istImmerNochWasLos' oder
'istEsZeitSichZuBeschweren'.
-
Versuchen Sie, die Namen von Auswahlscheitelpunkten in einem Objekt eindeutig zu halten (aus demselben Grund wie
bei den Namen von Übergängen).
-
Enthalten Übergänge überlange Codefragmente? Sollten stattdessen Funktionen verwendet werden, und werden allgemeine
Codefragmente als Funktionen erfasst? Ein Übergang sollte sich wie Pseudocode auf hoher Ebene lesen lassen und sich
an dieselben oder sogar strengere Regeln halten als C++-Funktionen. Ein Übergang mit mehr als 25 Zeilen ist
übermäßig lang.
-
Funktionen sollten danach benannt werden, was sie tun.
-
Schenken Sie Eintritts- und Austrittsaktionen besondere Aufmerksamkeit. Es passiert relativ leicht, Änderungen
vorzunehmen und dann zu vergessen, die Eintritts- und Austrittsaktionen zu ändern.
-
Austrittsaktionen können als Sicherheits-Features verwendet werden (beispielsweise schaltet die Austrittsaktion aus
dem Zustand 'HeizungAn' die Heizung aus). Die Aktionen dienen hier als Zusicherung.
-
Im Allgemeinen sollten Unterzustände mindestens zwei Zustände enthalten, sofern die Zustandsmaschine nicht abstrakt
ist und von Unterklassen des übergeordneten Elements präzisiert wird.
-
Auswahlpunkte können anstelle von bedingter Logik in Aktionen und Übergängen verwendet werden. Auswahlpunkte sind
leicht erkennbar, wohingegen bedingte Logik im Code in der Sicht verdeckt und leicht zu übersehen ist.
-
Vermeiden Sie Wächterbedingungen.
-
Wenn das Ereignis mehrere Übergänge auslöst, kann nicht gesteuert werden, welche Wächterbedingung zuerst
ausgewertet wird. Deshalb sind die Ergebnisse nicht vorhersehbar.
-
Es könnten mehrere Wächterbedingungen wahr sein, aber es kann nur einem Übergang gefolgt werden. Der
ausgewählte Pfad ist möglicherweise nicht unvorhersehbar.
-
Wächterbedingungen sind nicht visuell und damit schwerer zu erkennen.
-
Vermeiden Sie Zustandsmaschinen, die Ablaufdiagrammen gleichen.
-
Dies kann auf einen Versuch hinweisen, eine Abstraktion zu modellieren, die eigentlich nicht vorhanden ist,
z. B.:
-
Verwendung einer aktiven Klasse zur Modellierung von Verhalten, das sich am besten für eine passive
oder eine Datenklasse eignet.
-
Modellierung einer Datenklasse unter Verwendung einer Datenklasse und einer aktiven Klasse, die eng
miteinander gekoppelt sind (d. h. die Datenklasse wird für die Übergabe von Typinformationen
verwendet, aber die aktive Klasse enthält die meisten Daten, die der Datenklasse zugeordnet werden
müssen).
-
Dieser unsachgemäße Gebrauch von Zustandsmaschinen lässt sich an den folgenden Symptomen erkennen:
-
Nachrichten, die primär "an sich selbst" gesendet werden, um einfach Code wiederzuverwenden.
-
Wenige Zustände mit vielen Auswahlpunkten.
-
In einigen Fällen eine Zustandsmaschine ohne Zyklen. Solche Zustandsmaschinen sind gültig in
Prozesssteuerungsanwendungen oder zur Steuerung einer Ereignisfolge. Ihr Vorhandensein während der
Analyse stellt gewöhnlich die Degeneration der Zustandsmaschine in ein Ablaufdiagramm dar.
-
Wenn Sie das Problem identifiziert haben, können Sie wie folgt vorgehen:
-
Die aktive Klasse in kleinere Einheiten mit eindeutigeren Zuständigkeiten unterteilen.
-
Mehr Verhalten in eine Datenklasse verschieben, die der fraglichen aktiven Klasse zugeordnet ist.
-
Mehr Verhalten in die Funktionen der aktiven Klasse verschieben.
-
Aussagefähigere Signal erstellen, anstatt sich auf Daten zu verlassen.
Eine abstrakte Zustandsmaschine ist eine Zustandsmaschine, der weitere Details zugeordnet werden müssen, damit sie für
praktische Zwecke eingesetzt werden kann. Abstrakte Zustandsmaschinen können verwendet werden, um generisches,
wiederverwendbare Verhalten zu definieren, das in nachfolgenden Modellelementen weiter präzisiert wird.
Abbildung 5. Eine abstrakte Zustandsmaschine
Schauen Sie sich die abstrakte Zustandsmaschine in Abbildung 5 an. Die dargestellte Beispielzustandsmaschine
repräsentiert die abstrakteste Verhaltensebene (den Steuerautomaten) vieler unterschiedlicher Typen von Elementen in
ereignisgesteuerten Systemen. Obwohl alle Elemente dieses Verhalten der oberen Ebene aufweisen, können die
unterschiedlichen Elementtypen je nach ihrem Zweck stark unterschiedliches Detailverhalten im Zustand "Aktiv" haben.
Deshalb liegt es nahe, diese Zustandsmaschine in einer abstrakten Klasse zu definieren, die als Stammklasse für die
unterschiedlichen, spezialisierten aktiven Klassen dient.
Lassen Sie uns deshalb zwei solche Präzisierungen dieser abstrakten Zustandsmaschine durch Vererbung definieren. Diese
beiden Präzisierungen R1 und R2 sehen Sie in Abbildung 6. Zur Verdeutlichung werden die von der übergeordneten Klasse
geerbten Elemente mit einem grauen Stift gezeichnet.
Abbildung 6. Zwei Präzisierungen der Zustandsmaschine in Abbildung 5.
Die beiden Präzisierungen unterscheiden sich klar darin, wie sie den Zustand "Aktiv" zerlegen und wie sie den
ursprünglichen Übergang "Start" erweitern. Diese Auswahl kann natürlich erst getroffen werden, nachdem die Präzisierung
bekannt ist, und hätte nicht mit einem einzelnen End-to-End-Übergang in der abstrakten Klasse vorgenommen werden
können.
Die Fähigkeit, Eingangs- und Ausgangsübergänge "fortzuführen" ist für den zuvor beschriebenen Typ von Präzisierung
grundlegend. Eintrittspunkte und Endzustände kombiniert mit fortgeführten Übergängen scheinen für die Unterstützung
dieser Semantik ausreichend zu sein. Dies ist jedoch leider nicht der fall, wenn mehrere unterschiedliche Übergänge
erweitert werden müssen.
Für das abstrakte Verhaltensmuster ist eine Methode erforderlich, mit der zwei oder mehr Übergangssegmente verkettet
werden können, die alle im Rahmen eines vollständigen Schritts ausgeführt werden. Das bedeutet, dass Übergänge in einen
hierarchischen Zustand in den Eingangsteil, der an der Zustandsgrenze endet, und eine Erweiterung, die innerhalb des
Zustands fortgesetzt wird, aufgeteilt werden. Ausgangsübergänge aus einem hierarchisch verschachtelten Zustand werden
in einen Teil, der an der Grenze des übergeordneten Zustands endet, und einen Teil, der von der Zustandsgrenze in den
Zielzustand fortgeführt wird, unterteilt. Dieser Effekt kann in UML mit dem neuen Konzept des Durchgangszustands
erreicht werden. Dieses Konzept wird mit einem Stereotyp (<<Durchgangszustand>> (Chain State)) des Konzepts
des UML-Zustands modelliert. Es handelt sich hierbei um einen Zustand, dessen einziger Zweck die "Verkettung" weiterer
automatischer (ohne Auslöser) Übergänge zu einem Eingangsübergang ist. Ein Durchgangszustand hat keine interne
Struktur, keine Eintrittsaktion, keine interne Aufgabe und keine Austrittsaktion. Außerdem hat keine Übergänge, die von
Ereignissen ausgelöst werden. Er kann jedoch eine Reihe von Eingangsübergängen haben. Er kann einen Ausgangsübergang
ohne Auslöserereignis haben. Dieser Übergang wird automatisch ausgelöst, wenn ein Eingangsübergang den Zustand
aktiviert. Der Durchgangszustand verkettet einen Eingangsübergang mit einem separaten Ausgangsübergang. Zwischen den
Eingangsübergängen und dem verketteten Ausgangsübergang wird ein Zustand mit einem anderen Zustand innerhalb des
übergeordneten Zustands und der andere Zustand mit einem anderen Zustand außerhalb des übergeordneten Zustands
verbunden. Durch den Durchgangszustand wird eine Trennung der internen Spezifikation des übergeordneten Zustands von
seiner externen Umgebung erreicht. Es handelt sich hierbei um eine Art der Kapselung.
Ein Durchgangszustand (oder Pass-Through-Zustand) verkettet einen Übergang mit einem bestimmten fortgeführten Übergang.
Wenn kein fortgeführter Übergang definiert ist, endet der Übergang im Durchgangszustand. In diesem Fall muss ein
Übergang in einem übergeordneten Zustand ausgelöst werden, damit es weitergehen kann.
Das Segment mit der Beispielzustandsmaschine in Abbildung 7 veranschaulicht Durchgangszustände und ihre Darstellung.
Durchgangszustände werden in einem Zustandsmaschinendiagramm durch kleine weiße Kreise im entsprechenden hierarchischen
Zustand dargestellt (diese Darstellung gleicht der von Anfangs- und Endzuständen, denen die Durchgangszustände ähneln).
Die Kreise sind Stereotypsymbole für den Stereotyp "Durchgangszustand" (Chain State) und werden normalerweise nahe der
Grenze gezeichnet. (Eine Darstellungsvariante ist, diese Symbole direkt auf der Grenze zum übergeordneten Zustand zu
zeichnen.)
Abbildung 7. Durchgangszustände und verkettete Übergänge
Der verkettete Übergang in diesem Beispiel setzt sich aus den drei verketteten Übergangssegmenten e1/a11-/a12-/a13
zusammen. Wenn Signal e1 empfangen wird, wird der Übergang e1/a11 gewählt, seine Aktion a11 wird ausgeführt, und
schließlich wird der Übergangszustand c1 erreicht. Danach wird der fortgeführte Übergang zwischen c1 und c2 gewählt,
und da c2 auch ein Übergangszustand ist, danach der Übergang von c2 nach S21. Wenn die Zustände entlang dieser Pfade
Austritts- und Eintrittsaktionen haben, werden die Aktionen wie folgt nacheinander ausgeführt:
-
Austrittsaktion von S11
-
Aktion a11
-
Austrittsaktion von S1
-
Aktion a12
-
Eintrittsaktion von S2
-
Aktion a13
-
Eintrittsaktion von S21
Alle Aktionen werden im Rahmen eines einzelnen vollständigen Schritts ausgeführt.
Vergleichen Sie dies mit der Aktionsausführungssemantik des direkten Übergangs e2/a2:
-
Austrittsaktion von S11
-
Austrittsaktion von S1
-
Aktion a2
-
Eintrittsaktion für Zustand S2
-
Eintrittsaktion für Zustand S21
|