Linea guida: Diagramma di stato
I Diagrammi di stato sono una notazione grafica per le specifiche delle macchine a stati, utilizzati per modellare il comportamento dinamico degli elementi del modello. Questa linea guida presenta questa notazione e spiega come utilizzarla in modo efficace.
Relazioni
Descrizione principale

Spiegazione

Le macchine a stati vengono utilizzate per modellare il comportamento dinamico di un elemento del modello e, più specificamente, aspetti del comportamento del sistema guidati dall'evento (consultare Concetto: Eventi e segnali). Le macchine a stati vengono espressamente utilizzate per definire il comportamento dipendente dallo stato o il comportamento che varia in rapporto allo stato in cui si trova l'elemento del modello. Gli elementi del modello il cui comportamento non varia con lo stato dell'elemento, non richiede macchine a stati per descriverne il comportamento (questi elementi sono classi tipicamente passive la cui principale responsabilità è quella di gestire dati). In particolare, le macchine a stati devono essere usate per modellare il comportamento delle classi attive che utilizzano gli eventi di chiamata per implementare le loro operazioni (come transizioni nelle macchine a stati della classe).

Una macchina a stati è costituita da stati, collegati a transizioni. Uno stato è una condizione di un oggetto in cui vengono eseguiti alcuni compiti o si attende un evento. Una transizione è una relazione tra due stati attivati da alcuni eventi che esegue certe azioni o valutazioni e che termina in uno specifico stato-di-fine. Gli elementi di una macchina a stati sono descritti nella Figura 1.

Diagramma illustrativo della notazione della macchina a stati.

Figura 1. Notazione della macchina a stati.

Un semplice editor può essere visualizzato come macchina a stati finita, con gli stati di Vuota, In attesa di un comando e In attesa di testo. Gli eventi Carica file, Inserisci testo, Inserisci carattere e Salva ed esci causano delle transizioni nella macchina a stati. La macchina a stati per l'editor viene descritta nella Figura 1 di seguito riportata.

Diagramma descritto nella figura.

Figura 2. La macchina a stati per un editor semplice.

Stati

Uno stato è una condizione di un oggetto in cui vengono eseguiti alcuni compiti o si attende un evento. Un oggetto può rimanere in uno stato per un quantitativo di tempo finito. Uno stato ha diverse proprietà:

Nome Una stringa di testo che distingue lo stato dagli altri stati; uno stato può anche essere anonimo, cioè senza nome.
Azioni di entrata/uscita Azioni eseguite entrando e uscendo dallo stato.
Transizioni interne Transizioni gestite senza causare un cambio di stato.
Stati secondari La struttura nidificata di uno stato, che coinvolge gli stati secondari disgiunti (attivi sequenzialmente) o simultanei (attivi simultaneamente).
Eventi posticipati Un elenco di eventi non gestiti in quello stato ma posticipati e messi in coda perché vengano gestiti dall'oggetto in un altro stato.

Come descritto nella Figura 1, sono presenti due stati speciali che possono essere definiti per una macchina a stati dell'oggetto. Lo stato iniziale indica il luogo predefinito di partenza per la macchina a stati o per lo stato secondario. Uno stato iniziale viene rappresentato con un cerchio in nero. Lo stato finale indica il completamento dell'esecuzione della macchina a stati o che lo stato di inclusione è stato completato. Uno stato finale viene rappresentato da un cerchio nero circondato da un cerchio vuoto. Gli stati di inizio e di fine sono proprio pseudostati. Nessuno dei due può avere le parti usuali di uno stato normale, tranne che per il nome. Una transizione dallo stato iniziale a quello finale può avere il completamento totale delle funzioni, inclusa una condizione di guardia ed una azione, ma può non avere un evento trigger.

Transizioni

