Poglavlje 7: Dinamički model – sekvence i stanja

Priča za početak. Godine 1936. mladi engleski matematičar Alan Turing objavio je rad „On Computable Numbers” („O izračunljivim brojevima”). Računara tada nije bilo. Turing je zamislio jednostavnu mašinu: beskonačnu traku podijeljenu na polja, glavu koja čita i piše po jedan znak, i mali skup stanja u kojima mašina može biti. U svakom koraku mašina gleda samo dvije stvari: u kojem je stanju i koji znak čita. Na osnovu toga upiše znak, pomjeri glavu i pređe u novo stanje. Turing je pokazao da takva mašina, sa samo nekoliko pravila prelaza, može izračunati sve što se uopšte može izračunati. Ideja da se ponašanje opiše kao stanja i prelazi između njih od tada je svuda: u semaforu, automatu za kafu, liftu, protokolu interneta, igrici i, naravno, u narudžbi hrane. Kad DeliveryApp kaže da se narudžba na putu ne može otkazati, on se ponaša kao mala Turingova mašina: gleda u kojem je stanju i šta se desilo, i odlučuje kuda dalje.

U poglavlju 6 nacrtali smo šta DeliveryApp zna: klase, atribute i veze. To je fotografija sistema. Ovo poglavlje pravi film: kako se objekti ponašaju kroz vrijeme. Prvo crtamo sekvencijalni dijagram, koji pokazuje ko kome šalje koju poruku i kojim redom, dok kupac naručuje N-1001. Zatim crtamo dijagram stanja narudžbe: sedam stanja i prelaze između njih, iz pravila PP-6. Na kraju provjeravamo da se svi modeli iz poglavlja 4 do 7 slažu jedan s drugim. Na praktičnoj nastavi oba dijagrama crtamo u Mermaidu, a mašinu stanja pišemo i provjeravamo u Pythonu.

Literatura. Osnovna literatura predmeta:

  1. B. Popović, K. Kuk: Informacioni sistemi, Kriminalističko-policijski univerzitet, Beograd, 2017.
  2. J. S. Valacich, J. F. George: Modern Systems Analysis and Design, 9th ed., Pearson, 2020.
  3. L. Jelenković: Sustavi za rad u stvarnom vremenu – skripta, FER, Zagreb, 2015.
  4. D. Milićev: Programiranje u realnom vremenu – skripta, Beograd, 2002.
  5. V. Kovačević, M. Popović: Sistemska programska podrška u realnom vremenu 1, FTN, Novi Sad, 2013.

Riječi ovog poglavlja.

  • Dinamički model – model koji pokazuje kako se sistem ponaša kroz vrijeme (za razliku od strukturnog, koji pokazuje od čega je).
  • Sekvencijalni dijagram – UML dijagram poruka koje učesnici razmjenjuju, poredanih odozgo prema dolje po vremenu.
  • Linija života (lifeline) – uspravna isprekidana linija ispod učesnika; vrijeme teče niz nju.
  • Sinhrona poruka – poruka nakon koje pošiljalac čeka odgovor (puna strelica s punim vrhom).
  • Asinhrona poruka – poruka nakon koje pošiljalac ne čeka, nego nastavlja (strelica s otvorenim vrhom).
  • Kombinovani fragment – okvir u sekvencijalnom dijagramu za izbor (alt), opciju (opt) ili ponavljanje (loop).
  • Stanje – situacija u kojoj objekat čeka ili nešto radi, dok se ne desi događaj (npr. NA_PUTU).
  • Prelaz – prelazak iz jednog stanja u drugo kao odgovor na događaj.
  • Događaj – nešto što se desi i može izazvati prelaz (restoran prihvati, prođe 5 minuta).
  • Uslov (guard) – logički izraz u uglastim zagradama koji mora biti tačan da bi se prelaz desio.
  • Akcija – kratak posao koji se obavi pri prelazu (vrati novac, obavijesti kupca).
  • Završno stanje – stanje iz kojeg više nema prelaza (ISPORUČENA, ODBIJENA, OTKAZANA).
  • Tabela prelaza – tabela koja za svako stanje i svaki događaj kaže u koje se stanje prelazi.
  • Usklađenost modela – osobina da različiti dijagrami istog sistema ne govore jedan protiv drugog.

Ciljevi poglavlja. Nakon poglavlja možete: objasniti razliku između strukturnog i dinamičkog modela; nacrtati sekvencijalni dijagram s učesnicima, linijama života, sinhronim i povratnim porukama; pročitati sekvencu naručivanja N-1001 korak po korak; koristiti fragmente alt, opt i loop; objasniti šta su stanje, prelaz, događaj, uslov i akcija; nacrtati dijagram stanja narudžbe sa sedam stanja i sedam prelaza; napraviti tabelu prelaza i izračunati koliko je parova nedozvoljeno; napisati mašinu stanja u Pythonu i provjeriti pravilo PP-6; provjeriti usklađenost slučajeva korištenja, klasa, sekvenci i stanja; izabrati pravi dijagram za dato pitanje.

Plan poglavlja – Sedmica 7: tri časa teorije i tri časa praktične nastave

