Poglavlje 8: Arhitektura temeljena na komponentama
Priča za početak. Na istoj konferenciji u Garmischu 1968. godine, o kojoj smo čitali u poglavlju 1, programer Douglas McIlroy iz Bell Labsa održao je izlaganje pod naslovom „Masovno proizvedene softverske komponente”. Pitao je zašto softverska industrija nema ono što ima svaka druga industrija: katalog standardnih dijelova. Proizvođač automobila ne pravi sam svaki vijak; kupi ga, po standardu, iz kataloga. McIlroy je zamišljao da će programeri birati gotove rutine iz porodica, prema preciznosti, robusnosti i brzini, i od njih sklapati programe. Skoro pola vijeka kasnije, 22. marta 2016, ta vizija se ostvarila na način koji niko nije očekivao. Programer Azer Koçulu povukao je sve svoje pakete iz registra npm, u kojem programeri JavaScripta dijele komponente. Među njima je bio i left-pad, funkcija od jedanaest redova koja dopunjava tekst razmacima s lijeve strane. Ispostavilo se da od nje, preko lanca drugih paketa, zavise popularni alati, i gradnja hiljada projekata širom svijeta odjednom je počela padati. Registar je paket vratio za nekoliko sati i promijenio pravila povlačenja. Katalog dijelova je stvaran, ali je donio i novo pitanje: koliko zaista znamo o dijelovima od kojih je naš proizvod sastavljen?
U poglavlju 7 izabrali smo arhitekturu DeliveryApp 2.0: modularni monolit s jasnim granicama između narudžbi, dostave, plaćanja i obavještenja. Ovo poglavlje uzima te dijelove ozbiljno i pravi od njih komponente: dijelove s ugovorom, verzijom i vlastitim životom. Prvi dio objašnjava ideju programskog inženjerstva temeljenog na komponentama, odlike komponente, interfejse, koheziju i povezanost. Drugi dio daje principe i smjernice za dizajn komponenata, pokazuje kako se komponenta pravi kao paket sa semantičkom verzijom, i govori o rizicima ponovne upotrebe, od Ariane 5 do left-pada.
Literatura. Osnovna literatura predmeta:
- I. Sommerville: Software Engineering, 10th ed., Pearson, 2016 (poglavlje 16).
- C. Szyperski: Component Software, 2nd ed., Addison-Wesley, 2002.
- R. C. Martin: Clean Architecture, Prentice Hall, 2017 (dio o principima komponenata).
Riječi ovog poglavlja.
- Komponenta – samostalna jedinica softvera s jasnim interfejsom, koja se isporučuje nezavisno i sklapa s drugim komponentama.
- CBSE (component-based software engineering) – razvoj softvera sklapanjem gotovih i vlastitih komponenata.
- Ponuđeni interfejs – operacije koje komponenta nudi drugima.
- Zahtijevani interfejs – operacije koje komponenta traži od okoline da bi radila.
- Ugovor – precizan opis interfejsa: ulazi, izlazi, greške, uslovi.
- Kohezija – koliko dijelovi unutar komponente pripadaju zajedno.
- Povezanost (coupling) – koliko komponenta zavisi od drugih.
- Paket – komponenta spremna za instalaciju iz registra (pip/PyPI, NuGet, npm).
- Semantičko verzioniranje – verzija oblika glavna.sporedna.zakrpa s tačno određenim značenjem.
- Tranzitivna zavisnost – zavisnost moje zavisnosti.
- SBOM (software bill of materials) – spisak svih komponenata od kojih je proizvod sastavljen.
Ciljevi poglavlja. Nakon poglavlja možete: objasniti ideju CBSE i njene koristi; navesti odlike komponente po Szyperskom; razlikovati ponuđeni i zahtijevani interfejs i nacrtati UML dijagram komponenti; objasniti koheziju i povezanost; objasniti principe REP, CCP, CRP, ADP, SDP i SAP prostim riječima; primijeniti smjernice za dizajn komponente; napraviti Python paket sa semantičkom verzijom i reći kad se mijenja koji broj; objasniti rizike ponovne upotrebe i šta je SBOM.
Plan poglavlja – Predavanje 8: dva časa teorije i jedan čas dopunske prakse
| Čas | Sadržaj | Na času |
|---|---|---|
| Teorija 1 | 8.1–8.4 CBSE, odlike, interfejsi, kohezija i povezanost | Lego kocka i utičnica; dijagram komponenti DeliveryApp |
| Teorija 2 | 8.5–8.8 Principi, smjernice, provođenje, rizici | Koja je sljedeća verzija: 1.1.0 ili 2.0.0? |
| Dopunska praksa | Paket deliveryapp-dostava sa semantičkom verzijom |
pip install . i tri testa |
Dio 1 – Šta je komponenta
8.1 Ideja programskog inženjerstva temeljenog na komponentama
Lego kocke su najbolja slika komponente. Svaka kocka ima standardne čepiće (interfejs), pa se svaka može spojiti sa svakom, bez obzira na to ko ju je napravio i kada. Iz istih kocki prave se kuća, auto i svemirski brod. Niko ne pravi kocke iznova za svaku igračku.
Programsko inženjerstvo temeljeno na komponentama (CBSE) prenosi tu ideju u softver: proizvod se sklapa od komponenata, a ne piše od nule. Dio komponenata tim pravi sam (komponenta za obračun dostave), a dio uzima gotove (biblioteka za heširanje lozinki, okvir za web, klijent za sistem plaćanja).
Koristi:
- Brži razvoj – ne piše se ono što već postoji i radi.
- Pouzdanost – komponenta koju koriste hiljade projekata već je „istestirana” u praksi.
- Zamjenjivost – komponenta s istim interfejsom može se zamijeniti boljom.
- Podjela rada – svaki tim odgovara za svoje komponente.
Danas je CBSE svakodnevica: tipična web aplikacija sadrži više stotina paketa iz registara, a vlastitog koda je često manje od tuđeg.
Ukratko.
- CBSE sklapa proizvod od vlastitih i gotovih komponenata, kao igračku od Lego kocki.
- Koristi su brzina, pouzdanost, zamjenjivost i podjela rada.
- Tipičan proizvod danas sadrži više tuđeg nego vlastitog koda.
8.2 Odlike komponente
Clemens Szyperski je u knjizi Component Software dao definiciju koja se najčešće navodi: komponenta je jedinica sastavljanja s ugovorom definisanim interfejsima i samo eksplicitnim zavisnostima od okoline; može se isporučiti nezavisno i sklapati s drugim komponentama, i to od strane trećih lica.
Prevedeno na pet odlika:
| Odlika | Šta znači | deliveryapp-dostava |
|---|---|---|
| standardizovana | prati dogovoren model (npr. Python paket, .NET biblioteka) | Python paket s pyproject.toml |
| nezavisna | ne traži skrivene stvari od okoline; sve zavisnosti su zapisane | nema zavisnosti osim Pythona |
| sastavljiva | sav pristup ide kroz javni interfejs | obracunaj(grad, km, iznos) |
| isporučiva | može se instalirati i nadograditi posebno | pip install deliveryapp-dostava==2.0.0 |
| dokumentovana | interfejs je opisan tako da ga koristi neko ko ne vidi kod | opis u modulu i README |
Komponenta nije isto što i klasa. Klasa je jedinica koda; komponenta je jedinica isporuke. Komponenta obično sadrži više klasa, od kojih je većina skrivena, a vani se vidi samo interfejs.
Ukratko.
- Po Szyperskom, komponenta je jedinica sastavljanja s ugovorom i eksplicitnim zavisnostima, koja se isporučuje nezavisno.
- Odlike: standardizovana, nezavisna, sastavljiva, isporučiva, dokumentovana.
- Klasa je jedinica koda, a komponenta jedinica isporuke.
8.3 Interfejsi i ugovor
Komponenta ima dvije vrste interfejsa. Analogija je električni aparat:
- Ponuđeni interfejs je ono što aparat nudi: fen nudi topao zrak, dugme i dva stepena brzine.
- Zahtijevani interfejs je ono što aparat traži: utičnicu od 230 V.
Fen radi u bilo kojoj kući koja ima tu utičnicu; kući je svejedno koji fen je uključen. Tako i komponenta deliveryapp-narudzbe zahtijeva interfejse obracunaj(), naplati(), posalji() i udaljenost(), a ne zna i ne zanima je ko ih pruža.
flowchart LR
N["«komponenta»<br/>deliveryapp-narudzbe"]
D["«komponenta»<br/>deliveryapp-dostava 2.0.0"]
iD(("obracunaj()"))
D --- iD
N -.->|"zahtijeva"| iD

