Az UML-állapotgép más néven UML-állapotdiagram, a véges automata matematikai koncepciójának kiterjesztése a számítástechnikai alkalmazásokban, ahogyan azt az Unified Modeling Language (UML) jelölése fejezi ki.

A mögöttes koncepciók arra irányulnak, hogy megszervezzék egy eszköz, számítógépes program vagy más (gyakran technikai) folyamat működését úgy, hogy egy entitás vagy annak minden alentitása mindig pontosan egy lehetséges állapotban legyen, és hogy ezek között az állapotok között jól meghatározott feltételes átmenetek legyenek.

Az UML-állapotgép a Harel-állapotdiagramok objektumalapú változata, amelyet az UML adaptált és kibővített."Statecharts: A Visual Formalism for Complex Systems"D. Drusinsky, Modelling and verification using UML statecharts, Elsevier, 2006 Az UML-állapotgépek célja a hagyományos véges állapotgépek fő korlátainak leküzdése, miközben megőrzik azok fő előnyeit. Az UML-állapotdiagramok bevezetik a hierarchikusan beágyazott állapotok és az ortogonális régiók új fogalmait, miközben kiterjesztik az akciók fogalmát. Az UML-állapotgépek a Mealy gépek és a Moore gépek jellemzőit is magukban hordozzák. Támogatják azokat az akciókat, amelyek mind a rendszer állapotától, mind a kiváltó eseménytől függenek, mint a Mealy gépeknél, valamint a belépési és kilépési akciókat, amelyek állapotokhoz, nem pedig átmenetekhez kapcsolódnak, mint a Moore gépeknél.

Az "UML-állapotgép" kifejezés kétféle állapotgépre utalhat: viselkedési, illetve protokoll-állapotgépekre. A viselkedési állapotgépek egyedi entitások (pl. osztálypéldányok), egy alrendszer, egy csomag vagy akár egy teljes rendszer viselkedésének modellezésére használhatók. A protokoll állapotgépeket a használati protokollok kifejezésére használják, és osztályozók, interfészek és portok legális használati forgatókönyveinek meghatározására alkalmazhatók.

Alapvető állapotgép fogalmak Sok szoftverrendszer eseményvezérelt, ami azt jelenti, hogy folyamatosan várnak valamilyen külső vagy belső esemény bekövetkezésére, mint például egy egérkattintás, egy gombnyomás, egy időjel vagy egy adatcsomag érkezése. Az esemény felismerése után az ilyen rendszerek azáltal reagálnak, hogy elvégzik a megfelelő számítást, amely magában foglalhatja a hardver kezelését vagy olyan „puha” események generálását, amelyek más belső szoftverkomponenseket indítanak el. (Ezért hívják az eseményvezérelt rendszereket alternatívan reaktív rendszereknek is.) Miután az eseménykezelés befejeződött, a rendszer visszatér a következő esemény várakozásához.

Az eseményre adott válasz általában az esemény típusától és a rendszer belső állapotától függ, és magában foglalhat egy állapotváltozást, amely állapotátmenetet eredményez. Az események, állapotok és az ezek között zajló állapotátmenetek mintája absztrahálható és véges állapotgépként (FSM) ábrázolható.

Az FSM koncepciója fontos az eseményvezérelt programozásban, mert az eseménykezelést kifejezetten az esemény típusától és a rendszer állapotától teszi függővé. Ha helyesen használják, egy állapotgép drasztikusan csökkentheti a kódon keresztüli végrehajtási útvonalak számát, egyszerűsítheti az egyes elágazási pontokon tesztelt feltételeket, és megkönnyítheti a különböző végrehajtási módok közötti váltást. Ezzel szemben, ha az eseményvezérelt programozást egy mögöttes FSM modell nélkül alkalmazzák, a programozók hajlamosak hibára hajlamos, nehezen bővíthető és túlzottan összetett alkalmazáskódot előállítani.Samek, Miro (April 2003). "Who Moved My State?". C/C++ Users Journal, The Embedded Angle column.