Čas Sadržaj Na času
Teorija 1 7.1–7.3 Sekvencijalni dijagram, sekvenca N-1001, fragmenti Šest učesnika, šesnaest poruka
Teorija 2 7.4–7.6 Stanja, prelazi, dijagram i tabela Sedam stanja; 42 nedozvoljena para
Teorija 3 7.7–7.9 Usklađenost modela; koji dijagram kada; stanja oko nas Poruka = operacija; stanje = atribut
Praksa 1–3 Mermaid sequenceDiagram i stateDiagram; Python mašina stanja Provjera PP-6 kodom

Dio 1 – Sekvencijalni dijagram

7.1 Ko kome šta šalje

Dijagram slučajeva korištenja (poglavlje 5) kaže da kupac naručuje hranu. Specifikacija kaže koje korake prolazi. Ali kada se sistem pravi od više dijelova (aplikacija na mobitelu, server, sistem plaćanja), treba znati još nešto: koji dio kome šalje koju poruku, i kojim redom. To pokazuje sekvencijalni dijagram.

Sekvencijalni dijagram se čita kao strip ili kao zapisnik razgovora:

  • Učesnici stoje u redu na vrhu: akter (figurica) ili objekat (pravougaonik). Za N-1001: Kupac, Aplikacija, Server DeliveryApp, Servis mapa, Sistem plaćanja, Restoran.
  • Ispod svakog učesnika spušta se linija života: uspravna linija niz koju teče vrijeme. Ono što je više, desilo se ranije.
  • Poruke su vodoravne strelice od pošiljaoca do primaoca, s imenom poruke iznad. U Mermaidu ->> (puna linija) znači poziv, a -->> (isprekidana) odgovor.
  • Uski pravougaonik na liniji života (aktivacija) pokazuje vrijeme dok učesnik radi na poruci.

Postoje dvije vrste poziva, i razlika je važna za projektovanje:

  • Sinhrona poruka: pošiljalac čeka odgovor prije nego što nastavi. Server pita servis mapa za udaljenost i čeka, jer bez udaljenosti ne može izračunati dostavu.
  • Asinhrona poruka: pošiljalac pošalje i odmah nastavi, ne čekajući. Server javi restoranu „nova narudžba” i ne čeka da kuhar pročita; kupac odmah vidi da je narudžba primljena.

Slika iz života: sinhrona poruka je telefonski poziv (čekate da druga strana odgovori), a asinhrona je SMS (pošaljete i nastavite svoj posao).

Ukratko.

  • Sekvencijalni dijagram pokazuje koji dio sistema kome šalje koju poruku i kojim redom.
  • Učesnici su na vrhu, vrijeme teče niz linije života, a poruke su vodoravne strelice.
  • Sinhrona poruka čeka odgovor (telefonski poziv), a asinhrona ne čeka (SMS).

7.2 Sekvenca naručivanja N-1001

Evo glavnog toka UC-01 za narudžbu N-1001 kao Mermaid teksta:

sequenceDiagram
    actor K as Kupac
    participant A as Aplikacija
    participant S as Server DeliveryApp
    participant M as Servis mapa
    participant P as Sistem plaćanja
    participant R as Restoran
    K->>A: bira 2× Margarita i 1× Sok
    K->>A: unosi adresu
    A->>S: izracunaj_cijenu(stavke, adresa)
    S->>M: udaljenost(R-1, adresa)
    M-->>S: 4,2 km
    S-->>A: artikli 21,50 €, dostava 3,00 €, ukupno 24,50 €
    A-->>K: pregled narudžbe
    K->>A: potvrdi i plati
    A->>S: napravi_narudzbu()
    S->>P: naplati(24,50 €)
    alt plaćanje odobreno
        P-->>S: odobreno
        S->>R: nova narudžba N-1001
        S-->>A: N-1001 u stanju NOVA
        A-->>K: Narudžba N-1001 je primljena
    else plaćanje odbijeno
        P-->>S: odbijeno
        S-->>A: greška plaćanja
        A-->>K: Plaćanje nije uspjelo
    end

Pročitajmo ga odozgo, kao razgovor:

  1. Kupac u aplikaciji bira dvije Margarite i sok, pa unosi adresu.
  2. Aplikacija ne računa cijenu sama, nego pita server. To je važna projektna odluka: pravila PP-1 do PP-5 žive na jednom mjestu, na serveru, a ne u svakoj aplikaciji na svakom mobitelu (o tome više u poglavlju 9).
  3. Server pita servis mapa za udaljenost i čeka (sinhrono). Dobija 4,2 km.
  4. Server računa i vraća aplikaciji 21,50 €, 3,00 € i 24,50 €; aplikacija to pokazuje kupcu.
  5. Kupac potvrđuje; server traži naplatu od sistema plaćanja.
  6. Ovdje se tok grana (okvir alt): ako je plaćanje odobreno, server šalje narudžbu restoranu i javlja kupcu broj N-1001; ako nije, javlja grešku.

Primijetite tri stvari koje ovaj dijagram otkriva, a koje ranije nisu bile vidljive:

  • Svaka strelica prema serveru je buduća operacija API-ja (izracunaj_cijenu, napravi_narudzbu); u poglavlju 10 one postaju adrese na serveru.
  • Vidi se ko čeka koga. Ako servis mapa odgovara 8 sekundi, kupac 8 sekundi gleda prazan ekran. Zato specifikacija ima alternativni tok 3a (servis mapa ne odgovara 10 sekundi).
  • Vidi se koliko puta se ide preko mreže: ovdje šest poziva preko interneta prije nego što kupac vidi „primljena”. Svaki od njih može biti spor ili pasti.