Ugovor je precizan opis interfejsa. Za obracunaj(grad, km, iznos) ugovor kaže:
- ulazi: oznaka grada (A, B, C), udaljenost u kilometrima, iznos artikala u centima;
- izlaz: objekat
Obracuns gradom, iznosom dostave u centima i kratkim opisom; - greške: nepoznat grad →
KeyError; udaljenost izvan zone ili iznos ispod 5,00 € →ValueError; - garancije: od 30,00 € dostava je 0; rezultat ne zavisi od vremena ni od stanja baze.
Ugovor se ne mijenja „usput”. Ako se mora promijeniti, mijenja se glavna verzija (8.6).
Ukratko.
- Ponuđeni interfejs je ono što komponenta nudi, zahtijevani ono što traži, kao aparat i utičnica.
- UML dijagram komponenti crta komponente, interfejse (kružići) i zavisnosti (isprekidane strelice).
- Ugovor opisuje ulaze, izlaze, greške i garancije.
8.4 Kohezija i povezanost
Dva pojma odlučuju da li je podjela na komponente dobra:
- Kohezija – koliko dijelovi unutar komponente pripadaju zajedno. Visoka kohezija: komponenta radi jednu stvar (obračun dostave). Niska kohezija: komponenta
raznou kojoj su obračun dostave, slanje SMS-a i izvoz u Excel. - Povezanost – koliko komponenta zavisi od drugih. Niska povezanost: dostava ne zna ništa o plaćanju. Visoka povezanost: promjena u plaćanju ruši dostavu.
Cilj je uvijek isti: visoka kohezija, niska povezanost. Analogija: dobro organizovana kuhinja ima ladicu za pribor i ladicu za začine (visoka kohezija), a da biste uzeli kašiku ne morate izvaditi začine (niska povezanost).

