Dio 1 – Konceptualni model, UML, SOLID
Dio 2 – Prototip, UX, specifikacija dizajna
Dopunska praksa – Wireframe i SDD
Materijale priredio Erkan Islamović
erkan.islamovic@eubd.edu.ba · erkan.islamovic@gmail.com
Deset predavanja: dva časa teorije i jedan čas dopunske prakse. Danas: poglavlje 3 (označeno). Isti primjer kroz knjigu: DeliveryApp 2.0.
| Pred. | Dio 1 | Dio 2 | Praksa |
|---|---|---|---|
| 1 | Projekat i proizvod, trendovi, etika | Inženjerski pristup, alati, automatizacija | Repozitorij i vizija proizvoda |
| 2 | Modeli, uloge, planiranje | Rizici, tim, kvalitet, poboljšanje procesa | Plan izdanja, registar rizika |
| 3 | Konceptualni model, UML, SOLID | Prototip, UX, specifikacija dizajna | Wireframe i SDD |
| 4 | IDE, organizacija koda, OOP, okviri | Podaci, MVC/MVVM, čisti kod, refaktoring | Refaktoring funkcije |
| 5 | Git, pull request, CI | Testovi, CD, kontejneri | GitHub Actions |
Deset predavanja: dva časa teorije i jedan čas dopunske prakse. Danas je poglavlje 3. Isti primjer kroz knjigu: DeliveryApp 2.0.
| Pred. | Dio 1 | Dio 2 | Praksa |
|---|---|---|---|
| 6 | Klasifikacija, mjerljivost | Taktike i redizajn | Mjerenje i keš |
| 7 | Odluke, pogledi, stilovi | Troslojna i čista arhitektura, predlošci | ADR i C4 |
| 8 | CBSE, odlike, interfejsi | Principi, smjernice, provođenje | Paket sa verzijom |
| 9 | SaaS, SOA, IoT, proizvodne linije | Aspekti, reaktivno programiranje | Dekorator i tok događaja |
| 10 | Vrijednost, troškovi, razvoj ili kupnja, TCO | Metrike, procjena, NPV, povrat | NPV u Pythonu |
U decembru 1979. godine mala grupa iz Applea, sa Steveom Jobsom na čelu, posjetila je istraživački centar Xerox PARC u Palo Altu. Xerox je zauzvrat dobio pravo da prije izlaska Applea na berzu kupi 100.000 Appleovih dionica po 10,50 dolara. U PARC-u su vidjeli računar Alto: ekran s prozorima i ikonama, miš kojim se pokazuje i klikće, tekst koji na ekranu izgleda kao na papiru. Inženjeri Xeroxa su to napravili godinama ranije, ali Xerox nikad nije uspio od toga napraviti proizvod koji se masovno prodaje.
Jobs je kasnije pričao da ga je grafičko sučelje toliko zaslijepilo da nije ni primijetio ostale dvije novotarije koje su mu pokazali: objektno orijentirano programiranje (jezik Smalltalk) i umrežene računare. Apple je već radio na računarima Lisa i Macintosh, pa se i danas raspravlja koliko je posjeta zaista promijenila njihov dizajn. Ali jedna pouka nije sporna: ista tehnologija u jednoj firmi ostaje u laboratoriji, a u drugoj postaje proizvod, i razlika je u dizajnu, u tome koliko je neko mislio o čovjeku koji će proizvod koristiti.
U poglavlju 2 organizovali smo tim i napravili plan izdanja DeliveryApp 2.0. Prije nego što tim počne programirati, mora odlučiti kako će proizvod biti građen iznutra i kako će izgledati spolja. To je dizajn. Prvi dio govori o unutrašnjosti: konceptualnom modelu, UML dijagramima i principima objektno orijentiranog dizajna (SOLID). Drugi dio govori o onome što korisnik vidi: prototipu, korisničkom iskustvu i dokumentu u kojem se dizajn zapisuje da bi ga cijeli tim razumio isto.
Nakon poglavlja možete:
nacrtati konceptualni model domena i iz njega klasni dijagram; izabrati UML dijagram za dato pitanje (struktura, ponašanje, raspored); objasniti enkapsulaciju, apstrakciju, nasljeđivanje, kompoziciju i polimorfizam; objasniti svaki od pet principa SOLID na primjeru; izabrati nivo vjernosti prototipa; primijeniti Normanove principe i Nielsenove heuristike na ekran; prepoznati tamni obrazac; napisati kratak dokument specifikacije dizajna.
| Čas | Sadržaj | Na času |
|---|---|---|
| Teorija 1 | 3.1–3.4 Konceptualni model, UML, OO dizajn, SOLID | Domenski model DeliveryApp 2.0; tarifa kao podatak |
| Teorija 2 | 3.5–3.8 Prototip, UX, specifikacija dizajna, alati | Heuristička ocjena ekrana „Ponovi narudžbu” |
| Dopunska praksa | Wireframe i SDD za „Ponovi narudžbu” | Skica + dokument od dvije strane |
Prije nego što arhitekta nacrta kuću, pita porodicu: „Ko živi ovdje? Šta radite u kući?” Odgovori su riječi: spavaća soba, kuhinja, garaža, radni sto. Tek kad su riječi jasne, crta se plan.
Konceptualni model je takav popis riječi za softver: koji pojmovi postoje u svijetu proizvoda i kako su povezani. U njemu nema baze, ekrana ni programskog jezika. Za DeliveryApp 2.0 pojmovi su: grad, tarifa, restoran, jelo, kupac, narudžba, stavka, dostavljač. Veze: grad ima tarifu; restoran je u gradu; restoran nudi jela; kupac pravi narudžbe; narudžba sadrži stavke; stavka je za jedno jelo; dostavljač vozi narudžbu.
Konceptualni model se crta UML klasnim dijagramom. Uz svaku vezu piše se višestrukost: 1 (tačno jedan), (nula ili više), 1.. (bar jedan), 0..1 (nijedan ili jedan). Puni romb označava kompoziciju: stavka ne postoji bez svoje narudžbe.
classDiagram
Grad "1" -- "1" Tarifa : ima
Grad "1" -- "*" Restoran : u gradu
Restoran "1" -- "*" Jelo : nudi
Kupac "1" -- "*" Narudzba : pravi
Narudzba "1" *-- "1..*" Stavka : sadrži
Stavka "*" --> "1" Jelo : za
Dostavljac "0..1" -- "*" Narudzba : voziU vlastitom .md fajlu blok počinje sa ``` `mermaid ```, i VS Code ili GitHub ga iscrta.

Najvažnija novost u odnosu na verziju 1.x je pojam Tarifa. U verziji 1.x pravilo dostave bilo je napisano u kodu (2,00 € do 3 km, 0,50 € po kilometru). Kad se u modelu pojavi pojam „tarifa grada”, svima postaje jasno da je pravilo podatak koji se razlikuje od grada do grada.
Gdje u modelu treba dodati „Ponovi narudžbu”? Je li to novi pojam ili operacija postojećeg pojma? (Odgovor: operacija ponovi() na pojmu Narudžba; nova narudžba nastaje kao kopija stare sa svježim cijenama.)
UML je standardni jezik dijagrama za softver. Nastao je 1997. spajanjem metoda trojice autora (Booch, Rumbaugh, Jacobson), a danas ga održava organizacija OMG. Verzija 2.5 ima 14 vrsta dijagrama, ali u praksi se najviše koristi pet:
| Pitanje dizajna | UML dijagram | Primjer u DeliveryApp 2.0 |
|---|---|---|
| Koji pojmovi i klase postoje? | klasni | Narudžba, Stavka, Tarifa |
| Ko koga poziva i kojim redom? | sekvencijalni | tok „Ponovi narudžbu” |
| Kroz koja stanja prolazi objekat? | dijagram stanja | NOVA → … → ISPORUČENA |
| Od kojih dijelova se sastoji sistem? | dijagram komponenti | dostava, narudžbe, plaćanje (poglavlje 8) |
| Na kojim mašinama šta radi? | dijagram razmještaja | oblak, baza, mobitel (poglavlje 7) |
Sekvencijalni dijagram za „Ponovi narudžbu” pokazuje jednu važnu odluku dizajna: nova narudžba ne kopira stare cijene, nego ih ponovo čita iz jelovnika, i ponovo računa dostavu po tarifi grada. Ako se cijena promijenila, kupac to mora vidjeti prije potvrde.
sequenceDiagram
actor K as Kupac K-01
participant A as Mobilna aplikacija
participant S as Servis narudžbi
participant J as Jelovnik restorana
participant T as Tarifa grada
K->>A: dodir "Ponovi narudžbu" (N-1001)
A->>S: ponovi(N-1001)
S->>J: da li jela još postoje i koliko koštaju?
J-->>S: Margarita 9,50 €, Sok 2,50 €
S->>T: dostava(4,2 km, 21,50 €)
T-->>S: 3,00 €
S-->>A: nova narudžba, ukupno 24,50 €
A-->>K: "Potvrdi 24,50 €?"
„UML znači nacrtati sve dijagrame za cijeli sistem.” Dijagram se crta kad odgovara na pitanje koje tim ima. Martin Fowler razlikuje UML kao skicu (brzo, na tabli, da se tim dogovori), kao nacrt (detaljno, prije programiranja) i kao programski jezik (iz modela nastaje kod). Većina timova danas koristi UML kao skicu.
Objektno orijentirano programiranje (OOP) poznajete iz ranijih predmeta. Ovdje nas zanima kako se njegove ideje koriste za dobar dizajn, onaj koji se lako mijenja. Četiri ideje, uz analogiju s automobilom:
| Ideja | Šta znači | Automobil | DeliveryApp |
|---|---|---|---|
| Apstrakcija | pokaži samo ono što je važno | volan i pedale, a ne ventili | Tarifa.dostava(km, iznos) |
| Enkapsulacija | sakrij podatke, nudi operacije | ne diraš gorivo u motoru, sipaš na otvor | stanje narudžbe se mijenja samo preko promijeni() |
| Nasljeđivanje | nova klasa „jeste” vrsta stare | kombi jeste automobil | rijetko; vidi ispod |
| Polimorfizam | isti poziv, različito ponašanje | svaki auto „koči”, na svoj način | svaki način plaćanja ima naplati() |
Kompozicija prije nasljeđivanja. Prvi prijedlog za tarife u timu DeliveryApp bio je napraviti klase TarifaGradA, TarifaGradB, TarifaGradC, koje nasljeđuju zajedničku klasu. Za tri grada to radi, ali za trideset gradova znači trideset klasa, i svaki novi grad znači novi kod, novi test i novu isporuku. Bolje je rješenje da su sva tri grada ista klasa s različitim podacima:
@dataclass(frozen=True)
class Tarifa:
"""Pravila dostave jednog grada; novi grad je novi red podataka, ne novi kod."""
grad: str
osnovna: int # cijena do uključenih km, u centima
ukljuceno_km: float
po_km: int # za svaki započeti km preko uključenih
max_km: float
besplatna_od: int = 3000
min_narudzba: int = 500
def dostava(self, km: float, iznos: int) -> int:
if km < 0 or km > self.max_km:
raise ValueError("adresa je izvan zone dostave")
if iznos < self.min_narudzba:
raise ValueError("iznos je manji od najmanje narudžbe")
if iznos >= self.besplatna_od:
return 0
dodatni_km = math.ceil(max(0, km - self.ukljuceno_km))
return self.osnovna + self.po_km * dodatni_km
TARIFE = {
"A": Tarifa("A", osnovna=200, ukljuceno_km=3, po_km=50, max_km=10),
"B": Tarifa("B", osnovna=200, ukljuceno_km=2, po_km=60, max_km=8),
"C": Tarifa("C", osnovna=250, ukljuceno_km=3, po_km=50, max_km=12),
}Isto u C#, gdje record daje nepromjenjiv objekat s podacima:
record Tarifa(string Grad, int Osnovna, double UkljucenoKm, int PoKm, double MaxKm,
int BesplatnaOd = 3000, int MinNarudzba = 500)
{
public int Dostava(double km, int iznos)
{
if (km < 0 || km > MaxKm)
throw new ArgumentException("adresa je izvan zone dostave");
if (iznos < MinNarudzba)
throw new ArgumentException("iznos je manji od najmanje narudžbe");
if (iznos >= BesplatnaOd)
return 0;
int dodatniKm = (int)Math.Ceiling(Math.Max(0, km - UkljucenoKm));
return Osnovna + PoKm * dodatniKm;
}
}Oba programa (primjeri/python/dostava.py i primjeri/csharp/Dostava.cs) za N-1001 ispisuju dostavu 3,00 € u Gradu A, 3,80 € u Gradu B i 3,50 € u Gradu C.
dataclass i C# record su prirodan način da se napiše objekat koji nosi podatke.Robert C. Martin skupio je početkom 2000-ih pet principa objektno orijentiranog dizajna, a prva slova njihovih engleskih imena daju riječ SOLID (čvrst). Svi imaju isti cilj: da promjena na jednom mjestu ne izazove lavinu promjena na drugim.
| Slovo | Princip | Jednom rečenicom | U DeliveryApp 2.0 |
|---|---|---|---|
| S | jedna odgovornost | klasa ima samo jedan razlog za promjenu | Narudzba ne šalje SMS; za to postoji servis obavještenja |
| O | otvoreno–zatvoreno | otvoreno za proširenje, zatvoreno za izmjenu | novi grad = nova tarifa, postojeći kod se ne dira |
| L | zamjena (Liskov) | podtip mora raditi svuda gdje radi nadtip | svaki način plaćanja mora poštovati isti ugovor naplati() |
| I | razdvajanje interfejsa | bolje više malih interfejsa nego jedan veliki | dostavljač ne dobija interfejs s metodama za restoran |
| D | inverzija zavisnosti | zavisi od apstrakcije, ne od konkretne klase | narudžba zavisi od „servisa mapa”, a ne od jedne firme za mape |
Princip D je posebno važan za proizvod. U verziji 1.x DeliveryApp je direktno pozivao jednu firmu za mape. U Gradu B ta firma nema tačne adrese (rizik RZ-1 iz poglavlja 2). Ako kod zavisi od apstrakcije ServisMapa s jednom operacijom udaljenost(od, do), zamjena firme je promjena jedne klase, a ne pola aplikacije.
from typing import Protocol
class ServisMapa(Protocol):
def udaljenost(self, od: str, do: str) -> float: ...interface IServisMapa
{
double Udaljenost(string od, string doAdrese);
}
„SOLID znači da svaka klasa mora imati interfejs.” Principi su alat, a ne zakon. Interfejs ima smisla tamo gdje očekujemo zamjenu (mape, plaćanje, obavještenja). Za klasu koja se nikad neće zamijeniti, interfejs je samo još jedan fajl.
1..* na vezi Narudžba–Stavka? Narudžba ima bar jednu stavku.Odgovori: tipka R ili klik na zamućeno polje.
Prije nego što se sagradi zgrada, arhitekta napravi maketu. Maketa je jeftina, i na njoj se odmah vidi da je ulaz na pogrešnoj strani. Prototip je maketa softvera: rana verzija koja služi da se ideja provjeri s korisnicima prije nego što se programira.
Prototipovi se razlikuju po vjernosti (koliko liče na pravi proizvod):
| Nivo | Kako izgleda | Cijena izmjene | Čemu služi |
|---|---|---|---|
| Papirna skica | olovka i papir | sekunde | brzo isprobati više ideja |
| Wireframe | crno-bijeli raspored elemenata | minute | dogovor o rasporedu i toku |
| Mockup | boje, slova, slike, ali ne radi | sati | izgled i osjećaj |
| Interaktivni prototip | klikće se, prelazi s ekrana na ekran | sati do dana | test s korisnicima |
| Pravi kod | radi | dani | proizvod |

Pravilo: što je ideja neizvjesnija, to je prototip jeftiniji. Ena je za „Ponovi narudžbu” napravila tri papirne skice za deset minuta i pokazala ih petorici kupaca u kafiću. Dvojica nisu primijetila dugme na dnu ekrana. Tek tada je napravila wireframe s dugmetom na kartici prošle narudžbe.

Korisničko iskustvo (UX) je sve što korisnik doživi: da li je brzo našao šta treba, da li je razumio šta se desilo, da li je imao osjećaj kontrole, da li bi preporučio aplikaciju prijatelju. Dobar UX se ne vidi; loš se vidi odmah.
Normanovi principi. Don Norman je u knjizi The Design of Everyday Things (prvo izdanje 1988) objasnio zašto ljudi guraju vrata koja se vuku. Vrata s ručkom „kažu” povuci, a ravna ploča „kaže” gurni. Ako dizajn kaže jedno, a vrata traže drugo, kriv je dizajn, a ne čovjek. Takva vrata se danas zovu Normanova vrata. Njegovi principi:
Nielsenove heuristike. Jakob Nielsen objavio je 1994. deset pravila po kojima se sučelje ocjenjuje i bez korisnika. Najvažnija za DeliveryApp:
Ostale četiri su: fleksibilnost (prečice za iskusne), estetski i minimalistički dizajn, pomoć pri prepoznavanju i ispravci grešaka, te pomoć i dokumentacija.
Pristupačnost. Proizvod koriste i ljudi koji slabije vide, ne razlikuju boje ili koriste čitač ekrana. Pravila WCAG traže npr. kontrast teksta najmanje 4,5 : 1 (NZ-4 u DeliveryApp) i opis svake slike. Promjena cijene u „Ponovi narudžbu” ne smije se označiti samo crvenom bojom; uz boju ide i riječ „promijenjeno”.
Tamni obrasci. Suprotno dobrom UX-u su obrasci koji rade protiv korisnika: skrivena cijena dostave do posljednjeg koraka, unaprijed označena pretplata, dugme „Ne, hvala, ne volim uštedu”. Kratkoročno povećavaju prodaju, a dugoročno ruše povjerenje, i u Evropskoj uniji su sve češće zabranjeni propisima o zaštiti potrošača.

Otvorite aplikaciju koju koristite svaki dan i nađite jedno mjesto gdje krši neku Nielsenovu heuristiku. Koju, i kako biste to popravili?
Dizajn koji postoji samo u glavi jednog programera nije dizajn tima. Dokument specifikacije dizajna (SDD, software design description) zapisuje odluke tako da ih cijeli tim razumije isto, i da ih za godinu dana razumije i novi član. Standard IEEE 1016 opisuje šta takav dokument može sadržavati; u praksi je dovoljna kraća verzija.
Šablon koji koristi tim DeliveryApp (dvije do četiri strane po funkciji):
„Dokument dizajna se piše na kraju, za arhiv.” Dokument dizajna se piše prije programiranja, kratko, i mijenja se dok se dizajn mijenja. Najbolje mjesto mu je u repozitoriju, pored koda (npr. docs/dizajn/ponovi-narudzbu.md), da bi se mijenjao kroz isti pull request kao i kod.
| Posao | Alati (primjeri) | Napomena |
|---|---|---|
| UML i dijagrami kao tekst | Mermaid, PlantUML | dijagram je tekst, ide u Git, mijenja se kroz pull request |
| Crtanje mišem | draw.io (diagrams.net), Lucidchart | brzo za slobodne skice |
| Ozbiljno modelovanje | Enterprise Architect, Visual Paradigm | generisanje koda i dokumentacije iz modela |
| Prototip i UX | Figma, Penpot, papir | dijeljenje s timom, komentari, klik-prototip |
| Dokumentacija | Markdown u repozitoriju, wiki | jedan izvor istine |
| AI asistent | opšti AI asistenti | prijedlog dijagrama ili teksta; tim provjerava da li odgovara zahtjevima |
Prednost dijagrama kao teksta (Mermaid, PlantUML) je ista kao prednost koda: vidi se šta se promijenilo između dvije verzije, i dijagram se pregleda zajedno s kodom. AI asistent može iz opisa riječima predložiti Mermaid dijagram za sekundu, ali tim mora provjeriti da li je dijagram iscrtan bez greške i da li odgovara stvarnim pravilima (npr. da nije izmislio vezu „Kupac ima Tarifu”).
Odgovori: tipka R ili klik na zamućeno polje.
Cilj je napraviti skicu ekrana i kratak dokument dizajna za jednu funkciju. Trajanje: jedan čas.
Na papiru nacrtajte tri različita rasporeda ekrana „Moje narudžbe” s dugmetom „Ponovi”. Pokažite ih kolegi i zapišite šta je primijetio prvo.
Najbolju skicu prenesite u Figmu (okvir veličine mobitela) ili u draw.io. Samo sive kutije i tekst: naslov, kartica narudžbe N-1001 (datum, restoran, stavke, ukupno), dugme „Ponovi”, ekran potvrde s iznosom 24,50 € i oznakom „promijenjeno” ako se cijena promijenila.
U repozitoriju deliveryapp-2 napravite docs/dizajn/ponovi-narudzbu.md i u njega upišite sekvencijalni dijagram iz odjeljka 3.2 (blok ``` `mermaid ``). Dodajte alternativni tok kad jelo više ne postoji (alt` blok).
U isti fajl dopišite odjeljke iz šablona 3.7: svrha i obim, ponašanje (dijagram), sučelje (slika wireframea), NFR, jedna odluka s alternativom, otvorena pitanja.
Razmijenite wireframe s kolegom. Svako ocijeni tuđi ekran po šest heuristika iz 3.6 i zapiše bar dva problema s prijedlogom ispravke.
Rezultat: docs/dizajn/ponovi-narudzbu.md s dijagramom, slikom wireframea i ocjenom kolege.
Rješenja su sakrivena – tipka R ili klik na okvir.
DeliveryApp 2.0 dobija program vjernosti: kupac skuplja bodove, za svakih 10 € narudžbe dobija 1 bod, a 20 bodova može zamijeniti za besplatnu dostavu. Dodajte pojmove i veze u konceptualni model.
Novi pojam KarticaVjernosti (atribut bodovi), veza Kupac "1" -- "0..1" KarticaVjernosti. Pojam PromjenaBodova (datum, iznos, razlog) s vezom KarticaVjernosti "1" -- "" PromjenaBodova, i veza PromjenaBodova "*" --> "0..1" Narudzba (bodovi zarađeni ili potrošeni na narudžbi). Pravilo „10 € = 1 bod” je podatak (kao tarifa), a ne poseban pojam.
Klasa Narudzba ima metode dodaj_stavku(), ukupno(), posalji_sms_kupcu(), sacuvaj_u_bazu() i stampaj_racun_pdf(). Koji princip je narušen i kako biste je razdvojili?
Narušen je princip jedne odgovornosti: klasa se mijenja i kad se mijenja SMS dobavljač, i baza, i izgled računa. Narudžba zadržava dodaj_stavku() i ukupno(); posalji_sms_kupcu() ide u servis obavještenja, sacuvaj_u_bazu() u repozitorij narudžbi (poglavlje 7), a stampaj_racun_pdf() u generator računa.
Na ekranu plaćanja DeliveryApp dugme „Plati” je sivo i ništa se ne dešava kad se pritisne, jer adresa nije unesena. Koje heuristike i Normanovi principi su narušeni? Predložite ispravku.
Narušena je povratna informacija (Norman) i heuristike vidljivost stanja sistema i pomoć pri prepoznavanju greške (Nielsen). Ispravka: uz sivo dugme poruka „Unesite adresu dostave” i polje za adresu označeno okvirom i tekstom (ne samo bojom); nakon unosa dugme postaje aktivno.
Lana želi za funkciju „Praćenje dostavljača uživo” odmah praviti pravi kod, „jer je jasno šta treba”. Ena predlaže interaktivni prototip. Ko je u pravu i zašto?
Ena: funkcija je nova i neizvjesna (koliko često se tačka osvježava, šta se prikazuje kad dostavljač stoji, da li kupac želi vidjeti ime dostavljača), a interaktivni prototip se pravi za sate i testira s korisnicima. Pravi kod za istu provjeru košta dane, a promjena poslije je još skuplja.
1, , 1.. i 0..1? Šta označava puni romb?