Slika 7.1 – Sekvencijalni dijagram naručivanja N-1001

Ukratko.

  • Sekvenca N-1001 ima šest učesnika: kupca, aplikaciju, server, servis mapa, sistem plaćanja i restoran.
  • Aplikacija ne računa cijenu sama; pravila žive na serveru.
  • Strelice prema serveru postaju operacije API-ja.
  • Dijagram pokazuje ko koga čeka i koliko poziva ide preko mreže.

7.3 Kombinovani fragmenti: alt, opt, loop

Stvarni tok nije uvijek ravna linija. Sekvencijalni dijagram zato ima kombinovane fragmente: okvire s oznakom u gornjem lijevom uglu.

Fragment Značenje Primjer u DeliveryApp
alt (alternative) ili jedno ili drugo, zavisno od uslova plaćanje odobreno / odbijeno
opt (option) dio koji se izvrši samo ako je uslov tačan ako je upisan kod: provjeri kod popusta
loop dio koji se ponavlja za svaku stavku: provjeri da je jelo dostupno
par (parallel) dijelovi koji teku istovremeno obavijesti restoran i pošalji kupcu potvrdu

Primjer s opt i loop, dio koji provjerava korpu prije računanja:

sequenceDiagram
    participant S as Server DeliveryApp
    participant J as Jelovnik
    loop za svaku stavku
        S->>J: dostupno(jelo)?
        J-->>S: da
    end
    opt kupac je upisao kod
        S->>S: popust(iznos, kod)
    end

Strelica S->>S je poruka samom sebi: server poziva svoju operaciju. Crta se kao mala petlja na istoj liniji života.

Fragmenti su korisni, ali ih ne treba pretjerivati. Sekvencijalni dijagram s pet ugniježđenih okvira postaje nečitljiv; tada je bolje nacrtati dva dijagrama (jedan za uspjeh, jedan za grešku) ili tok prebaciti u dijagram aktivnosti (poglavlje 5).

Česta zabluda. „Sekvencijalni dijagram treba pokazati sve slučajeve.” Ne treba. Jedan sekvencijalni dijagram obično pokazuje jedan scenarij, najčešće glavni tok, uz najvažniju grešku. Ostali scenariji su u specifikaciji i testovima.

Ukratko.

  • Fragment alt pokazuje izbor, opt opcioni dio, loop ponavljanje, a par istovremene dijelove.
  • Poruka samom sebi crta se kao petlja na istoj liniji života.
  • Jedan sekvencijalni dijagram pokazuje jedan scenarij; previše fragmenata ga čini nečitljivim.

Provjeri se.

  1. Šta znači da je vrijeme na sekvencijalnom dijagramu „odozgo prema dolje”? – Poruka koja je više desila se ranije.
  2. Zašto je poziv servisu mapa sinhron? – Jer server bez udaljenosti ne može izračunati dostavu, pa mora čekati odgovor.
  3. Koji fragment koristimo za „ako je upisan kod”? – opt.

Dio 2 – Dijagram stanja

7.4 Stanje, prelaz, događaj

Neki objekti se kroz život mijenjaju na predvidiv način. Narudžba se rodi kad je plaćena, restoran je prihvati, kuhar je pripremi, dostavljač je odveze. U svakom trenutku narudžba je u tačno jednom stanju, a iz svakog stanja može preći samo u neka druga. Takvo ponašanje crta dijagram stanja (mašina stanja).

Pet pojmova:

  1. Stanje – situacija u kojoj objekat čeka ili radi, dok se ne desi nešto novo: NOVA, NA_PUTU. Crta se kao zaobljen pravougaonik.
  2. Prelaz – strelica iz jednog stanja u drugo.
  3. Događaj – ono što pokreće prelaz: „restoran prihvati”, „kupac otkaže”, „prošlo 5 minuta”. Piše se na strelici.
  4. Uslov (guard) – izraz u uglastim zagradama koji mora biti tačan: kupac otkaže [stanje prije pripreme]. Ako nije tačan, prelaza nema.
  5. Akcija – kratak posao pri prelazu, piše se iza kose crte: kupac otkaže / vrati novac.

Zapis na strelici ima opšti oblik događaj [uslov] / akcija, i svaki dio je opcionalan.

Uz to postoje dva posebna čvora: početni (pun crni krug), iz kojeg objekat ulazi u prvo stanje, i završni (krug u krugu), u koji objekat ulazi kad je njegov život gotov.

Slika iz života: semafor. Stanja su crveno, crveno-žuto, zeleno, žuto. Događaj je „prošlo 30 sekundi”. Iz zelenog se ne može direktno u crveno-žuto; mora se proći kroz žuto. Upravo ta pravila (koji prelazi postoje, a koji ne) su suština dijagrama stanja.

Ukratko.

  • Stanje je situacija u kojoj objekat čeka ili radi; objekat je uvijek u tačno jednom stanju.
  • Prelaz je strelica između stanja, a pokreće ga događaj.
  • Zapis na prelazu je „događaj [uslov] / akcija”.
  • Kao kod semafora, važno je i koji prelazi postoje i koji ne postoje.

