Poglavlje 6: Strukturni model – klase i objekti
Priča za početak. Početkom šezdesetih godina dvojica norveških naučnika, Ole-Johan Dahl i Kristen Nygaard, radili su u Norveškom računskom centru u Oslu na simulacijama: kako se ponaša red brodova u luci, kako teče posao u fabrici, gdje se stvaraju gužve. Programi tog vremena bili su dugi spiskovi naredbi, i u njima se teško vidjelo šta je brod, a šta dizalica. Dahl i Nygaard su smislili drugačiji način: program se sastoji od objekata koji liče na stvari iz stvarnog svijeta, a svaki objekat ima svoje podatke i svoje ponašanje. Opis po kojem se prave svi brodovi iste vrste nazvali su klasa. Jezik koji su napravili zvao se Simula, a njegova verzija iz 1967. godine prvi je jezik s klasama, objektima i nasljeđivanjem. Kasnije su iz te ideje nastali Smalltalk, C++, Java, Python i C#, pa danas skoro svaki programer misli u objektima. Dahl i Nygaard su 2001. godine dobili Turingovu nagradu, koja se često naziva „Nobelovom nagradom za računarstvo”, upravo za objektno orijentisano programiranje.
U poglavlju 5 opisali smo šta DeliveryApp radi za svakog aktera. Sada pitamo: šta DeliveryApp zna? Koje „stvari” postoje u sistemu, šta o svakoj pamti i kako su povezane? Odgovor daje strukturni model, a u UML-u ga crtamo dijagramom klasa. Prvo objašnjavamo objekat i klasu, uz Python kod. Zatim učimo veze među klasama: asocijaciju, višestrukost, kompoziciju i nasljeđivanje. Na kraju iz teksta vizije pronalazimo klase i crtamo domenski model DeliveryApp. Na praktičnoj nastavi isti model crtamo u Mermaidu i pišemo ga kao Python klase koje računaju 24,50 €.
Literatura. Osnovna literatura predmeta:
- B. Popović, K. Kuk: Informacioni sistemi, Kriminalističko-policijski univerzitet, Beograd, 2017.
- J. S. Valacich, J. F. George: Modern Systems Analysis and Design, 9th ed., Pearson, 2020.
- L. Jelenković: Sustavi za rad u stvarnom vremenu – skripta, FER, Zagreb, 2015.
- D. Milićev: Programiranje u realnom vremenu – skripta, Beograd, 2002.
- V. Kovačević, M. Popović: Sistemska programska podrška u realnom vremenu 1, FTN, Novi Sad, 2013.
Riječi ovog poglavlja.
- Objekat – jedna konkretna stvar u sistemu, s vlastitim podacima (npr. narudžba N-1001).
- Klasa – opis po kojem se prave svi objekti iste vrste (npr. klasa Narudžba).
- Atribut – podatak koji objekat pamti (broj, stanje, udaljenost).
- Operacija (metoda) – nešto što objekat zna uraditi (dodati stavku, izračunati ukupno).
- Instanca – drugo ime za objekat napravljen po klasi.
- Enkapsulacija – skrivanje unutrašnjih podataka objekta, tako da se mijenjaju samo kroz njegove operacije.
- Asocijacija – veza između klasa koja kaže da se njihovi objekti „poznaju” (kupac pravi narudžbu).
- Višestrukost – koliko objekata jedne klase može biti povezano s jednim objektom druge (1, 0..1, 0.., 1..).
- Kompozicija – jaka veza „dio–cjelina”: dio ne postoji bez cjeline (stavka bez narudžbe).
- Agregacija – slaba veza „dio–cjelina”: dio postoji i sam (dostavljač bez tima).
- Nasljeđivanje (generalizacija) – posebna klasa preuzima sve od opšte i dodaje svoje (Kupac je vrsta Korisnika).
- Domenski model – dijagram klasa koji opisuje pojmove posla, bez tehničkih detalja.
- Dijagram objekata – slika stvarnih objekata i njihovih vrijednosti u jednom trenutku.
Ciljevi poglavlja. Nakon poglavlja možete: objasniti razliku između objekta i klase na primjeru narudžbe; za objekat navesti stanje, ponašanje i identitet; nacrtati klasu u UML-u s atributima, tipovima, operacijama i vidljivošću; objasniti enkapsulaciju i zašto stanje narudžbe ne mijenjamo direktno; nacrtati asocijaciju s višestrukošću i pročitati je kao rečenicu; razlikovati kompoziciju, agregaciju i običnu asocijaciju; prepoznati kada je nasljeđivanje dobar izbor, a kada nije; iz teksta vizije izdvojiti kandidate za klase, atribute i operacije; nacrtati domenski model DeliveryApp u Mermaidu; napisati kostur klasa u Pythonu i provjeriti da daje 24,50 € za N-1001; nacrtati dijagram objekata za N-1001.
Plan poglavlja – Sedmica 6: tri časa teorije i tri časa praktične nastave
| Čas | Sadržaj | Na času |
|---|---|---|
| Teorija 1 | 6.1–6.3 Objekat, klasa, enkapsulacija | Kalup i kolači; klasa Narudžba u UML-u i Pythonu |
| Teorija 2 | 6.4–6.6 Asocijacija, višestrukost, kompozicija, nasljeđivanje | „Jedan kupac pravi nula ili više narudžbi” |
| Teorija 3 | 6.7–6.9 Od imenica do klasa; domenski model; objekti | Domenski model DeliveryApp; N-1001 kao objekti |
| Praksa 1–3 | Mermaid classDiagram; Python klase |
model.py računa 24,50 € |
Dio 1 – Objekat i klasa
6.1 Objekat
Objekat je jedna konkretna stvar u sistemu. Narudžba N-1001 je objekat. Picerija R-1 je objekat. Pizza Margarita na jelovniku R-1 je objekat. Svaki objekat ima tri osobine:
- Stanje – podaci koje objekat u ovom trenutku pamti. Narudžba N-1001 pamti: broj „N-1001”, kupca K-01, restoran R-1, udaljenost 4,2 km, dvije stavke i stanje NOVA.
- Ponašanje – šta objekat zna uraditi. Narudžba zna dodati stavku, izračunati ukupnu cijenu i promijeniti stanje.
- Identitet – po čemu je ovaj objekat on, a ne neki drugi. Dvije narudžbe mogu imati iste stavke i istu adresu, ali su ipak dvije različite narudžbe (N-1001 i N-1007), kao što dvije sestre bliznakinje nisu ista osoba.
Objekat može predstavljati i nešto što se ne može dodirnuti: narudžbu, plaćanje, kod popusta. Pravilo je jednostavno: ako sistem o nečemu mora pamtiti podatke i to nešto treba razlikovati od drugih iste vrste, to je kandidat za objekat.
Ukratko.
- Objekat je jedna konkretna stvar u sistemu, opipljiva ili ne (narudžba, restoran, plaćanje).
- Objekat ima stanje (podatke), ponašanje (šta zna uraditi) i identitet (po čemu je baš on).
- Ako sistem o nečemu pamti podatke i razlikuje ga od drugih, to je kandidat za objekat.
6.2 Klasa
Klasa je opis po kojem se prave svi objekti iste vrste. Klasa Narudžba kaže: svaka narudžba ima broj, kupca, restoran, udaljenost, stavke i stanje, i svaka zna izračunati ukupnu cijenu. Svaki pojedinačni objekat (N-1001, N-1002…) je instanca te klase: ima istu građu, ali svoje vrijednosti.
Najbolja slika iz života je kalup za kolače. Kalup je klasa: određuje oblik. Kolači su objekti: svaki ima isti oblik, ali jedan je s čokoladom, drugi s vanilom, a treći je pojeden. Kalup se ne jede; kolač se jede. Isto tako, klasa Narudžba ne košta ništa; narudžba N-1001 košta 24,50 €.
Klasa u UML-u
U dijagramu klasa klasa se crta kao pravougaonik s tri dijela:
- gore ime klase (imenica u jednini, veliko početno slovo: Narudzba);
- u sredini atributi, u obliku
ime: tip; - dolje operacije, u obliku
ime(parametri): tip rezultata.
Ispred atributa i operacija stoji znak vidljivosti: + znači javno (svi smiju koristiti), - znači privatno (samo sam objekat), # znači zaštićeno (objekat i njegove podklase). Evo klase Narudzba kao Mermaid teksta:
classDiagram
class Narudzba {
+broj: str
+udaljenost_km: float
-stanje: str
+dodaj(jelo: Jelo, kolicina: int)
+artikli() int
+dostava() int
+ukupno() int
+promijeni(novo: str)
}
Primijetite da u imenima pišemo „Narudzba” bez slova ž. Mermaid i većina programskih jezika dozvoljavaju i naša slova, ali mnogi alati i baze s njima imaju problema, pa je dobra navika da se u imenima u kodu koriste samo engleska slova, a u tekstu za ljude puni dijakritici.
Ista klasa u Pythonu
Dijagram i kod opisuju isto. Ovako izgleda dio klase u Pythonu (cijeli fajl je primjeri/deliveryapp/model.py):
@dataclass
class Narudzba:
broj: str
kupac: Kupac
restoran: Restoran
udaljenost_km: float
kod: str | None = None
stavke: list = field(default_factory=list)
stanje: str = "NOVA"
def dodaj(self, jelo, kolicina=1):
self.stavke.append(Stavka(jelo, kolicina))
def artikli(self):
return sum(s.iznos() for s in self.stavke)
def ukupno(self):
a = self.artikli()
return a - popust(a, self.kod) + self.dostava()Oznaka @dataclass kaže Pythonu da sam napravi dio koda koji puni atribute; mi pišemo samo atribute i operacije. Iznosi su u centima (950 znači 9,50 €), da bi se izbjegle greške zaokruživanja decimalnih brojeva u računaru; na ekranu ih pretvaramo nazad u eure.

