Dio 1 – Sekvencijalni dijagram
Dio 2 – Dijagram stanja narudžbe
Dio 3 – Usklađenost modela
Praksa – sequenceDiagram, stateDiagram; Python
Materijale priredio Erkan Islamović
erkan.islamovic@eubd.edu.ba · erkan.islamovic@gmail.com
Petnaest sedmica, svaka s tri časa teorije i tri časa prakse. Danas: poglavlje 7 (Sedmica 7, označeno). Isti primjer kroz knjigu: DeliveryApp, narudžba N-1001 (24,50 €).
| Sed. | Poglavlje | Sed. | Poglavlje |
|---|---|---|---|
| 1 | P1 Zašto projektujemo | 9 | P9 Arhitektura |
| 2 | P2 Životni ciklus | 10 | P10 Integracija i API |
| 3 | P3 Zahtjevi | 11 | P11 Korisnički interfejs |
| 4 | P4 Poslovni procesi | 12 | P12 Sigurnost i privatnost |
| 5 | P5 UML i slučajevi korištenja | 13 | P13 Realno vrijeme i IoT |
| 6 | P6 Klase i objekti | 14 | P14 Kvalitet i isporuka |
| 7 | P7 Sekvence i stanja | 15 | P15 AI i završni projekat |
| 8 | P8 Baza podataka |
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.
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.
| Č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 |
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:
->> (puna linija) znači poziv, a -->> (isprekidana) odgovor.Postoje dvije vrste poziva, i razlika je važna za projektovanje:
Slika iz života: sinhrona poruka je telefonski poziv (čekate da druga strana odgovori), a asinhrona je SMS (pošaljete i nastavite svoj posao).
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
endPročitajmo ga odozgo, kao razgovor:
Primijetite tri stvari koje ovaj dijagram otkriva, a koje ranije nisu bile vidljive:
izracunaj_cijenu, napravi_narudzbu); u poglavlju 10 one postaju adrese na serveru.
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)
endStrelica 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).
„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.
Odgovori: tipka R ili klik na zamućeno polje.
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:
kupac otkaže [stanje prije pripreme]. Ako nije tačan, prelaza nema.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.
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.

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.)
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).
Odgovori: tipka R ili klik na zamućeno polje.
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.
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.
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.
Kad jednom naučite misliti u stanjima, vidite ih svuda, i to pomaže u projektovanju bilo kojeg sistema:
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.

dostupno(jelo) objektu Jelovnik, šta mora postojati u klasnom dijagramu? Operacija dostupno u klasi tog objekta.Odgovori: tipka R ili klik na zamućeno polje.
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/.
modeli/sekvence.md prepišite sekvencu iz 7.2 (blok mermaid) i pogledajte je u pregledu.popust(iznos, kod) prije vraćanja cijene. Izmijenite poruku o cijeni da za kod STUDENT10 pokazuje 22,35 €.modeli/stanja.md prepišite dijagram iz 7.5.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)python provjera_stanja.py. Očekivani ispis je:dozvoljeno: 7 nedozvoljeno: 42n.istorija. Zatim provjerite da otkazivanje iz U_PRIPREMI baca grešku.PRELAZI i ponovo pokrenite provjeru. Da li se broj slaže s vašom tabelom iz koraka 2?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.
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.
Rješenja su sakrivena – tipka R ili klik na okvir.
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.
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).
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?
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.
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.
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).
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?
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.
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?
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.