7.5 Mašina stanja narudžbe

Pravila DeliveryApp, prvenstveno PP-6, daju ovu mašinu stanja:

stateDiagram-v2
    state "NOVA" as NOVA
    state "PRIHVAĆENA" as PRIHVACENA
    state "ODBIJENA" as ODBIJENA
    state "U_PRIPREMI" as U_PRIPREMI
    state "NA_PUTU" as NA_PUTU
    state "ISPORUČENA" as ISPORUCENA
    state "OTKAZANA" as OTKAZANA
    [*] --> NOVA: plaćanje odobreno
    NOVA --> PRIHVACENA: restoran prihvati
    NOVA --> ODBIJENA: restoran odbije ili 5 min bez odgovora / vrati novac
    NOVA --> OTKAZANA: kupac otkaže / vrati novac
    PRIHVACENA --> U_PRIPREMI: kuhar počne
    PRIHVACENA --> OTKAZANA: kupac otkaže / vrati novac
    U_PRIPREMI --> NA_PUTU: dostavljač preuzme
    NA_PUTU --> ISPORUCENA: dostavljač preda
    ISPORUCENA --> [*]
    ODBIJENA --> [*]
    OTKAZANA --> [*]

Red state "PRIHVAĆENA" as PRIHVACENA daje stanju kratko ime bez dijakritika za kod, a puno ime za sliku; tako se izbjegavaju problemi sa slovima č, ć i ž u imenima.

Pročitajmo život narudžbe N-1001: plaćanje je odobreno, pa je narudžba NOVA. Picerija R-1 prihvati: PRIHVAĆENA. Kuhar počne: U_PRIPREMI. Dostavljač preuzme: NA_PUTU. Dostavljač preda: ISPORUČENA, i život narudžbe je gotov.

Dijagram pokazuje i ono čega nema. Iz U_PRIPREMI ne vodi nijedna strelica u OTKAZANA: to je pravilo PP-6 nacrtano. Iz ISPORUČENA ne vodi nijedna strelica nigdje: isporučena narudžba se ne može „vratiti” u pripremu. ISPORUČENA, ODBIJENA i OTKAZANA su završna stanja.

Događaj „5 minuta bez odgovora” je vremenski događaj: ne izaziva ga čovjek, nego sat. To je pravilo koje smo otkrili crtajući BPMN u poglavlju 4 (srednji vremenski događaj), a ovdje dobija svoje mjesto u životu narudžbe.

Slika 7.2 – Dijagram stanja narudžbe: sedam stanja, tri završna

Na času. Kupac zove i kaže: „Pogriješio sam adresu, a dostavljač je već krenuo.” Šta dijagram kaže da sistem smije uraditi? (Stanje je NA_PUTU; prelaz u OTKAZANA ne postoji. Sistem ne smije otkazati; tim treba odlučiti da li je potreban novi događaj „promijeni adresu”, uz poziv dostavljaču. To je nova priča za backlog.)

Ukratko.

  • Narudžba ima sedam stanja: NOVA, PRIHVAĆENA, ODBIJENA, U_PRIPREMI, NA_PUTU, ISPORUČENA i OTKAZANA.
  • Normalan život je NOVA, PRIHVAĆENA, U_PRIPREMI, NA_PUTU, ISPORUČENA.
  • Iz U_PRIPREMI nema strelice u OTKAZANA; to je pravilo PP-6.
  • ISPORUČENA, ODBIJENA i OTKAZANA su završna stanja, a „5 minuta bez odgovora” je vremenski događaj.

7.6 Tabela prelaza i mašina stanja u kodu

Dijagram je dobar za ljude. Za provjeru i za kod korisnija je tabela prelaza: redovi su stanja, kolone su moguća nova stanja, a u ćeliji piše da li je prelaz dozvoljen.

Iz  U NOVA PRIHV. ODBIJ. U_PRIP. NA_PUTU ISPOR. OTKAZ.
NOVA – da da – – – da
PRIHVAĆENA – – – da – – da
ODBIJENA – – – – – – –
U_PRIPREMI – – – – da – –
NA_PUTU – – – – – da –
ISPORUČENA – – – – – – –
OTKAZANA – – – – – – –

Tabela ima 7 × 7 = 49 ćelija, a samo 7 je „da”. Ostalih 42 su nedozvoljeni parovi. To je važan broj za testiranje: dobar tester provjeri ne samo sedam dozvoljenih prelaza, nego i da sistem odbija nedozvoljene, na primjer U_PRIPREMI → OTKAZANA ili ISPORUČENA → NOVA. U predmetu Testiranje softvera ova tehnika se zove testiranje prelaza stanja.

Tabela se direktno prepisuje u kod. U primjeri/deliveryapp/deliveryapp.py stoji:

PRELAZI = {
    "NOVA": {"PRIHVAĆENA", "ODBIJENA", "OTKAZANA"},
    "PRIHVAĆENA": {"U_PRIPREMI", "OTKAZANA"},
    "U_PRIPREMI": {"NA_PUTU"},
    "NA_PUTU": {"ISPORUČENA"},
    "ISPORUČENA": set(),
    "ODBIJENA": set(),
    "OTKAZANA": set(),
}