Ukratko.
- Klasa je opis po kojem se prave objekti iste vrste, kao kalup za kolače.
- Svaki objekat je instanca klase: ista građa, svoje vrijednosti.
- U UML-u klasa je pravougaonik s imenom, atributima i operacijama; + je javno, − privatno.
- Isti model se piše i kao Python klasa; iznosi su u centima da se izbjegne zaokruživanje.
6.3 Enkapsulacija
Zamislite da svako ko ima pristup narudžbi može direktno napisati n.stanje = "OTKAZANA", u bilo kom trenutku. Šta sprečava da neko otkaže narudžbu koja je već na putu, suprotno pravilu PP-6? Ništa.
Enkapsulacija (od latinskog „u kapsulu”) znači da objekat skriva svoje unutrašnje podatke, a mijenja ih samo kroz svoje operacije, koje provjeravaju pravila. Narudžba ne dozvoljava da joj neko spolja postavi stanje; dozvoljava samo poziv promijeni("OTKAZANA"), a ta operacija prvo provjeri je li prelaz dozvoljen:
def promijeni(self, novo):
if novo not in PRELAZI[self.stanje]:
raise ValueError(f"nedozvoljen prelaz {self.stanje} -> {novo}")
self.stanje = novoZato je u UML-u atribut stanje označen s - (privatno), a operacija promijeni s + (javno).
Slika iz života: bankomat. Novac je u kapsuli; ne možete otvoriti bankomat i uzeti koliko hoćete. Možete samo pozvati operaciju „podigni 50 €”, a bankomat provjeri PIN i stanje računa prije nego što isplati. Pravila su na jednom mjestu, unutar objekta, i niko ih ne može zaobići.
Česta zabluda. „Enkapsulacija je skrivanje od drugih programera, iz nepovjerenja.” Nije. Enkapsulacija čuva pravila na jednom mjestu. Kad se pravilo PP-6 promijeni, mijenja se samo operacija
promijeni, a ne stotinu mjesta u kodu koja su direktno pisala stanje.
Ukratko.
- Enkapsulacija znači da objekat skriva svoje podatke i mijenja ih samo kroz operacije koje provjeravaju pravila.
- Stanje narudžbe je privatno; mijenja se samo operacijom promijeni(), koja provjerava PP-6.
- Kao bankomat: novac je u kapsuli, a isplata ide samo kroz operaciju s provjerom.
Provjeri se.
- Koje tri osobine ima svaki objekat? – Stanje, ponašanje i identitet.
- Šta je razlika između klase i objekta? – Klasa je opis (kalup), a objekat je konkretna instanca s vrijednostima (kolač).
- Zašto je atribut stanje privatan? – Da bi se mijenjao samo kroz operaciju koja provjerava dozvoljene prelaze.
Dio 2 – Veze između klasa
6.4 Asocijacija i višestrukost
Klase same nisu mnogo korisne. Narudžba mora znati čija je i iz kojeg restorana. Veza koja kaže da se objekti dvije klase „poznaju” zove se asocijacija i crta se linijom između klasa. Na krajevima linije piše višestrukost: koliko objekata s te strane može biti povezano s jednim objektom s druge strane.
| Oznaka | Značenje | Primjer |
|---|---|---|
1 |
tačno jedan | narudžba ima tačno jednog kupca |
0..1 |
nijedan ili jedan | narudžba ima nijednog ili jednog dostavljača (dok ga ne dobije) |
0..* ili * |
nijedan ili više | kupac može imati nula ili više narudžbi |
1..* |
jedan ili više | narudžba ima bar jednu stavku |
Asocijacija se čita kao rečenica, u oba smjera. Za vezu Kupac "1" --> "0..*" Narudzba : pravi:
- „Jedan kupac pravi nula ili više narudžbi.”
- „Jedna narudžba pripada tačno jednom kupcu.”
Ako se rečenica ne slaže sa stvarnošću, dijagram je pogrešan. Može li narudžba imati dva kupca? U DeliveryApp ne. Može li kupac postojati bez ijedne narudžbe? Da, tek se registrovao. Zato je višestrukost na strani narudžbe 0..*, a ne 1..*.
Višestrukost nije sitnica. Ona direktno postaje pravilo u bazi (poglavlje 8) i provjera u kodu. Ako je na strani stavki 1..*, sistem ne smije sačuvati narudžbu bez ijedne stavke.
Na času. Pročitajte naglas, u oba smjera:
Narudzba "0..*" --> "0..1" Dostavljac : nosi. Zašto je na strani dostavljača 0..1, a ne 1? (Jer narudžba u stanju NOVA još nema dostavljača.)
Ukratko.
- Asocijacija je linija koja kaže da se objekti dvije klase poznaju.
- Višestrukost na krajevima linije kaže koliko objekata može biti povezano: 1, 0..1, 0..* ili 1..*.
- Asocijacija se čita kao rečenica u oba smjera, i mora se slagati sa stvarnošću.
- Višestrukost postaje pravilo u bazi i provjera u kodu.
6.5 Kompozicija i agregacija
Neke asocijacije su posebne: jedna strana je cjelina, a druga njen dio. UML razlikuje dvije jačine te veze.
Kompozicija je jaka veza: dio ne postoji bez cjeline i nestaje zajedno s njom. Crta se punim rombom (◆) na strani cjeline. Stavka „2 × Pizza Margarita” nema smisla bez narudžbe N-1001: ako se narudžba obriše, briše se i stavka. Isto važi za jelo na jelovniku restorana u DeliveryApp: kad restoran napusti DeliveryApp, njegov jelovnik nestaje s njim.
Agregacija je slaba veza: dio postoji i sam, a cjelina ga samo okuplja. Crta se praznim rombom (◇). Dostavljač D-2 može biti u timu „Jutarnja smjena”, ali ako se tim raspusti, D-2 i dalje postoji i vozi.
Slika iz života: kuća i sobe su kompozicija; kad se kuća sruši, sobe nestaju s njom. Fudbalski tim i igrači su agregacija; kad se tim raspusti, igrači prelaze u druge timove.
U praksi se agregacija rijetko crta, jer se teško razlikuje od obične asocijacije. Kompozicija je korisnija, jer kaže nešto važno za bazu i kod: brisanje cjeline briše i dijelove.
Ukratko.
- Kompozicija (pun romb) je jaka veza: dio ne postoji bez cjeline, kao stavka bez narudžbe.
- Agregacija (prazan romb) je slaba veza: dio postoji i sam, kao dostavljač bez tima.
- Kompozicija kaže da brisanje cjeline briše i njene dijelove.
6.6 Nasljeđivanje
Kupac, dostavljač i osoblje restorana imaju mnogo zajedničkog: svi se prijavljuju, svi imaju ime, e-mail i lozinku. Umjesto da ista tri atributa pišemo tri puta, napravimo opštu klasu Korisnik, a posebne klase je nasljeđuju: preuzimaju sve od nje i dodaju svoje. Kupac dodaje adrese, Dostavljac dodaje vrstu vozila.
U UML-u se nasljeđivanje (generalizacija) crta punom linijom sa šupljim trouglom na strani opšte klase. Čita se „je vrsta”: kupac je vrsta korisnika.
classDiagram
Korisnik <|-- Kupac
Korisnik <|-- Dostavljac
Korisnik <|-- OsobljeRestorana
class Korisnik {
+email: str
-lozinka_hes: str
+prijavi(email, lozinka) bool
}
class Kupac {
+adrese: list
}
class Dostavljac {
+vozilo: str
}
Kada nasljeđivanje nije dobar izbor
Nasljeđivanje je moćno, ali se lako zloupotrebi. Dva testa:
- Test „je vrsta”. Ako rečenica „B je vrsta A” zvuči čudno, nasljeđivanje je pogrešno. „Stavka je vrsta narudžbe”? Ne; stavka je dio narudžbe, pa je to kompozicija.
- Test zamjene. Svuda gdje sistem očekuje opštu klasu mora moći raditi i posebna, bez iznenađenja. Ako bi PlacanjeGotovinom moralo baciti grešku na operaciju „vrati novac na karticu”, onda možda ne treba nasljeđivati PlacanjeKarticom, nego obje klase trebaju nasljeđivati opštije Placanje.
U savremenom projektovanju često se kaže: radije sastavljaj nego nasljeđuj (composition over inheritance). Ako kupac i dostavljač samo dijele adresu, bolje je da oba imaju objekat Adresa nego da nasljeđuju klasu koja „ima adresu”.

