Hogy specifikálj? I. állapotgépek

Nagyon sokan gyenge specifikációkat adnak. Tudom, hogy manapság agilitás van (bear with me for a moment), de még mindig fontos ismeret, mitől lesz valami “specifikus”.

Ahhoz, hogy megértsük, mitől “jó” egy programozónak egy specifikáció (azaz mitől erős), és hogyan tudjuk ezt elérni, szükségünk van egy kis elméletre.

Az informatika alapjai: az állapotgép

Tanulni azt tanulod meg biztosan, amit folyamatosan számonkérnek. A BME informatika képzésének első két évében ez az állapotgép volt: minden félévben legalább egy tárgyból előkerült, amellett, hogy komplett tárgyak épültek köré.

Az állapotgép alapvetően két dologból áll:

  • Állapotokból, amiben egy rendszer (komponens) tartózkodik
  • Eseményekből, amikkel egyik állapotból megyünk a másikba

Nézzünk egy egyszerű állapotgépet:

alap.png

Ezt simán bonyolíthatjuk így:

pluszegy.png

De akár így is:

komplett.png

Minden specifikációnak az állapotgép az alapja. (vagy rokonai, a veremautomaták, a Petri-hálók vagy a Turing-gépek, amikbe most ne menjünk bele, röviden: az ún. absztrakt gépek)

Mitől specifikált egy állapotgép?

Egy állapotgép akkor specifikus, ha jól definiált és determinisztikus.

Magyarra fordítva: a specifikációd akkor jó, ha:

  • Minden állapotban az összes elvégezhető eseményről elmondtad, mi történik (akár azzal, hogy explicit kijelented, nem történik semmi)
  • Egy adott állapotban egy adott esemény hatására pontosan egy dolog történhet

A gyakorlatban fontos UX szempont a bejárhatóság: minden állapotból elérhető-e minden állapot. Nyilván

  • vannak explicit helyzetek, amikor ezt nem szeretnénk (blokkolás),

más problémákra elég az,

  • ha a visszatérés mindig adott (vissza gomb),
  • vagy a kezdőállapotba bármikor el lehet jutni (főoldal link)

de a legtöbbször szeretnénk egyéb, közvetlen, esemény-specifikus megoldásokat is.

Fontos még kijelölni legalább egy speciális állapotot is: ez a kezdőállapot.

Mi köze az állapotgépeknek a UX-hez?

Amikor interaktív prototípust készítesz pl. Marvelben vagy Invisionben, akkor valójában állapotgépet építesz, ahol az állapotok az egyes képernyőid.

Bár a fejlesztőknek is nagyon hasznos, ha ki tudják próbálni az alkalmazást, a tényleges munkájuk elvégzéséhez az is kell, hogy az állapotgépet “felülnézeti”, kiterített ábrákon megkapják, nem csak bejárható modellként.

Az állapot és a kulcsképernyő (key screen) UX-ben sokszor a gyakorlatban felcserélhető fogalmak.

brownflow.png

Képernyős állapotgép (wireflow) Dan Brown Communicating Design. c. könyvéből. Used under CC license.

Mi köze az állapotgépeknek a use case-ekhez?

Egy use case-nek mindig van egy főforgatókönyve, amely egy állapotgép fő bejárási útvonala – ezt hol eseményekkel, hol állapotokkal specifikálják.

A mellékforgatókönyvek további (másodlagos) eseményeket és állapotokat definiálnak.

A gyakorlatban az állapotgépen a főforgatókönyvhöz tartozó eseményeket kiemeljük vastagon, és igyekszünk úgy rendezni az állapotokat, hogy azok egy tengelyt (pl. a felső sort) képviseljék.

allapotgep.png

Egy tényleges regisztráció állapotgépe, kijelölt főforgatókönyvvel és mellékforgatókönyvekkel

Use case-ek esetén a kezdőállapot mellé kijelölünk egy vagy több végállapotot is.

Hogy passzinthatóak be az agilis világba?

Az, hogy egy user story hány eseményből, állapotból áll, csak a Jóisten tudja megmondani, nagyon cégfüggő. Sok helyen nem helyben felrajzolt drótvázak, hanem részletes tervek alapján próbálnak meg becsülni.

Az állapotok és átmenetek (kulcsképernyők és események) száma erősen befolyásolja a rendszer méretét, így implementációs költségét is. Agilisan teljes (de kis méretű) állapotgépeket implementálnak, vagy ebből “csípnek ki” a fejlesztők részeket.

Hogy ábrázoljuk őket a gyakorlatban?

Az UML rengeteg állapotgép-ábrázolást megkülönböztet (ilyen a szekvenciadiagram, a eseménydiagram, az állapotdiagramm stb), mi ezek közül csak az állapotdiagrammal fogunk foglalkozni.