class Narudzba:
    def __init__(self, broj):
        self.broj = broj
        self.stanje = "NOVA"
        self.istorija = ["NOVA"]

    def promijeni(self, novo):
        if novo not in PRELAZI[self.stanje]:
            raise ValueError(f"nedozvoljen prelaz {self.stanje} -> {novo}")
        self.stanje = novo
        self.istorija.append(novo)

Svaki red rječnika PRELAZI je jedan red tabele; set() znači završno stanje. Operacija promijeni je enkapsulacija iz poglavlja 6: stanje se mijenja samo ako je prelaz u tabeli. Lista istorija pamti cijeli život narudžbe, što je korisno i za kupca („kada je krenula?”) i za provjeru (revizijski trag, poglavlje 12).

Broj za pamćenje. Mašina stanja narudžbe ima 7 dozvoljenih i 42 nedozvoljena prelaza. Sistem mora ispravno reagovati na svih 49.

Ukratko.

  • Tabela prelaza za svako stanje kaže u koja stanja se smije preći.
  • Od 49 parova stanja narudžbe, 7 je dozvoljeno, a 42 nije.
  • Rječnik PRELAZI u Pythonu je ista tabela; operacija promijeni() odbija sve što nije u tabeli.
  • Istorija stanja pamti život narudžbe i služi kao trag.

Provjeri se.

  1. Šta znači zapis „kupac otkaže / vrati novac”? – Događaj je otkazivanje kupca, a akcija pri prelazu je povrat novca.
  2. Koja su završna stanja narudžbe? – ISPORUČENA, ODBIJENA i OTKAZANA.
  3. Koliko nedozvoljenih parova ima tabela prelaza? – 42 od 49.

Dio 3 – Modeli koji se slažu

7.7 Usklađenost modela

Do sada imamo mnogo modela istog sistema: proces (BPMN), slučajeve korištenja, klase, sekvence i stanja. Svaki gleda iz svog ugla. Opasnost je da počnu govoriti jedan protiv drugog: u dijagramu stanja narudžba ima stanje NA_PUTU, a u klasnom dijagramu klasa Narudzba nema atribut stanja; ili sekvencijalni dijagram šalje poruku napravi_narudzbu, a nijedna klasa nema takvu operaciju.

Zato se modeli provjeravaju jedan prema drugom. Pravila usklađenosti za DeliveryApp:

Ako u ovom modelu… …onda u ovom mora postojati Primjer
slučaj korištenja bar jedan sekvencijalni dijagram ili specifikacija UC-01 → slika 7.1
učesnik u sekvenci (osim aktera) klasa ili komponenta Server DeliveryApp → poglavlje 9
poruka objektu operacija u njegovoj klasi dostupno(jelo) → operacija klase Jelo
dijagram stanja objekta atribut stanja u klasi stanje → atribut -stanje klase Narudzba
događaj u dijagramu stanja aktivnost u procesu ili korak slučaja „restoran prihvati” → UC-02
akcija pri prelazu operacija ili poruka „vrati novac” → UC-04 «include» Vrati novac

Ova tabela je i praktična lista za recenziju (poglavlje 14). Kad tim pregleda modele, prolazi je red po red.

Iz stvarnog svijeta. Neusklađeni modeli su čest uzrok grešaka koje se otkriju tek kad se dijelovi spoje, kao kod Healthcare.gova iz poglavlja 1: svaka firma je imala svoj dio i svoj opis, ali opisi se nisu slagali. Što ranije se modeli uporede, to jeftinije.

Ukratko.

  • Različiti modeli istog sistema moraju se slagati.
  • Svaka poruka objektu je operacija u njegovoj klasi, a svako stanje je vrijednost atributa.
  • Događaji i akcije u dijagramu stanja moraju postojati i u procesu ili slučajevima korištenja.
  • Tabela usklađenosti služi kao lista za recenziju modela.

7.8 Koji dijagram kada

Projektant ne crta sve dijagrame za svaku stvar. Bira dijagram prema pitanju na koje treba odgovoriti:

Pitanje Dijagram Poglavlje
Kako posao teče kroz organizaciju i ko šta radi? BPMN 4
Kako teku podaci i gdje se čuvaju? DFD 4
Ko koristi sistem i za šta? slučajevi korištenja 5
Kojim redom idu koraci jednog posla s odlukama? aktivnosti (ili dijagram toka) 5
Koje stvari sistem zna i kako su povezane? klase 6
Ko kome šalje poruku i kojim redom? sekvencijalni 7
Kroz koja stanja prolazi jedna stvar? stanja 7
Koje tabele čuvamo? ER / relaciona šema 8
Od kojih dijelova je sistem i gdje rade? C4 9

Dobro pravilo: dijagram stanja se crta samo za objekte koji zaista imaju zanimljiv život (narudžba, plaćanje, nalog dostavljača). Za Jelo (dostupno ili ne) dijagram stanja nije potreban; dovoljna je jedna rečenica.

Ukratko.

  • Dijagram se bira prema pitanju na koje treba odgovoriti.
  • Sekvencijalni dijagram odgovara ko kome šalje poruke, a dijagram stanja kroz koja stanja prolazi jedna stvar.
  • Dijagram stanja crta se samo za objekte sa zanimljivim životom, kao što je narudžba.

7.9 Stanja oko nas