Ukratko.
- Nasljeđivanje znači da posebna klasa preuzima sve od opšte i dodaje svoje; crta se šupljim trouglom.
- Nasljeđivanje se čita „je vrsta”: kupac je vrsta korisnika.
- Ako „je vrsta” zvuči čudno, ili posebna klasa ne može zamijeniti opštu, nasljeđivanje je pogrešno.
- Često je bolje sastavljati objekte (kupac ima adresu) nego nasljeđivati.
Provjeri se.
- Pročitajte vezu
Narudzba "1" *-- "1..*" Stavka. – Jedna narudžba se sastoji od jedne ili više stavki, a stavka ne postoji bez svoje narudžbe.- Koja je razlika između kompozicije i agregacije? – Kod kompozicije dio ne postoji bez cjeline, a kod agregacije postoji i sam.
- Da li je Stavka vrsta Narudžbe? – Ne; stavka je dio narudžbe, pa je veza kompozicija, a ne nasljeđivanje.
Dio 3 – Domenski model DeliveryApp
6.7 Od imenica do klasa
Odakle znamo koje klase DeliveryApp treba? Najjednostavnija tehnika je analiza teksta: uzmemo viziju, korisničke priče i specifikacije slučajeva korištenja i podvučemo imenice i glagole.
- Imenice su kandidati za klase ili atribute.
- Glagoli su kandidati za operacije ili asocijacije.
Iz specifikacije UC-01 (poglavlje 5): „Kupac bira jela i količine; sistem pokazuje zbir artikala. Kupac unosi adresu dostave. Sistem traži udaljenost od servisa mapa… Sistem pravi narudžbu u stanju NOVA i prikazuje je restoranu.”
Kandidate zatim sortiramo:
| Imenica | Odluka | Zašto |
|---|---|---|
| Kupac | klasa | sistem pamti njegove podatke i razlikuje kupce |
| Jelo | klasa | ima naziv i cijenu; restoran ih ima više |
| Količina | atribut (stavke) | broj, nema svoje ponašanje |
| Zbir artikala | operacija | računa se iz stavki, ne pamti se |
| Adresa | klasa ili atribut | klasa, ako kupac ima više adresa; inače atribut |
| Udaljenost | atribut (narudžbe) | broj u km |
| Servis mapa | nije klasa domena | vanjski sistem (akter), ne pojam posla |
| Sistem | odbaciti | to je DeliveryApp sam |
| Narudžba | klasa | srce sistema |
| Stanje | atribut | jedna od sedam vrijednosti |
| Restoran | klasa | ima jelovnik i narudžbe |
Primijetite tri pravila: ono što se računa nije atribut (zbir artikala računamo, ne pamtimo, jer bi inače mogao biti netačan); vanjski sistemi nisu klase domena; i „sistem” se odbacuje.
Ukratko.
- Analiza teksta: imenice su kandidati za klase ili atribute, glagoli za operacije ili veze.
- Kandidati se sortiraju: šta se pamti i razlikuje je klasa; jednostavan broj je atribut; ono što se računa je operacija.
- Vanjski sistemi i riječ „sistem” nisu klase domena.
6.8 Domenski model
Domenski model je dijagram klasa koji opisuje pojmove posla i njihove veze, bez tehničkih detalja (nema baze, ekrana, servera). Razumije ga i vlasnik restorana: on će reći „narudžba uvijek ima bar jedno jelo”, a mi ćemo to pročitati kao višestrukost 1..*.
Domenski model DeliveryApp:
classDiagram
class Kupac {
+oznaka: str
+telefon: str
}
class Adresa {
+ulica: str
+broj: str
}
class Restoran {
+oznaka: str
+naziv: str
+otvoren: bool
}
class Jelo {
+naziv: str
+cijena: int
+dostupno: bool
}
class Narudzba {
+broj: str
+udaljenost_km: float
-stanje: str
+artikli() int
+dostava() int
+ukupno() int
+promijeni(novo)
}
class Stavka {
+kolicina: int
+iznos() int
}
class Dostavljac {
+oznaka: str
+vozilo: str
}
class Placanje {
+iznos: int
+odobreno: bool
}
class KodPopusta {
+kod: str
+procenat: int
+max_iznos: int
}
Kupac "1" --> "1..*" Adresa : ima
Kupac "1" --> "0..*" Narudzba : pravi
Restoran "1" *-- "1..*" Jelo : nudi
Narudzba "0..*" --> "1" Restoran : iz
Narudzba "1" *-- "1..*" Stavka : sadrži
Stavka "0..*" --> "1" Jelo : od
Narudzba "0..*" --> "0..1" Dostavljac : nosi
Narudzba "1" --> "0..1" Placanje : plaćena
Narudzba "0..*" --> "0..1" KodPopusta : koristi
Pročitajmo nekoliko veza kao rečenice: „Jedan restoran nudi jedno ili više jela, a jelo ne postoji bez restorana.” „Jedna narudžba sadrži jednu ili više stavki.” „Svaka stavka je od tačno jednog jela, a jedno jelo može biti u mnogo stavki.” „Narudžba može koristiti nijedan ili jedan kod popusta.”
Jedno pitanje vrijedi postaviti glasno: zašto Stavka ima samo količinu, a ne i cijenu? Ako restoran sutra poskupi Margaritu na 10,00 €, da li se mijenja i cijena već plaćene narudžbe N-1001? Ne smije! Zato u stvarnom sistemu stavka pamti cijenu u trenutku narudžbe (cijena_u_trenutku: int). Ovo je primjer kako domenski model otkriva poslovno pravilo koje niko nije izgovorio. Dopisujemo ga u backlog i u model.