Alapvető UML-állapotdiagramok Az UML megőrzi a hagyományos állapotdiagramok általános formáját. Az UML-állapotdiagramok irányított gráfok, amelyekben a csomópontok az állapotokat, a kapcsolók pedig az állapotátmeneteket jelölik. Például, az 1. ábra egy UML-állapotdiagramot mutat be, amely a számítógép billentyűzetének állapotgépéhez tartozik. Az UML-ben az állapotokat lekerekített téglalapokként ábrázolják, amelyek állapotnevekkel vannak feliratozva. Az átmeneteket nyilakként ábrázolják, amelyeket a kiváltó események címkéznek, amelyeket opcionálisan a végrehajtott akciók listája követ. A kezdeti átmenet a szilárd körből indul ki, és meghatározza az alapértelmezett állapotot, amikor a rendszer először elindul. Minden állapotdiagramnak rendelkeznie kell ilyen átmenettel, amelyet nem kell címkézni, mivel nem esemény váltja ki. A kezdeti átmenethez akciók is társíthatók.

középre|bélyegkép| 1. ábra: A számítógép billentyűzetének állapotgépét ábrázoló UML-állapotdiagram

Események Az esemény olyan esemény, amely hatással van a rendszerre. Szigorúan véve, az UML specifikációban az esemény kifejezés az előfordulás típusára utal, nem pedig annak bármely konkrét előfordulására. Például a Keystroke egy esemény a billentyűzet számára, de egy gomb minden egyes lenyomása nem esemény, hanem a Keystroke esemény konkrét példánya. Egy másik érdekes esemény a billentyűzet számára a bekapcsolás lehet, de ha holnap 10:05:36-kor bekapcsoljuk, az csak egy példa a bekapcsolási eseményre.

Egy eseményhez kapcsolódhatnak paraméterek, amelyek lehetővé teszik, hogy az eseménypéldány ne csak egy érdekes esemény bekövetkezését közvetítse, hanem mennyiségi információkat is az eseményről. Például a számítógép billentyűzetén egy billentyű lenyomásával generált Keystroke eseményhez kapcsolódó paraméterek tartoznak, amelyek közvetítik a karakter szkennelési kódját, valamint a Shift, Ctrl és Alt billentyűk állapotát.

Egy eseménypéldány túllépi azt a pillanatnyi eseményt, amely létrehozta, és közvetítheti ezt az eseményt egy vagy több állapotgép számára. Miután létrejött, az eseménypéldány egy feldolgozási életcikluson megy keresztül, amely akár három szakaszból is állhat. Először, az eseménypéldányt fogadják, amikor azt elfogadják és várakozik a feldolgozásra (például elhelyezik az eseménysorban). Később az eseménypéldányt továbbítják az állapotgéphez, ekkor válik az aktuális eseménnyé. Végül, amikor az állapotgép befejezi az eseménypéldány feldolgozását, azt elfogyasztják. Egy elfogyasztott eseménypéldány már nem áll rendelkezésre a feldolgozásra.

Állapotok Minden állapotgépnek van egy állapota, amely meghatározza az állapotgép reakcióját az eseményekre. Például, amikor lenyom egy billentyűt a billentyűzeten, a generált karakterkód lehet nagybetűs vagy kisbetűs, attól függően, hogy a Caps Lock aktív-e. Ezért a billentyűzet viselkedése két állapotra osztható: "alapértelmezett" állapot és "caps_locked" állapot. (A legtöbb billentyűzeten van egy LED, amely jelzi, hogy a billentyűzet "caps_locked" állapotban van.) A billentyűzet viselkedése csak a történetének bizonyos aspektusaitól függ, nevezetesen attól, hogy megnyomták-e a Caps Lock billentyűt, de például nem attól, hogy hány és pontosan melyik más billentyűket nyomták le korábban. Egy állapot képes absztrahálni minden lehetséges (de lényegtelen) eseménysorozatot, és csak a relevánsakat rögzíteni.

A szoftverállapotgépek (és különösen a klasszikus FSM-ek) kontextusában az állapot kifejezést gyakran egyetlen állapotváltozóként értelmezik, amely csak korlátozott számú előre meghatározott értéket vehet fel (például két értéket a billentyűzet esetében, vagy általánosabban - valamilyen enum típusú változót sok programozási nyelvben). Az állapotváltozó (és a klasszikus FSM modell) elképzelése az, hogy az állapotváltozó értéke teljes mértékben meghatározza a rendszer aktuális állapotát bármely adott időpontban. Az állapot koncepciója leegyszerűsíti a végrehajtási kontextus azonosításának problémáját a kódban azáltal, hogy csak az állapotváltozót kell vizsgálni sok változó helyett, így kiküszöbölve rengeteg feltételes logikát.