Una transizione è una relazione tra due stati ed indica che un oggetto nel primo stato eseguirà talune azioni ed entrerà in un secondo stato quando si verificheranno eventi specificati e quando verranno soddisfatte delle condizioni specifiche. In un tale cambio di stato, la transizione viene definita come 'generata'. Finché la transizione non genera, si dice che l'oggetto si trova nello stato di 'origine'; dopo la generazione, si definisce stato di 'destinazione'. Una transizione ha diverse proprietà:

Condizione di origine Lo stato influenzato dalla transizione; se un oggetto si trova nello stato di origine, si può generare una transizione in partenza quando l'oggetto riceve l'evento trigger della transizione e se la condizione di guardia, se c'è, viene soddisfatta.
Evento trigger L'evento che rende la transizione eleggibile alla generazione (ammesso che la sua condizione di guardia venga soddisfatta) quando viene ricevuto dall'oggetto nello stato di origine.
Condizione di guardia Un'espressione booleana che viene valutata quando la transizione viene attivata dalla ricezione dell'evento trigger; se l'espressione dà una valutazione di tipo "True", la transizione ha i requisiti per essere generata. Se invece la valutazione è "False", la transizione non viene generata. Se non esistono transizioni che potrebbero essere attivate dallo stesso evento, quest'ultimo viene perso.
Azione Un calcolo atomico eseguibile, che può agire direttamente sull'oggetto che possiede la macchina a stati, e indirettamente su altri oggetti visibili all'oggetto.
Condizione di destinazione Lo stato che è attivo dopo il completamento della transizione.

Una transizione può avere origini multiple, nel qual caso rappresenta una unione di molteplici stati concorrenti nonché obiettivi multipli, per cui rappresenta un bivio verso molteplici stati concorrenti.

Eventi Trigger

Nel contesto della macchina a stati, un evento è un avvenimento di emissione che può attivare una transizione di stato. Gli eventi possono includere eventi di segnale, eventi di chiamata, il passaggio del tempo o un cambio di stato. Un segnale o chiamata possono avere parametri i cui valori sono disponibili alla transizione, incluso le espressioni per le condizioni di guardia e l'azione. E' inoltre possibile avere una transizione senza trigger, rappresentata da una transizione senza evento di attivazione. Queste transizioni, denominate anche transizioni di completamento, sono implicitamente attivate quando il loro stato di origine ha completato il suo compito.

Condizioni di guardia

Una condizione di guardia viene valutata dopo che si è verificato l'evento di attivazione per la transizione. E' possibile avere transizioni multiple provenienti dallo stesso stato di origine e con lo stesso evento trigger, finché le condizioni di guardia non si sovrappongono. Una condizione di guardia viene valutata solo una volta per transizione, al momento in cui si verifica l'evento. L'espressione booleana può far riferimento allo stato dell'oggetto.

Azioni

Un'azione è un calcolo atomico eseguibile, non può essere cioè interrotto da un evento e pertanto viene eseguito fino al suo completamento. Questo è in contrasto con un compito, che può essere interrotto da altri eventi. Le azioni possono comprendere chiamate di operazioni (il proprietario di una macchina a stati nonché di altri oggetti visibili) la creazione o la distruzione di un altro oggetto, o l'invio di un segnale ad un altro oggetto. Nel caso di invio di un segnale, il nome del segnale ha come prefisso la parola chiave 'send'.

Azioni di entrata e di uscita

Le azioni di entrata e di uscita consentono alla stessa azione di essere inviate ogni volta che si entra o si esce da uno stato. Le azioni di entrata e di uscita consentono di effettuare ciò in modo pulito, senza dover esplicitamente mettere le azioni su ogni transizione in entrata ed in uscita. Le azioni di entrata e di uscita non dispongono di argomenti e di condizioni di guardia. Le azioni di entrata a livello superiore di una macchina a stati per un elemento del modello possono avere parametri che rappresentano gli argomenti che la macchina riceve quando viene creato l'elemento.

Transizioni interne