Kad jednom naučite misliti u stanjima, vidite ih svuda, i to pomaže u projektovanju bilo kojeg sistema:

  • Automat za kafu: ČEKA_NOVAC → IMA_NOVAC → PRIPREMA → IZDAJE → ČEKA_NOVAC. Događaj „ubačeno 1 €” u stanju PRIPREMA ne smije ništa promijeniti; inače automat proguta novac.
  • Lift: MIRUJE, IDE_GORE, IDE_DOLJE, VRATA_OTVORENA. Uslov „[vrata zatvorena]” na prelazu u IDE_GORE je sigurnosno pravilo.
  • Prijava u aplikaciju: ODJAVLJEN → ČEKA_KOD (dvofaktorska prijava) → PRIJAVLJEN → ZAKLJUČAN (nakon 5 pogrešnih pokušaja).
  • Plaćanje karticom: ZAPOČETO → ODOBRENO ili ODBIJENO; ODOBRENO → VRAĆENO (povrat novca).

Sistemi u realnom vremenu (poglavlje 13) skoro uvijek se projektuju kao mašine stanja: kontroler semafora, kočnica, pejsmejker. Razlog je isti kao kod Turinga 1936: kad je ponašanje opisano konačnim brojem stanja i jasnim prelazima, može se provjeriti svaki slučaj, a to je kod sistema od kojih zavisi život neophodno.

Slika 7.3 – Stanja oko nas: automat za kafu i prijava s dva faktora

Ukratko.

  • Mašine stanja su svuda: automat za kafu, lift, prijava u aplikaciju, plaćanje karticom.
  • Događaj u pogrešnom stanju ne smije ništa promijeniti, inače automat proguta novac.
  • Sistemi u realnom vremenu projektuju se kao mašine stanja jer se tada može provjeriti svaki slučaj.

Provjeri se.

  1. Ako sekvencijalni dijagram šalje poruku dostupno(jelo) objektu Jelovnik, šta mora postojati u klasnom dijagramu? – Operacija dostupno u klasi tog objekta.
  2. Kojim dijagramom odgovaramo na pitanje „kroz koja stanja prolazi plaćanje”? – Dijagramom stanja.
  3. Treba li klasi Jelo dijagram stanja? – Ne; njen život (dostupno ili ne) dovoljno je opisati jednom rečenicom.

Praktična nastava – sekvence i stanja DeliveryApp

Cilj je nacrtati sekvencu naručivanja i mašinu stanja narudžbe u Mermaidu, napisati mašinu stanja u Pythonu i automatski provjeriti svih 49 parova prelaza. Fajlovi idu u modeli/ i kod/.

Korak 1 – Sekvencijalni dijagram

  1. U modeli/sekvence.md prepišite sekvencu iz 7.2 (blok mermaid) i pogledajte je u pregledu.
  2. Dodajte fragment opt „kupac je upisao kod” sa samopozivom servera popust(iznos, kod) prije vraćanja cijene. Izmijenite poruku o cijeni da za kod STUDENT10 pokazuje 22,35 €.
  3. Nacrtajte drugi sekvencijalni dijagram, za UC-02 Prihvati ili odbij narudžbu: Restoran, Aplikacija restorana, Server, Sistem plaćanja, Kupac. Koristite alt za prihvatanje i odbijanje (s povratom novca).
  4. Za svaku poruku prema serveru zapišite ime buduće operacije API-ja u tabelu ispod dijagrama.

Korak 2 – Dijagram stanja

  1. U modeli/stanja.md prepišite dijagram iz 7.5.
  2. Dodajte stanje REKLAMACIJA: iz ISPORUČENA, događaj „kupac prijavi problem u roku od 24 h”; iz REKLAMACIJA u RIJEŠENA. Promijenite da ISPORUČENA više nije završno stanje i obrazložite promjenu jednom rečenicom.
  3. Napravite tabelu prelaza (kao u 7.6) za svoju novu verziju. Koliko je sada dozvoljenih i nedozvoljenih parova?

Korak 3 – Mašina stanja u Pythonu

  1. U kod/ imate deliveryapp.py iz poglavlja 6. U kod/provjera_stanja.py napišite:
from deliveryapp import Narudzba, PRELAZI

STANJA = list(PRELAZI)
dozvoljeno = nedozvoljeno = 0
for iz in STANJA:
    for u in STANJA:
        n = Narudzba("N-TEST")
        n.stanje = iz              # samo za test: postavljamo početno stanje
        try:
            n.promijeni(u)
            dozvoljeno += 1
        except ValueError:
            nedozvoljeno += 1
print("dozvoljeno:", dozvoljeno, "nedozvoljeno:", nedozvoljeno)
  1. Pokrenite python provjera_stanja.py. Očekivani ispis je:
dozvoljeno: 7 nedozvoljeno: 42
  1. Napišite i provjeru života N-1001 od NOVA do ISPORUČENA i ispišite n.istorija. Zatim provjerite da otkazivanje iz U_PRIPREMI baca grešku.
  2. Dodajte stanja REKLAMACIJA i RIJEŠENA u PRELAZI i ponovo pokrenite provjeru. Da li se broj slaže s vašom tabelom iz koraka 2?

Korak 4 – Usklađenost