Kiterjesztett állapotok A gyakorlatban azonban az állapotgép teljes állapotának egyetlen állapotváltozóként való értelmezése gyorsan impraktikussá válik minden egyszerűnél bonyolultabb állapotgép esetében. Valójában még ha csak egyetlen 32 bites egész számot használunk is az állapotgép állapotának leírására, ez több mint 4 milliárd különböző állapotot eredményezhet, ami korai állapotrobbanáshoz vezet. Ez az értelmezés nem praktikus, így az UML-állapotgépekben az állapotgép teljes állapota általában két részre oszlik: (a) egy enumerált állapotváltozóra és (b) minden más változóra, amelyeket kiterjesztett állapotnak nevezünk. Másképpen fogalmazva, az enumerált állapotváltozót a teljes állapot minőségi aspektusaként, míg a kiterjesztett állapotot a mennyiségi aspektusokként értelmezhetjük. Ebben az értelmezésben a változó megváltozása nem mindig jelenti a rendszer viselkedésének minőségi aspektusainak változását, és ezért nem vezet állapotváltozáshoz.

Az állapotgépeket, amelyeket kiterjesztett állapotváltozókkal egészítettek ki, kiterjesztett állapotgépeknek nevezik, és az UML-állapotgépek ebbe a kategóriába tartoznak. A kiterjesztett állapotgépek az alapul szolgáló formalizmust sokkal összetettebb problémákra tudják alkalmazni, mint amit a kiterjesztett állapotváltozók nélkül praktikus lenne. Például, ha egy korlátot kell megvalósítanunk az FSM-ben (például a billentyűleütések számának korlátozása 1000-re), akkor kiterjesztett állapot nélkül 1000 állapotot kellene létrehoznunk és feldolgoznunk, ami nem praktikus; azonban egy kiterjesztett állapotgéppel bevezethetünk egy key_count változót, amelyet 1000-re inicializálunk és minden egyes billentyűleütéssel csökkentünk, anélkül, hogy az állapotváltozó megváltozna.

középre|bélyegkép| 2. ábra: Az "olcsó billentyűzet" kiterjesztett állapotú gépe kiterjesztett állapotváltozóval, a key_count változóval és különböző védelmi feltételekkel

A 2. ábrán látható állapotdiagram egy kiterjesztett állapotgép példája, amelyben a rendszer teljes állapota (amit kiterjesztett állapotnak nevezünk) egy minőségi aspektus—a állapotváltozó—és a mennyiségi aspektusok—a kiterjesztett állapotváltozók kombinációja.

A kiterjesztett állapotgépek nyilvánvaló előnye a rugalmasság. Például a key_count által meghatározott korlát 1000-ről 10000 leütésre való módosítása egyáltalán nem bonyolítaná a kiterjesztett állapotgépet. Az egyetlen szükséges módosítás a key_count kiterjesztett állapotváltozó inicializálási értékének megváltoztatása lenne az inicializálás során.

A kiterjesztett állapotú gépek e rugalmasságának azonban ára van a kiterjesztett állapot "minőségi" és "mennyiségi" aspektusa közötti összetett kapcsolat miatt. A csatolás az átmenetekhez csatolt védőfeltételeken keresztül történik, amint az a 2. ábrán látható.

Őrfeltételek Az őrfeltételek (vagy egyszerűen őrök) logikai kifejezések, amelyeket dinamikusan értékelnek ki a kiterjesztett állapotváltozók és az eseményparaméterek értékei alapján. Az őrfeltételek befolyásolják az állapotgép viselkedését azáltal, hogy akciókat vagy átmeneteket csak akkor engedélyeznek, ha értékük TRUE, és letiltják őket, ha értékük FALSE. Az UML-jelölésmódban az őrfeltételeket szögletes zárójelek között tüntetik fel (például [key_count == 0] a 2. ábrán).

Az őrfeltételek szükségessége azonnali következménye annak, hogy memória kiterjesztett állapotváltozókat adunk az állapotgép formalizmusához. Mértékkel használva a kiterjesztett állapotváltozók és az őrfeltételek egy erőteljes mechanizmust alkotnak, amely egyszerűsítheti a tervezést. Másrészt, a kiterjesztett állapotok és őrfeltételek könnyen túlzottan használhatók.

Műveletek és átmenetek Amikor egy eseménypéldány továbbításra kerül, az állapotgép akciók végrehajtásával reagál, mint például egy változó megváltoztatása, I/O műveletek végrehajtása, egy függvény meghívása, egy másik eseménypéldány generálása, vagy egy másik állapotba való átlépés. Az aktuális eseményhez kapcsolódó bármilyen paraméterérték elérhető az összes olyan akció számára, amelyet közvetlenül az az esemény vált ki.