Le transizioni interne consentono la gestione degli eventi all'interno dello stato, senza lasciare lo stato, evitando perciò le entrate di attivazione o le azioni d'uscita. Le transizioni interne possono presentare eventi con parametri e condizioni di guardia, e rappresentare essenzialmente dei gestori di interruzione.

Eventi posticipati

Gli eventi posticipati sono quelli la cui gestione viene ritardata finché non diventa attivo uno stato in cui l'evento non è ritardato. Quando questo stato diventa attivo, l'evento viene attivato e può comportare transizioni come se si fosse appena verificato. L'implementazione degli eventi posticipati richiede la presenza di una coda interna di eventi. Se si verifica un evento ma viene elencato come posticipato, viene messo in coda. Gli eventi vengono tolti da questa coda appena l'oggetto entra in uno stato che non rimanda questi eventi.

Stati secondari

Uno stato semplice è uno che non ha strutture secondarie. Uno stato con stati secondari (stati nidificati) viene definito stato composito. Gli stati secondari possono essere nidificati a qualunque livello. Una macchina a stati nidificata può avere al massimo uno stato iniziale ed uno finale. Gli stati secondari vengono utilizzati per semplificare macchine a stati complesse e flat, mostrando che alcuni stati sono possibili solo all'interno di un particolare contesto (lo stato di chiusura).

Diagramma illustrativo degli stati secondari

Figure 3. Stati secondari

Da una origine al di fuori di uno stato composito di chiusura, una transizione può indirizzarsi allo stato composito oppure allo stato secondario. Se il suo obiettivo è lo stato composito, la macchina a stati nidificata deve comprendere uno stato di inizio a cui il controllo passa dopo aver immesso lo stato composito e dopo aver distribuito la sua eventuale azione d'entrata. Se il suo obiettivo è lo stato nidificato, il controllo passa allo stato nidificato dopo aver distribuito l'azione di immissione dello stato composito (se presente) e poi l'azione di immissione dell'eventuale stato nidificato.

Una transizione che conduce fuori da uno stato composito può avere come sua origine lo stato composito o uno stato secondario. In entrambi i casi, il controllo prima lascia lo stato nidificato (e la sua azione di uscita, se c'è, viene distribuita), poi lascia lo stato composito (e la sua azione di uscita, se c'è, viene distribuita). Una transizione la cui origine è lo stato composito essenzialmente interrompe il compito della macchina a stati nidificata.

Stati cronologici

Se non diversamente specificato, quando una transizione entra in uno stato composito, l'azione della macchina a stati nidificata parte di nuovo dallo stato iniziale (a meno che la transizione non si indirizzi direttamente ad uno stato secondario). Gli stati cronologici consentono alla macchina a stati di reimmettere l'ultimo stato secondario che era attivo prima di lasciare lo stato composito. Un esempio di utilizzo di stato cronologico viene presentato nella Figura 3.

Diagramma illustrativo degli stati cronologici.

Figure 4. Stato cronologico.

Tecniche comuni di modellazione

Le macchine a stati sono usate più comunemente per modellare il comportamento di un oggetto durante il suo periodo di vita. Sono particolarmente necessarie quando gli oggetti hanno un comportamento dipendente dallo stato. Gli oggetti che possono avere le macchine a stati contengono classi, sistemi secondari, casi d'uso e interfacce (per sostenere stati che devono essere soddisfatti da un oggetto che realizza l'interfaccia). Nel caso di sistemi in tempo reale, le macchine a stati vengono utilizzate anche per capsule e protocolli (per sostenere stati che devono essere soddisfatti da un oggetto che realizza il protocollo).

Non tutti gli oggetti richiedono macchine a stati. Se il comportamento di un oggetto è semplice, come quello che semplicemente memorizza o che richiama i dati, il comportamento dell'oggetto non varia con lo stato e la sua macchina di stato è di poco interesse.