Na času. Tim predlaže komponentu
deliveryapp-alatiu kojoj bi bili formatiranje cijene (24,50 €), provjera e-mail adrese, računanje udaljenosti i slanje push obavještenja. Šta nije u redu i kako biste je razdvojili?
Ukratko.
- Kohezija je koliko dijelovi unutar komponente pripadaju zajedno; povezanost koliko komponenta zavisi od drugih.
- Cilj: visoka kohezija, niska povezanost.
- Komponenta „razno” ili „alati” je znak niske kohezije.
Provjeri se.
- Koja je razlika između klase i komponente? – Klasa je jedinica koda, a komponenta jedinica isporuke koja obično sadrži više klasa.
- Šta je zahtijevani interfejs? – Operacije koje komponenta traži od okoline da bi radila.
- Kakvu koheziju i povezanost želimo? – Visoku koheziju i nisku povezanost.
Dio 2 – Dizajn i provođenje
8.5 Principi dizajna temeljenog na komponentama
Robert C. Martin je opisao šest principa za komponente. Tri govore šta ide zajedno u komponentu, a tri kako komponente zavise jedna od druge.
Šta ide zajedno (kohezija):
| Princip | Prostim riječima | U DeliveryApp |
|---|---|---|
| REP – ponovna upotreba = izdanje | ono što se ponovo koristi mora imati verziju i izdanje | deliveryapp-dostava ima verziju 2.0.0 i bilješke o izdanju |
| CCP – zajedničko zatvaranje | u istu komponentu ide ono što se mijenja iz istog razloga i u isto vrijeme | tarife i obračun dostave mijenjaju se zajedno, pa su zajedno |
| CRP – zajednička ponovna upotreba | ne tjeraj korisnika da zavisi od onoga što ne koristi | dostava ne nosi kod za SMS, pa ko koristi dostavu ne mora instalirati SMS |
Kako zavise (povezanost):
| Princip | Prostim riječima | U DeliveryApp |
|---|---|---|
| ADP – bez ciklusa | zavisnosti ne smiju praviti krug | narudžbe → dostava, ali dostava ne zavisi od narudžbi |
| SDP – zavisi od stabilnog | zavisi od onoga što se rjeđe mijenja od tebe | ekran zavisi od narudžbi, narudžbe od tarife |
| SAP – stabilno je apstraktno | komponente od kojih mnogi zavise neka budu apstraktne (interfejsi) | ServisMapa je interfejs, a konkretna firma je zamjenjiva |
Zašto je ciklus opasan? Ako narudžbe zavise od dostave, a dostava od narudžbi, nijedna se ne može izgraditi, testirati ni isporučiti bez druge: dvije komponente su zapravo jedna, samo s dva imena. Ciklus se prekida tako što se zajednički dio izdvoji ili se uvede interfejs (inverzija zavisnosti).