Ukratko.
- Domenski model je dijagram klasa s pojmovima posla, bez tehničkih detalja.
- DeliveryApp ima devet klasa: Kupac, Adresa, Restoran, Jelo, Narudžba, Stavka, Dostavljač, Plaćanje i KodPopusta.
- Svaka veza se čita kao rečenica koju potvrđuje čovjek iz posla.
- Model je otkrio novo pravilo: stavka pamti cijenu u trenutku narudžbe.
6.9 Dijagram objekata
Dijagram klasa je kalup. Ponekad je korisno nacrtati i kolače: stvarne objekte s vrijednostima u jednom trenutku. To je dijagram objekata. Ime objekta piše se podvučeno, u obliku ime: Klasa, a umjesto tipova stoje vrijednosti.
Narudžba N-1001, u trenutku kad je plaćena:
| Objekat | Vrijednosti |
|---|---|
| k01: Kupac | oznaka = “K-01” |
| r1: Restoran | oznaka = “R-1”, naziv = “Picerija” |
| margarita: Jelo | naziv = “Pizza Margarita”, cijena = 950 |
| sok: Jelo | naziv = “Sok”, cijena = 250 |
| n1001: Narudzba | broj = “N-1001”, udaljenost_km = 4.2, stanje = “NOVA” |
| s1: Stavka | kolicina = 2 → margarita |
| s2: Stavka | kolicina = 1 → sok |
Iz ovih vrijednosti operacije daju: s1.iznos() = 2 × 950 = 1900; s2.iznos() = 250; n1001.artikli() = 2150; n1001.dostava() = 300; n1001.ukupno() = 2450 centi = 24,50 €.
Dijagram objekata je odličan za provjeru modela: ako ne možete nacrtati stvaran primjer s vrijednostima, model ima rupu. Probajte, na primjer, nacrtati narudžbu bez stavki: višestrukost 1..* kaže da to nije dozvoljeno, i dijagram objekata to odmah pokaže.