La modellazione della durata di un oggetto coinvolge tre aspetti: la specifica degli eventi a cui l'oggetto può rispondere, la risposta a quegli eventi e l'impatto del passato sul comportamento attuale. La modellazione della durata di un oggetto include anche l'ordine con il quale l'oggetto può rispondere in modo significativo agli eventi, iniziando dal momento della creazione dell'oggetto e continuando fino alla sua fine.

Per modellare la durata di un oggetto:

  • Impostare il contesto per una macchina a stati, se è una classe, un caso d'uso o un sistema nel suo intero.
    • Se il contesto è una classe o un caso d'uso, raccogliere le classi limitrofe, incluso le classi principali o quelle raggiungibili da associazioni o dipendenze. Queste classi limitrofe sono obiettivi candidati per le azioni e per le inclusioni nelle condizioni di guardia.
    • Se il contesto è il sistema nella sua interezza, restringere l'attenzione su un comportamento del sistema e poi considerare le durate degli oggetti coinvolti in quell'aspetto. La durata dell'intero sistema è semplicemente troppo grande per poter essere un punto significativo su cui concentrarsi.
  • Stabilire gli stati iniziali e finali per l'oggetto. Se esistono condizioni antecedenti o successive di stati iniziali e finali, definire anche quelli.
  • Determinare gli eventi a cui rispondono gli oggetti. Questi si possono trovare nelle interfacce dell'oggetto. In caso di sistemi in tempo reale, questi si possono trovare anche nei protocolli dell'oggetto.
  • Partendo dallo stato iniziale in direzione di quello finale, la struttura del livello superiore indica che l'oggetto potrebbe essere presente. Collegare questi stati con le transizione attivare dagli eventi appropriati. Continuare aggiungendo queste transizioni.
  • Identificare eventuali azioni di entrata o di uscita.
  • Espandere o semplificare la macchina a stati usando gli stati secondari.
  • Controllare che tutte le transizioni di attivazione degli eventi nella macchina a stati coincidano con gli eventi previsti dalle interfacce realizzate dall'oggetto. Analogamente, controllare che tutti gli eventi previsti dalle interfacce dell'oggetto vengano gestiti dalla macchina a stati. In caso di sistemi in tempo reale, effettuare controlli equivalenti per i protocolli di una capsula. Alla fine, stabilire dove si vogliono ignorare esplicitamente gli eventi (ad es., eventi posticipati).
  • Controllare che tutte le azioni nella macchina a stati siano supportate da relazioni, metodi e operazioni di oggetti di inclusione.
  • Eseguire una traccia lungo tutta la macchina a stati, confrontandola con le sequenze previste di eventi e con le loro risposte. Cercare stati non raggiungibili e stati in cui la macchina si blocca.
  • Se si sta riorganizzando o ristrutturando la macchina a stati, assicurarsi che le semantica non sia cambiata.