A gyakorlatban kétféle nézetről beszélünk:

  • Felülnézetiről
  • Részletnézetről

Felülnézetben egy adott use case köré bemutatjuk a lehetséges állapotokat.

A programozóknak ez egy jó áttekintés, de valójában nem ez a fő kérdésük: ők jellemzőként képernyőnként (állapotonként) implementálnak.

Így a nagy kérdés, hogy egy adott képernyőn

  • milyen események történhetnek,
  • ezek milyen hatással járnak és
  • főleg milyen képernyőkre visznek – különös tekintettel a hibaállapotokra.

Erre való az állapotonkénti (képernyőkénti) eseménylajstrom, amikről majd egy más cikkben lesz szó.

Hogyan kezeljük a hibákat és kivételeket?

Nem feltétlenül egészséges ha a fejlesztőre bízzuk a hibakezelést. Biztos találkoztunk már “Általános hiba! Próbálja újra” jellegű hibaüzenetekkel.

Mobilfejlesztés esetén ráadásul fel kell készülnünk egy csomó állapotra:

  • A felhasználó kikapcsolta a wifit
  • Nincs GPS, vagy van GPS csak nincs jel
  • Az előbb még volt net, most nincs

Ezek szintén állapotok és események – ja, hogy mi is az az esemény?

Esemény bármi, amely az állapotgép életében időben történhet és változást idéz elő a gép állapotában. Tipikusan a felhasználói interakció lesz ez, pl. megnyom egy gombot, kiválaszt valamit, fölémegy egérrel, stb. 

Az absztrakt állapotgépen rendszerint nem műveletszinten (pl. OnClick Submit Form) , hanem elvi szinten írjuk fel (Form submited) az eseményeket.

A hibaképernyőt egyszerűen meg kell rajzolni: ez is egy állapot, amibe

  • bele lehet menni,
  • ki kell tudni belőle jönni,
  • máshogy néz ki mint a többi

stb.

Hogyan kezeljük az eseményeket?

Kétféle esemény van:

  • Felhasználói esemény (pl. valaki valamire kattintott)
  • Külső esemény (pl. elment a net)

Külső eseményt kétféleképpen kezelünk:

  • Mint esemény (pl. oldal betöltése)
  • Mint feltétel

Ez már persze bonyolultabb dolog, de: az állapotgépeinket felszerelhetjük „őrzőkkel”, feltételekkel, amelyek szabályozzák az egyes állapotokba lépést. Ez elsősorban egy kényelmi funkció. 

Ilyenkor mindig fel kell tennünk magunknak a kérdést, mi történik, ha az esemény bekövetkezik, de a feltétel nem teljesül?

Ebből is látszik, a feltételek kényelmi, ábrázolástechnikai dolgok, valójában a feltétel csak egy shorthand két különálló eseményre vagy állapotra.

Az állapotgép ellenőrzése

Most érkeztünk el a legfontosabb részhez: nézd át, amit csináltál.

Négy dolgot kell ellenőrizned:

  1. Minden, az egyes állapotban feltűntetett eseményet definiáltad és tudjuk, hogy hova megy?
  2. Minden állapot × esemény páros definiált vagy explicit kihagyott?
  3. Minden állapotba el lehet jutni a kezdőállapotból?
  4. Minden állapotból el lehet jutni egy végállapotba?

Az első a legegyszerűbb: megnézed a drótvázakat, összeszámolod a linkeket és a gombokat, ha mindegyikre megírtad, mi történik, már boldogabb fejlesztőid lesznek.

A második is egyszerű: fogsz egy excel táblát, és összeírod: sorokban az állapotok, oszloponként a események. Nem minden esemény definiált minden állapotra, ezeket explicit satírozd ki.

allapotatmeneti.png

A fenti ábra állapotátmenetije – szürkével jelölve az explicit nem várt eseményeket, fehérrel a (némileg egyszerűsített) modell hiányosságait

A harmadikra és a negyedikre kell a térkép: egyszerűen egy ceruzát végig kell tudnod tolni bárhova. A néhai Bach tanár úr (Isten nyugosztalja) ötforintos tesztnek hívta: ha a vonalak mentén értelmesen végig lehet tolni egy ötforintost, rendben van.

Értesülnél a cikkekről?

Kötelező megadni.

1 Comment

  1. pf

    Hiányolom a posztból azt, hogy milyen konkrét eszközzel lehet ezt értelmesen csinálni: magyarul van-e olyan drótvázmodellező, amelyik az oldalakból (wireframe) megcsinálja a wireflow-t? Oldaltérképet kapunk néhánytól (pl. UXPin, Moqups…), de az nem elég.

Comments are closed