Napravite u modeli/uskladenost.md tabelu iz 7.7 za svoj projekat: za svaku poruku iz oba sekvencijalna dijagrama napišite klasu i operaciju iz klasnog dijagrama (poglavlje 6); ako operacija ne postoji, dodajte je u klasni dijagram.

Korak 5 – AI kao provjera (opcionalno)

Dajte AI asistentu svoj dijagram stanja i zatražite: „Navedi događaje koji bi u stvarnoj aplikaciji za dostavu mogli stići u pogrešnom stanju, i šta bi sistem trebao uraditi.” Provjerite svaki prijedlog prema pravilima PP-1 do PP-6 i dodajte u backlog one koje biste i sami branili.

Rezultat koji se predaje: modeli/sekvence.md (dva sekvencijalna dijagrama i tabela operacija), modeli/stanja.md (dijagram s reklamacijom i tabela prelaza), kod/provjera_stanja.py koji ispisuje 7 i 42 za osnovnu mašinu, te modeli/uskladenost.md.

Vježbe

Vježba za studenta 1 – sinhrono ili asinhrono.

Koje poruke biste projektovali kao sinhrone, a koje kao asinhrone? a) Server pita sistem plaćanja da li je kartica odobrena. b) Server javlja kupcu SMS-om da je narudžba krenula. c) Aplikacija pita server za ukupnu cijenu. d) Server bilježi u dnevnik (log) da je narudžba prihvaćena.

Rješenje. a) sinhrona (bez odgovora se ne zna smije li se narudžba napraviti); b) asinhrona (server ne treba čekati da SMS stigne); c) sinhrona (kupac mora vidjeti cijenu prije plaćanja); d) asinhrona (zapis u dnevnik ne treba usporavati rad).

Vježba za studenta 2 – čitanje sekvence.

Na slici 7.1 prebrojite poruke koje putuju između aplikacije i servera (u oba smjera) u slučaju odobrenog plaćanja. Zašto je taj broj važan za projektanta?

Rješenje. Aplikacija → server: izracunaj_cijenu i napravi_narudzbu (2); server → aplikacija: cijena i „N-1001 u stanju NOVA” (2); ukupno 4 poruke. Važan je jer svaka poruka ide preko mobilne mreže, koja može biti spora ili se prekinuti; projektant zato smanjuje broj takvih poziva i predviđa šta se dešava ako jedan ne uspije.

Vježba za studenta 3 – prelazi.

Za svaki pokušaj recite da li je dozvoljen i zašto: a) N-1002 je NA_PUTU, a kupac pokuša otkazati. b) N-1007 je NOVA, a restoran je odbije. c) N-1001 je ISPORUČENA, a restoran pokuša vratiti stanje u U_PRIPREMI. d) N-1010 je PRIHVAĆENA, a kupac otkaže.

Rješenje. a) Nije dozvoljeno: iz NA_PUTU postoji samo prelaz u ISPORUČENA (PP-6). b) Dozvoljeno: NOVA → ODBIJENA, uz akciju povrata novca. c) Nije dozvoljeno: ISPORUČENA je završno stanje. d) Dozvoljeno: PRIHVAĆENA → OTKAZANA, uz povrat novca (PP-6).

Vježba za studenta 4 – mašina stanja plaćanja.

Nacrtajte dijagram stanja za objekat Plaćanje: ZAPOČETO, ODOBRENO, ODBIJENO, VRAĆENO. Povrat novca je moguć samo za odobreno plaćanje. Koliko je dozvoljenih prelaza i koliko nedozvoljenih parova?

Rješenje. Prelazi: [*] → ZAPOČETO; ZAPOČETO → ODOBRENO (banka odobri); ZAPOČETO → ODBIJENO (banka odbije); ODOBRENO → VRAĆENO (narudžba odbijena ili otkazana / vrati novac). Završna stanja: ODBIJENO i VRAĆENO. Među četiri stanja ima 4 × 4 = 16 parova, od kojih su 3 dozvoljena, pa je 13 nedozvoljenih.

Vježba za studenta 5 – usklađenost.

U dijagramu stanja narudžbe postoji akcija „vrati novac”, a u sekvencijalnom dijagramu UC-02 server šalje poruku povrat(N-1007) sistemu plaćanja. U klasnom dijagramu klasa Placanje ima samo atribute iznos i odobreno. Šta nije usklađeno i kako popraviti?

Rješenje. Akcija i poruka govore o povratu novca, a ni klasa Placanje ni stanje plaćanja to ne predviđaju. Treba dodati operaciju vrati() u klasu Placanje i atribut stanja plaćanja (ZAPOČETO, ODOBRENO, ODBIJENO, VRAĆENO), kao u vježbi 4; tada se poruka, akcija i klasa slažu.

Sažetak u pet rečenica

  1. Dinamički model pokazuje ponašanje sistema kroz vrijeme, a ideja stanja i prelaza seže do Turingove mašine iz 1936.
  2. Sekvencijalni dijagram pokazuje ko kome šalje koju poruku i kojim redom; za N-1001 ima šest učesnika, sinhrone i asinhrone poruke i fragment alt za plaćanje.
  3. Dijagram stanja narudžbe ima sedam stanja i sedam dozvoljenih prelaza u obliku „događaj [uslov] / akcija”, a pravilo PP-6 vidi se kao nepostojanje prelaza iz U_PRIPREMI u OTKAZANA.
  4. Tabela prelaza ima 49 parova, od kojih je 42 nedozvoljeno; ista tabela je rječnik PRELAZI u Pythonu, a operacija promijeni() odbija sve što nije u njoj.
  5. Modeli moraju biti usklađeni, tako da je svaka poruka operacija neke klase i svako stanje vrijednost atributa, a dijagram se bira prema pitanju na koje treba odgovoriti.