Consigli e suggerimenti

  • Quando viene data una scelta, usare la semantica visiva della macchina a stati piuttosto che scrivere codice di transizione dettagli. Ad esempio, non attivare una transizione su svariati segnali, usare il codice del dettaglio per gestire il flusso di controllo che dipende in modo diverso dal segnale. Usare transizioni separate, attivate da segnali separati. Evitare logiche condizionali nel codice di transizione che nasconde il comportamento aggiuntivo.
  • I nomi sono fissati secondo quello che ci si aspetta o quello che sta accadendo durante lo stato. Ricordare che uno stato non è un 'punto in un periodo'; è un periodo durante il quale la macchina a stati attende che accade qualcosa. Ad esempio, 'inattesaDellaFine' è un nome migliore di 'fine'; 'tempiPerAlcuniCompiti' è migliore di 'timeout' (supero tempo). Non assegnare nomi agli stati come se fossero azioni.
  • Assegnare un nome a tutti gli stati e alle transizioni unicamente all'interno di una macchina a stati: ciò renderà più semplice il debug del livello di origine.
  • Usare le variabili di stato (attributi utilizzati per controllare il comportamento) cautamente; non usarle per creare nuovi stati. Quando gli stati sono pochi, con pochi o nessun comportamento dipendente dallo stato, e dove c'è un piccolo o nessun comportamento che potrebbe essere concorrente con o indipendente dall'oggetto che contiene la macchina a stati, possono essere usate le variabili di stato. In presenza di un comportamento complesso, dipendente dallo stato, potenzialmente simultaneo, o se gli eventi da gestire possono originare al di fuori dell'oggetto che contiene la macchina a stati, prendere in considerazione la possibilità di utilizzare la collaborazione di due o più oggetti attivi (possibilmente definiti come composizione). Nei sistemi in tempo reale, dipendenti dallo stato complesso, il comportamento simultaneo deve essere modellato utilizzando una capsula contenente capsule secondarie.
  • Con più di 5 ± 2 stati in un singolo diagramma, considerare l'utilizzo di stati secondari. Si applica il senso comune: dieci stati in un pattern assolutamente regolare possono andar bene, ma due stati con quaranta transizioni tra di loro hanno ovviamente bisogno di essere riconsiderate. Assicurarsi che la macchina a stati sia comprensibile.
  • Assegnare il nome alle transizioni per quello che attivano e/o per quello che accade durante la transizione. Scegliere i nomi che aumentano la comprensione.
  • Quando si osserva il vertice di una scelta, bisognerebbe chiedersi se è possibile delegare la responsabilità di quella scelta ad un altro componente, come quella che viene presentata all'oggetto come insieme distinto di segnali sui quali agire (ad es., invece di una scelta su msg->data > x), far prendere la decisione al mittente o a qualche altro attore intermediario ed inviare il segnale con la decisione esplicita nel nome del segnale (ad es., usare segnali con il nome isFull e isEmpty invece di avere un valore di segnale cui è stato assegnato un nome e controllare la data del messaggio).
  • Assegnare un nome alle domande che hanno avuto una risposta al vertice della scelta descrittivamente, ad es. 'esisteAncoraLaVita' o 'tempoDiProtestare'.
  • All'interno di ciascun oggetto, provare a conservare univoci i nomi del vertice della scelta (per lo stesso motivo per il quale si conservano univoci i nomi delle transizioni).
  • Ci sono troppi frammenti di lunghe code o transizioni? Dovrebbero invece essere usate le funzioni, e i frammenti di codice comune sono catturati come funzioni? Una transizione dovrebbe leggere come pseudo-codice ad alto livello, e dovrebbe aderire allo stesso o anche a più regole stringenti di lunghezza come le funzioni C++. Ad esempio, una transizione con più di 25 righe di codice viene considerata eccessivamente lunga.
  • Alle funzioni bisogna assegnare un nome in base a quello che fanno.
  • Porre particolare attenzione alle azioni di entrata e di uscita: è molto semplice apportare modifiche e dimenticare di cambiare le azioni di entrata e di uscita.
  • Le azioni di uscita possono essere usate per fornire funzioni di sicurezza, ad es. l'azione di uscita dallo stato 'heaterOn' disattiva la stufa (heater), dove le azioni vengono usate per rinforzare un'asserzione.
  • Generalmente gli stati secondari devono contenere uno o più stati, a meno che la macchina a stati non sia astratta e verrà ridefinita da classi secondarie dell'elemento di inclusione.
  • I punti di scelta devono essere usati al posto della logica condizionale nelle azioni o nelle transizioni. Il punto di scelta è facilmente individuabile, laddove la logica condizionale nel codice viene nascosto alla vista ed è semplice da lasciarsi sfuggire.
  • Evitare condizioni di guardia
    • Se l'evento attiva svariate transizioni, non c'è controllo su quale condizione di guardia venga valutata per prima. Come risultato, i risultati possono essere imprevedibili.
    • Più di un condizione di guardia potrebbe essere 'true', ma può essere seguita solo una transizione. Il percorso scelto può essere imprevedibile.
    • Le condizioni di guardia sono non-visive; è più difficile 'vedere' la loro presenza.
  • Evitare macchine a stati somiglianti a diagrammi di flusso.
    • Ciò può indicare un tentativo di modellare un'astrazione che non è davvero lì, come:
      • uso di una classe attiva per modellare il comportamento che meglio si adatta ad una classe di dati o passiva.
      • modellazione di una classe di dati utilizzando una classe di dati ed una classe attiva accoppiati molto saldamente (ad es., la classe di dati è stata utilizzata per passare le informazioni sul tipo ma la classe attiva contiene la maggior parte dei dati che deve essere associata alla classe di dati).
    • Questo uso sbagliato delle macchine di stato può essere riconosciuto dai seguenti sintomi:
      • messaggi spediti a 'self', principalmente solo per riutilizzare il codice
      • pochi stati, con molti punti di scelta
      • in alcuni casi, una macchina a stati senza cicli. Queste macchine a stati sono valide in applicazioni di controllo del processo o quando si prova a controllare una sequenza di eventi; la loro presenza durante l'analisi di solito rappresenta la degenerazione della macchina a stati in un diagramma di flusso.
    • Quando il problema viene identificato:
      • Considerare la possibilità di dividere la classe attiva in unità più piccole con più responsabilità distinte.
      • Spostare più comportamenti in una classe di dati associata al problema della classe attiva.
      • Spostare più comportamenti in funzioni di classe attiva.
      • Rendere più significativi i segnali invece di confidare sui dati.