Ukratko.
- Dijagram objekata prikazuje stvarne objekte i njihove vrijednosti u jednom trenutku.
- Za N-1001 operacije daju 2150 centi artikala, 300 centi dostave i ukupno 2450 centi, odnosno 24,50 €.
- Ako se ne može nacrtati stvaran primjer s vrijednostima, model ima rupu.
Provjeri se.
- Zašto „zbir artikala” nije atribut? – Jer se računa iz stavki; da se pamti, mogao bi postati netačan.
- Zašto Servis mapa nije klasa domenskog modela? – To je vanjski sistem (akter), a ne pojam posla.
- Koliko je
n1001.ukupno()? – 2450 centi, odnosno 24,50 €.
Praktična nastava – domenski model u Mermaidu i Pythonu
Cilj je nacrtati domenski model DeliveryApp i napisati ga kao Python klase koje računaju cijenu narudžbe po pravilima PP-1 do PP-5. Fajlovi idu u modeli/ i kod/ repozitorija deliveryapp-projekat.
Korak 1 – Analiza teksta
U modeli/klase.md napravite tabelu imenica iz svoje specifikacije UC-01 i UC-02 (poglavlje 5) s odlukom: klasa, atribut, operacija ili odbaciti, i razlogom. Najmanje 15 imenica.
Korak 2 – Domenski model u Mermaidu
- U
modeli/klase.mdprepišite domenski model iz 6.8 (blokmermaid). - Dodajte atribut
cijena_u_trenutku: intu klasu Stavka. - Dodajte klasu Ocjena (kupac ocjenjuje restoran od 1 do 5 nakon isporuke) s vezama i višestrukošću. Napišite obje rečenice za svaku novu vezu.
- Dodajte nasljeđivanje Korisnik → Kupac, Dostavljac, OsobljeRestorana iz 6.6.
- Provjerite da se dijagram iscrtava (pregled u VS Codeu ili mermaid.live).
Korak 3 – Python klase
- U folder
kod/kopirajtedeliveryapp.pyimodel.pyizprimjeri/deliveryapp/(repozitorij udžbenika) ili ih prepišite. - Pokrenite u terminalu:
python model.py
Očekivani ispis:
N-1001 artikli 21,50 € dostava 3,00 € ukupno 24,50 €
sa kodom 22,35 €
- Dodajte u klasu Narudzba operaciju
promijeni(novo)iz 6.3, koja koristi rječnikPRELAZIizdeliveryapp.py. - Na kraj
model.pydodajte provjere:
n.promijeni("PRIHVAĆENA")
n.promijeni("U_PRIPREMI")
try:
n.promijeni("OTKAZANA")
print("GREŠKA: otkazivanje u pripremi je prošlo")
except ValueError:
print("ispravno: otkazivanje u pripremi nije dozvoljeno (PP-6)")- Napravite i narudžbu N-1002 (4 × Ćevapi, 2,5 km) i provjerite da je ukupno 3200 centi.
Korak 4 – Dijagram objekata
Nacrtajte (u Mermaidu kao classDiagram s imenima objekata, ili na papiru pa slikajte) dijagram objekata za N-1002 u trenutku isporuke: kupac, restoran, jelo, stavka, narudžba, dostavljač D-3 i plaćanje.
Korak 5 – AI kao recenzent modela (opcionalno)
Dajte AI asistentu svoj Mermaid domenski model i zatražite: „Pročitaj svaku vezu kao rečenicu u oba smjera i reci mi koja ti zvuči sumnjivo za aplikaciju za dostavu hrane.” Za svaku primjedbu odlučite sami da li je opravdana. Zatražite i da iz modela napiše Python klase; pokrenite ih i uporedite rezultat s 24,50 €.
Rezultat koji se predaje: modeli/klase.md (analiza teksta i domenski model s dodacima), kod/model.py koji ispisuje 24,50 €, 22,35 €, poruku o PP-6 i 32,00 € za N-1002, te dijagram objekata za N-1002.
Vježbe
Vježba za studenta 1 – objekat ili klasa.
Šta je klasa, a šta objekat? a) Pizza Margarita na jelovniku R-1; b) Jelo; c) dostavljač D-3; d) Plaćanje; e) plaćanje karticom za N-1001 u iznosu 24,50 €.
Rješenje. Klase: b) Jelo, d) Plaćanje. Objekti: a) (instanca klase Jelo), c) (instanca klase Dostavljač), e) (instanca klase Plaćanje).
Vježba za studenta 2 – višestrukost.
Napišite višestrukost i pročitajte vezu u oba smjera: a) Restoran – Narudžba; b) Kupac – Adresa (kupac mora imati bar jednu adresu da bi naručio, a može ih sačuvati više); c) Narudžba – Plaćanje.
Rješenje. a) Restoran "1" <-- "0..*" Narudzba: jedan restoran ima nula ili više narudžbi; jedna narudžba je iz tačno jednog restorana. b) Kupac "1" --> "1..*" Adresa: jedan kupac ima jednu ili više adresa; jedna adresa pripada jednom kupcu. c) Narudzba "1" --> "0..1" Placanje: jedna narudžba ima nijedno ili jedno plaćanje (prije naplate nijedno); plaćanje pripada tačno jednoj narudžbi.
Vježba za studenta 3 – kompozicija, agregacija ili nasljeđivanje.
- Restoran i Jelo; b) Tim dostavljača i Dostavljač; c) PlacanjeKarticom i Placanje; d) Narudžba i Kupac.
Rješenje. a) kompozicija (jelo u DeliveryApp ne postoji bez restorana); b) agregacija (dostavljač postoji i bez tima); c) nasljeđivanje (plaćanje karticom je vrsta plaćanja); d) obična asocijacija (kupac nije dio narudžbe, niti obrnuto).
Vježba za studenta 4 – računanje kroz objekte.
Napravite (na papiru) objekte za narudžbu N-1005: kupac K-05 iz Salatarnice R-3 naručuje 2 × Salata s piletinom (9,00 €) i 2 × Limunada (3,00 €), na 6,5 km, s kodom STUDENT10. Šta vraćaju artikli(), dostava() i ukupno() (u centima)?
Rješenje. artikli = 2 × 900 + 2 × 300 = 2400 centi (24,00 €). Dostava: 24,00 € < 30,00 €, a preko 3 km je 3,5 km, dakle četiri započeta kilometra: 200 + 4 × 50 = 400 centi (4,00 €). Popust: 10 % od 2400 = 240 centi (manje od 500). ukupno = 2400 − 240 + 400 = 2560 centi = 25,60 €.
Vježba za studenta 5 – nedostajuće pravilo.
Kupac K-01 je naručio N-1001 kad je Margarita koštala 9,50 €. Sedmicu kasnije restoran je poskupi na 10,00 € i kupac otvori istoriju narudžbi. Šta pokazuje model iz 6.8 bez dodatka iz koraka 2, a šta s dodatkom? Kako se to zove u projektovanju?
Rješenje. Bez dodatka stavka pokazuje na jelo, pa bi se ukupno ponovo izračunalo s novom cijenom: 2 × 10,00 + 2,50 + 3,00 = 25,50 €, što nije iznos koji je kupac platio (24,50 €). S atributom cijena_u_trenutku stavka pamti 950 centi, pa istorija pokazuje tačnih 24,50 €. Ovo je primjer da se istorijski podaci zamrzavaju u trenutku transakcije; to je poslovno pravilo koje je otkrio model, a ne korisnik.
Sažetak u pet rečenica
- Objekat je konkretna stvar u sistemu sa stanjem, ponašanjem i identitetom, a klasa je opis po kojem se prave objekti iste vrste, ideja koja potiče iz jezika Simula iz 1967.
- U UML-u klasa je pravougaonik s imenom, atributima i operacijama, a enkapsulacija skriva podatke tako da se mijenjaju samo kroz operacije koje provjeravaju pravila.
- Asocijacija s višestrukošću (1, 0..1, 0.., 1..) čita se kao rečenica u oba smjera, kompozicija znači da dio ne postoji bez cjeline, a nasljeđivanje da je posebna klasa vrsta opšte.
- Klase se nalaze analizom teksta, a domenski model DeliveryApp ima devet klasa i otkrio je novo pravilo da stavka pamti cijenu u trenutku narudžbe.
- Isti model napisan kao Python klase računa za N-1001 2150 centi artikala, 300 centi dostave i ukupno 24,50 €, a dijagram objekata provjerava model na stvarnom primjeru.