Pitanja za ponavljanje

  1. Šta je Turing opisao 1936. i kakve veze to ima s dijagramom stanja?
  2. Koja je razlika između strukturnog i dinamičkog modela?
  3. Koji su elementi sekvencijalnog dijagrama i kako se on čita?
  4. Koja je razlika između sinhrone i asinhrone poruke? Dajte primjer iz DeliveryApp za svaku.
  5. Ispričajte sekvencu naručivanja N-1001 od izbora jela do poruke „primljena”.
  6. Šta su fragmenti alt, opt, loop i par?
  7. Šta su stanje, prelaz, događaj, uslov i akcija?
  8. Nabrojte sedam stanja narudžbe i navedite tri završna.
  9. Kako se pravilo PP-6 vidi na dijagramu stanja?
  10. Šta je vremenski događaj? Navedite primjer.
  11. Šta je tabela prelaza i koliko dozvoljenih i nedozvoljenih parova ima za narudžbu?
  12. Kako tabela prelaza izgleda u Pythonu i šta radi operacija promijeni()?
  13. Navedite tri pravila usklađenosti modela.
  14. Kojim dijagramom odgovaramo na pitanje „ko kome šalje poruku”, a kojim „kroz koja stanja prolazi stvar”?

Odgovori na pitanja za ponavljanje.

  1. Turing je opisao zamišljenu mašinu s trakom, glavom i malim skupom stanja, koja u svakom koraku na osnovu stanja i pročitanog znaka upiše znak, pomjeri glavu i pređe u novo stanje. Ideja da se ponašanje opiše stanjima i prelazima osnova je dijagrama stanja.
  2. Strukturni model pokazuje od čega je sistem (klase, atributi, veze), kao fotografija. Dinamički model pokazuje kako se sistem ponaša kroz vrijeme (poruke, stanja), kao film.
  3. Učesnici su na vrhu, ispod svakog je linija života niz koju teče vrijeme, poruke su vodoravne strelice s imenom, a aktivacija je uski pravougaonik dok učesnik radi. Čita se odozgo prema dolje, kao razgovor.
  4. Kod sinhrone poruke pošiljalac čeka odgovor (server pita servis mapa za udaljenost); kod asinhrone ne čeka (server javi restoranu da je stigla nova narudžba ili pošalje SMS kupcu).
  5. Kupac bira jela i adresu; aplikacija pita server za cijenu; server pita servis mapa za udaljenost (4,2 km) i vraća 21,50 €, 3,00 € i 24,50 €; kupac potvrđuje; server traži naplatu od sistema plaćanja; ako je odobreno, server šalje narudžbu restoranu i javlja aplikaciji da je N-1001 u stanju NOVA, a aplikacija kupcu da je primljena.
  6. alt je izbor jedne od grana prema uslovu, opt je dio koji se izvrši samo ako je uslov tačan, loop je ponavljanje, a par su dijelovi koji teku istovremeno.
  7. Stanje je situacija u kojoj objekat čeka ili radi; prelaz je prelazak u drugo stanje; događaj je ono što pokreće prelaz; uslov je izraz u uglastim zagradama koji mora biti tačan; akcija je kratak posao pri prelazu, pisan iza kose crte.
  8. NOVA, PRIHVAĆENA, ODBIJENA, U_PRIPREMI, NA_PUTU, ISPORUČENA, OTKAZANA; završna su ISPORUČENA, ODBIJENA i OTKAZANA.
  9. Iz NOVA i PRIHVAĆENA postoji prelaz u OTKAZANA, a iz U_PRIPREMI i NA_PUTU ne postoji. Nepostojanje strelice je pravilo da se narudžba ne može otkazati kad je priprema počela.
  10. Vremenski događaj nastaje zbog proteklog vremena, a ne zbog čovjeka; npr. „5 minuta bez odgovora restorana” prevodi narudžbu iz NOVA u ODBIJENA, uz povrat novca.
  11. Tabela prelaza za svako stanje kaže u koja stanja se smije preći. Za narudžbu ima 7 × 7 = 49 parova, od kojih je 7 dozvoljeno, a 42 nedozvoljeno.
  12. Kao rječnik PRELAZI u kojem je ključ stanje, a vrijednost skup dozvoljenih novih stanja (prazan skup za završno stanje). Operacija promijeni() provjeri je li novo stanje u skupu; ako nije, baci grešku, a ako jeste, promijeni stanje i doda ga u istoriju.
  13. Na primjer: svaka poruka objektu mora biti operacija u njegovoj klasi; svaki dijagram stanja zahtijeva atribut stanja u klasi; svaki događaj u dijagramu stanja mora postojati kao aktivnost u procesu ili korak slučaja korištenja.
  14. Sekvencijalnim dijagramom odgovaramo ko kome šalje poruku i kojim redom, a dijagramom stanja kroz koja stanja prolazi jedna stvar.