Progettazione con macchine astratte a stati

Una macchina a stati astratta è una astratto che ha bisogno di maggiori dettagli prima di poter essere utilizzata per scopi pratici. Le macchine a stati astratte possono essere utilizzate per definire un comportamenti generico e riutilizzabile che viene in seguito perfezionato negli elementi del modello successivo.

Diagramma descritto nella figura.

Figure 5. Una macchina a stati astratta

Esaminare la macchina a stati astratta nella Figura 5. La semplice macchina a stati rappresentata è rappresentativa del massimo livello astratto di comportamento (l'automa di "controllo") di molti differenti tipi di elementi in sistemi guidati dall'evento. Sebbene tutti condividano il modulo di alto livello, i differenti tipi di elemento possono avere comportamenti dettagliati ampiamente diversi nello stato di Esecuzione a secondo del loro scopo. Pertanto, questa macchina a stati potrebbe essere più ampiamente definita in una certa classe astratta che serve come classe root per le diverse classi attive specializzate.

Si possono dunque definire due differenti perfezionamenti di questa macchina a stati astratta utilizzando l'ereditarietà. Questi due perfezionamenti, R1 e R2, sono illustrati nella Figura 6. Per chiarezza, gli elementi ereditati dalla classe principale sono disegnati in grigio.

Diagramma descritto nella figura.

Figure 6. Due perfezionamenti della macchina a stati nella Figura 5.

I due perfezionamenti differiscono chiaramente nel modo in cui scompongono lo stato di Esecuzione ed anche nel modo in cui estendono la transizione originale di "inizio". Queste scelte possono ovviamente essere fatte solo una volta che si conosce il perfezionamento e perciò, non è stato possibile farle con una transizione singola completa nella classe astratta.

Stati a catena

La capacità di "continuare" entrambe le transizioni in entrata ed in uscita è fondamentale per il tipo di perfezionamento precedentemente descritto. Può apparire che i punti di ingresso e gli stati finali, uniti alle transizioni continuate siano sufficienti a fornire queste semantiche. Sfortunatamente, ciò non è sufficiente dove esistono transizione multiple differenti che hanno bisogno di essere estese.

Quello che viene richiesto per un pattern astratto di comportamento è un modo di concatenazione di due o più segmenti di transizione che vengono tutti eseguiti nell'ambito di un singolo passo di esecuzione al completamento (run-to-completion). Ciò vuol dire che le transizioni che entrano in uno stato gerarchico vengono divise nella parte in entrata che effettivamente termina sul confine dello stato e nell'estensione che continua all'interno dello stato. In modo analogo, le transizioni in uscita derivanti da uno stato nidificato gerarchicamente vengono segmentate in una parte che termina nel confine dello stato di inclusione ed una parte che continua dal limite dello stato fino allo stato di destinazione. Questo risultato può essere raggiunto in UML con l'introduzione del concetto di stato a catena. Questo è modellato da uno stereotipo (<<chainState>>) del concetto di stato UML. Si tratta di uno stato il cui unico scopo è quello di "incatenare" ulteriori transizioni automatiche (disattive) in una transizione di immissione. Uno stato di catena non ha una struttura interna, non ha compiti interni, né azione di uscita. Non ha neanche transizioni attivate dagli eventi. Può avere un numero qualsiasi di transizioni di immissione. Può avere una transizione senza evento di attivazione; questa transizione si alimenta automaticamente quando una transizione di immissione attiva lo stato. Lo scopo di tale ambito è quello di incatenare una transizione di immissione in una transizione di output separata. Tra le transizioni di immissione e quelle di output incatenate, una si collega ad un altro stato all'interno dello stato che li contiene e l'altra si collega ad un altro stato al di fuori dello stato che li contiene. Lo scopo per il quale è stato introdotto uno stato di catena è stato quello di separare la specifica interna dello stato di contenimento dal suo ambiente esterno. è una questione di incapsulamento.

In effetti, uno stato a catena rappresenta uno stato di "attraversamento" che serve a incatenare una transizione ad una transizione di continuazione specifica. Se non viene definita una transizione di continuazione, la transizione termina in uno stato a catena e si devono eventualmente generare transizioni su uno stato di chiusura per far circolare le cose.

Il segmento di esempio della macchina a stati nella Figura 7 illustra gli stati a catena e le loro notazioni. Gli stati a catena sono rappresentati in un diagramma di macchina a stati attraverso cerchi bianchi posizionati all'interno dello stato gerarchico appropriato (questa notazione è simile agli stati di inizio e di fine). I cerchi sono icone dello stereotipo dello stato a catena e sono di solito disegnate accanto al limite, per praticità. (Infatti, una variazione di notazione dovrebbe essere disegnata sul bordo dello stato di inclusione).

Diagramma descritto nel testo di accompagnamento.

Figure 7. Stati a catena e transizioni incatenate.

La transizione incatenata di questo esempio consiste in tre segmenti di transizione incatenati e1/a11-/a12-/a13. Quando viene ricevuto il canale e1, viene presa la transizione etichettata e1/a11, la sua azione a11 viene eseguita e poi viene raggiunto lo stato c1. Dopo di ciò, viene presa la transizione di continuazione tra c1 e c2 e, alla fine, poiché c2 è anche uno stato a catena, la transizione da c2 a S21. Se gli stati, insieme a questi percorsi, hanno tutti le azioni di entrata e di uscita, la sequenza attuale dell'esecuzione dell'azione procede nel modo seguente:

  • azione d'uscita di S11
  • azione a11
  • azione d'uscita di S1
  • azione a12
  • azione di entrata di S2
  • azione a13
  • azione di entrata di S21

Tutto ciò viene eseguito nell'ambito di un passo singolo completo.

Questo dovrebbe essere confrontato con le semantiche di esecuzione dell'azione della transizione diretta e2/a2, che sono:

  • azione d'uscita di S11
  • azione d'uscita di S1
  • azione a2
  • azione di entrata per stato S2
  • azione di entrata per stato S21