Ukratko.
- REP, CCP i CRP odlučuju šta ide u komponentu: ono što se izdaje, mijenja i koristi zajedno.
- ADP, SDP i SAP odlučuju o zavisnostima: bez ciklusa, prema stabilnom, a stabilno neka bude apstraktno.
- Ciklus pretvara dvije komponente u jednu i prekida se izdvajanjem ili interfejsom.
8.6 Smjernice za dizajn komponenata
Praktične smjernice koje tim DeliveryApp koristi:
- Mali, jasan interfejs. Što manje javnih funkcija, to manje obećanja koja se moraju čuvati.
deliveryapp-dostavaizvozi tri imena:Obracun,obracunaj,gradovi. Sve ostalo (npr._Tarifa,_TARIFE) počinje donjom crtom i nije dio ugovora. - Nepromjenjivi objekti na granici. Komponenta vraća objekat koji se ne može mijenjati (
frozen=True), da pozivalac ne pokvari stanje komponente. - Jasne greške. Svaka greška ugovora ima svoj tip i poruku.
- Bez skrivenih zavisnosti. Ništa iz globalnih varijabli, okruženja ili baze, osim ako to piše u ugovoru.
- Dokumentacija i primjer. README s primjerom poziva od tri reda.
- Testovi uz komponentu. Komponenta se isporučuje sa svojim testovima.
- Semantička verzija. Verzija glavna.sporedna.zakrpa ima tačno značenje:
| Promjena | Koji broj raste | Primjer za deliveryapp-dostava |
|---|---|---|
| ispravka greške, ugovor isti | zakrpa | 1.1.0 → 1.1.1: ispravljeno zaokruživanje na 8,0 km |
| nova mogućnost, stari pozivi i dalje rade | sporedna | 1.0.0 → 1.1.0: dodane tarife po gradu, stari poziv dostava(km, iznos) radi za Grad A |
| promjena koja kvari stare pozive | glavna | 1.1.0 → 2.0.0: obracunaj() vraća Obracun umjesto broja; stari poziv uklonjen |
Kad DeliveryApp kaže da zavisi od deliveryapp-dostava>=2.0,<3, zna da će dobiti sve ispravke i nove mogućnosti verzije 2, a da ga ništa neće pokvariti bez upozorenja. Pravila semantičkog verzioniranja zapisana su na stranici semver.org.
Česta zabluda. „Verzija je samo broj za marketing.” U svijetu komponenata verzija je obećanje. Ako komponenta u zakrpi promijeni ugovor, hiljade projekata koji su vjerovali obećanju mogu se pokvariti preko noći.
Ukratko.
- Smjernice: mali interfejs, nepromjenjivi objekti na granici, jasne greške, bez skrivenih zavisnosti, dokumentacija, testovi.
- Semantička verzija: zakrpa za ispravku, sporedna za kompatibilnu novost, glavna za promjenu koja kvari stare pozive.
- Verzija je obećanje korisnicima komponente.
8.7 Provođenje dizajna komponenata
Kako tim DeliveryApp od dijela koda pravi komponentu, korak po korak:
- Prepoznati kandidata. Dio s visokom kohezijom koji se mijenja iz jednog razloga i koji bi mogao trebati i drugima: obračun dostave (trebaće ga i budući proizvod za dostavu iz apoteka).
- Definisati ugovor. Ponuđeni interfejs (
obracunaj), zahtijevani (nijedan), greške, garancije. - Izdvojiti kod. Premjestiti kod iza interfejsa, sakriti sve ostalo.
- Napisati testove komponente. Prije nego što je drugi počnu koristiti.
- Spakovati. Python:
pyproject.tomls imenom i verzijom; C#: projekat biblioteke (.csproj) i NuGet paket. - Objaviti. U javni registar (PyPI, NuGet, npm) ili u interni registar firme.
- Održavati. Bilješke o izdanju, semantičke verzije, ispravke sigurnosnih problema.
Paket deliveryapp-dostava (primjeri/paket/deliveryapp-dostava) ima ovu strukturu:
deliveryapp-dostava/
├── pyproject.toml
├── src/deliveryapp_dostava/__init__.py
└── tests/test_komponenta.py
pyproject.toml opisuje paket:
[project]
name = "deliveryapp-dostava"
version = "2.0.0"
description = "Obračun dostave po tarifi grada (komponenta proizvoda DeliveryApp 2.0)"
requires-python = ">=3.10"
A ponuđeni interfejs izgleda ovako:
@dataclass(frozen=True)
class Obracun:
grad: str
dostava: int # centi
opis: str
def obracunaj(grad: str, km: float, iznos: int) -> Obracun:
t = _TARIFE.get(grad)
if t is None:
raise KeyError(f"nepoznat grad: {grad}")
if km < 0 or km > t.max_km:
raise ValueError("adresa je izvan zone dostave")
if iznos < MIN_NARUDZBA:
raise ValueError("iznos je manji od najmanje narudžbe")
if iznos >= BESPLATNA_OD:
return Obracun(grad, 0, "besplatna dostava od 30,00 €")
dodatni = math.ceil(max(0, km - t.ukljuceno_km))
return Obracun(grad, t.osnovna + t.po_km * dodatni, f"osnovna + {dodatni} km")Nakon pip install . u čistom virtuelnom okruženju, poziv obracunaj("B", 4.2, 2150) vraća Obracun(grad='B', dostava=380, opis='osnovna + 3 km'), a tri testa komponente prolaze.
U C# isti posao radi projekat biblioteke: dotnet new classlib -n DeliveryApp.Dostava, verzija u .csproj (<Version>2.0.0</Version>), pakovanje sa dotnet pack i objava u NuGet registar. Javne su samo klase i metode označene sa public; ostalo je internal i ne vidi se izvan komponente.
Ukratko.
- Provođenje: prepoznati kandidata, definisati ugovor, izdvojiti kod, testovi, spakovati, objaviti, održavati.
- Python komponenta je paket s
pyproject.toml; C# komponenta je biblioteka i NuGet paket.- Sve osim ponuđenog interfejsa je sakriveno (donja crta u Pythonu,
internalu C#).
8.8 Ponovna upotreba i njeni rizici
Ponovna upotreba štedi vrijeme, ali komponenta koja je radila u jednom okruženju ne mora raditi u drugom, a svaka tuđa komponenta je i tuđi rizik.
Iz stvarnog svijeta. Raketa Ariane 5 eksplodirala je na prvom letu, 4. juna 1996, oko četrdeset sekundi nakon polijetanja. Softver za inercijalni navigacioni sistem preuzet je s rakete Ariane 4, gdje je godinama radio bez greške. Ariane 5 je, međutim, brža, pa je jedna vrijednost horizontalne brzine postala prevelika za pretvaranje iz 64-bitnog decimalnog broja u 16-bitni cijeli broj. Pretvaranje nije bilo zaštićeno, sistem je prijavio grešku, i raketa je skrenula s putanje i raspala se. Istražna komisija je utvrdila da funkcija koja je izazvala grešku Ariani 5 nakon polijetanja nije ni bila potrebna. Komponenta je bila ispravna za svoj stari ugovor, a niko nije provjerio da li taj ugovor važi u novom okruženju.
Rizici ponovne upotrebe i odgovori:
| Rizik | Primjer | Odgovor |
|---|---|---|
| komponenta ne odgovara novom okruženju | Ariane 5 | provjeriti ugovor i granice u novom okruženju; testovi s novim vrijednostima |
| komponenta nestane | left-pad, 2016 | interni registar ili keš paketa; zaključane verzije |
| ranjivost u komponenti | ranjivost u biblioteci Log4j otkrivena u decembru 2021, koja je pogodila ogroman broj Java sistema | praćenje ranjivosti (npr. Dependabot), brza nadogradnja |
| zlonamjerna komponenta | paket s imenom sličnim popularnom, s ubačenim kodom | provjera izvora i imena, potpisani paketi |
| tranzitivne zavisnosti | moja zavisnost zavisi od stotinu drugih | spisak svih zavisnosti, redovna provjera |
| licenca | biblioteka s licencom koja traži objavu vlastitog koda | provjera licenci prije uključivanja |
Zaključavanje verzija. Fajl s tačnim verzijama svih zavisnosti, uključujući tranzitivne (npr. requirements.txt s ==, poetry.lock, packages.lock.json u .NET-u), garantuje da se proizvod sutra gradi od istih dijelova kao danas.
SBOM (software bill of materials) je deklaracija sastava proizvoda, kao spisak sastojaka na pakovanju hrane: sve komponente, njihove verzije i licence. Kad se objavi nova ranjivost, firma sa SBOM-om za minut zna da li je pogođena. Zakoni o sajber sigurnosti (npr. evropski Akt o sajber otpornosti) sve češće traže takav spisak za proizvode koji se prodaju.
Ukratko.
- Komponenta ispravna u jednom okruženju može biti pogrešna u drugom, kao kod Ariane 5.
- Rizici: drugo okruženje, nestanak, ranjivost, zlonamjerni paket, tranzitivne zavisnosti, licence.
- Odgovori: provjera ugovora, zaključane verzije, interni registar, praćenje ranjivosti, provjera licenci.
- SBOM je deklaracija sastava proizvoda.
Provjeri se.
- Šta kaže princip ADP? – Zavisnosti između komponenata ne smiju praviti ciklus.
- Komponenta dobija novu funkciju, a stari pozivi rade. Koja verzija slijedi nakon 1.1.0? – 1.2.0.
- Šta je SBOM? – Spisak svih komponenata, verzija i licenci od kojih je proizvod sastavljen.
Dopunska praksa – paket deliveryapp-dostava
Cilj je napraviti komponentu kao Python paket, instalirati je i promijeniti verziju po pravilima. Trajanje: jedan čas.
Korak 1 – Paket
Kopirajte folder primjeri/paket/deliveryapp-dostava u svoj repozitorij. Napravite virtuelno okruženje i instalirajte paket:
python -m venv .venv
.venv\Scripts\activate (Linux/macOS: source .venv/bin/activate)
pip install -e .
python -c "import deliveryapp_dostava as z; print(z.__version__, z.obracunaj('B', 4.2, 2150))"
pip install pytest
pytest tests
Korak 2 – Zakrpa
Pronađite ili zamislite ispravku koja ne mijenja ugovor (npr. bolja poruka greške). Napravite je, promijenite verziju u pyproject.toml i __init__.py na 2.0.1 i dopišite stavku u CHANGELOG.md.
Korak 3 – Sporedna verzija
Dodajte Grad D (2,00 € do 4 km, 0,40 € po km, najdalje 15 km) i test za njega. Stari pozivi rade, pa je nova verzija 2.1.0. Provjerite: koliko je dostava za N-1001 (21,50 €, 4,2 km) u Gradu D?
Korak 4 – Glavna verzija (samo zapis)
U CHANGELOG.md opišite promjenu koja bi tražila 3.0.0 (npr. iznos se vraća kao Decimal u eurima umjesto int u centima) i šta korisnici komponente moraju promijeniti.
Korak 5 – SBOM (opcionalno)
Pokrenite pip list --format=freeze u virtuelnom okruženju i sačuvajte izlaz kao docs/sastav.txt. To je najjednostavniji spisak sastava; profesionalni alati prave SBOM u standardnim formatima (CycloneDX, SPDX).
Rezultat: paket koji se instalira, testovi koji prolaze, verzija 2.1.0 i CHANGELOG.md s tri stavke.
Vježbe
Vježba za studenta 1 – verzije.
Komponenta deliveryapp-placanje je u verziji 3.4.2. Koja je sljedeća verzija za: a) ispravku greške u zaokruživanju; b) novi način plaćanja (stari rade); c) uklanjanje starog načina plaćanja „pouzećem”; d) ispravku pravopisne greške u poruci?
Rješenje. a) 3.4.3; b) 3.5.0; c) 4.0.0 (stari pozivi prestaju raditi); d) 3.4.3 ako se poruka ne smatra dijelom ugovora (ako je pozivaoci porede kao tekst, sigurnije je smatrati je promjenom ugovora).
Vježba za studenta 2 – kohezija i povezanost.
Komponenta deliveryapp-narudzbe direktno čita tabelu tarifa iz baze da bi izračunala dostavu, umjesto da pozove deliveryapp-dostava. Šta je loše i šta predlažete?
Rješenje. Povezanost je visoka i skrivena: narudžbe zavise od unutrašnje strukture podataka dostave, pa svaka promjena tabele kvari narudžbe, a pravilo obračuna postoji na dva mjesta (krši DRY i CCP). Prijedlog: narudžbe pozivaju samo ponuđeni interfejs obracunaj(); tabela tarifa je privatna stvar komponente dostave.
Vježba za studenta 3 – ciklus.
deliveryapp-narudzbe zavisi od deliveryapp-obavjestenja (šalje poruku o promjeni stanja), a deliveryapp-obavjestenja zavisi od deliveryapp-narudzbe (čita detalje narudžbe za tekst poruke). Kako prekinuti ciklus?
Rješenje. Npr. narudžbe objavljuju događaj „stanje promijenjeno” sa svim podacima potrebnim za poruku (broj, novo stanje, telefon), preko reda poruka ili interfejsa koji pripada narudžbama. Obavještenja reaguju na događaj i više ne zovu narudžbe. Zavisnost ide samo u jednom smjeru (ADP).
Vježba za studenta 4 – ponovna upotreba.
Tim želi u DeliveryApp uključiti besplatnu biblioteku za crtanje mape koju je napisao jedan programer i koja nije ažurirana tri godine. Napišite pet pitanja koja tim treba postaviti prije odluke.
Rješenje. 1) Kakva je licenca i da li dozvoljava upotrebu u komercijalnom proizvodu? 2) Ima li poznatih ranjivosti i ko ih ispravlja? 3) Od čega ona zavisi (tranzitivne zavisnosti)? 4) Šta radimo ako nestane ili prestane raditi – možemo li je držati u internom registru ili zamijeniti? 5) Da li njen ugovor odgovara našim uslovima (broj tačaka na mapi, mobilni uređaji, brzina)?
Sažetak u pet rečenica
- McIlroy je 1968. sanjao katalog softverskih komponenata, a left-pad 2016. pokazao je da taj katalog postoji, ali i da od jedanaest redova tuđeg koda mogu zavisiti hiljade projekata.
- Komponenta je jedinica sastavljanja i isporuke s ugovorom, ponuđenim i zahtijevanim interfejsom i eksplicitnim zavisnostima, a dobra podjela ima visoku koheziju i nisku povezanost.
- Principi REP, CCP i CRP odlučuju šta ide zajedno u komponentu, a ADP, SDP i SAP traže zavisnosti bez ciklusa, prema stabilnim i apstraktnim komponentama.
- Komponenta se pravi kao paket (pip, NuGet) s malim interfejsom, testovima i semantičkom verzijom, gdje zakrpa znači ispravku, sporedna verzija kompatibilnu novost, a glavna promjenu koja kvari stare pozive.
- Ponovna upotreba nosi rizike, od drugog okruženja (Ariane 5) do nestanka, ranjivosti i licenci, pa se verzije zaključavaju, zavisnosti prate, a sastav proizvoda vodi u SBOM-u.