HelloWorld logo
29.07.2022. ·
7 min

Spajanje komponenata (web) aplikacija

Siniša Nimčević Siniša Nimčević

Kada govorimo o spajanju komponenata neke aplikacije, dotičemo se vrlo rudimentarnog dela softverske arhitekture. Možda su negde gore "oblaci", redirekcije i redis keševi, ali u dnu svega je izvorni kod koji mi gledamo tokom održavanja i nadogradnje sistema.

Ovaj, najniži nivo arhitekture je mesto gde se često pravi ključna razlika - da li će popravka (ili nadogradnja) trajati satima, danima ili nedeljama. Arhitekturu softvera formiraju suprotstavljene sile koje mogu biti tehničke i političke (dogovori, zahtevi i sve ono što nije tehnička prepreka). Tu negde u tenziji između upotrebljivosti, brzine rešenja i logičke organizacije baze koda leži naša arhitektura, koju biju ti tehnički i politički talasi koji su pre svega nestalni (dinamični).

Odatle je većina starijih baza koda dobilo onaj pogani pridev "legacy", koji sa sobom nosi gomilu negativnih konotacija. Da bismo uticali na promenu u arhitekturi moramo jasno i argumentovano da iznesemo svoje razmišljanje (prvi korak je naravno unutrašnja prepirka sa samim sobom). Iako se velika većina spajanja komponenata radi "intuitivno" i "po osećaju", kada želimo da uvedemo promenu moramo rezonovati "iznad" tih subjektivnih argumenata, i ubediti i sebe i ostatak tima da postoji bolji način (ukoliko postoji). Popularni Robert C. Martin je napisao odličnu knjigu, koju bih uveo u obavezno čitanje za sve rastuće, i poodrasle programere - Čista Arhitektura.

Jasan kod, i Čista arhitektura su odlični naslovi prevedeni i na srpski jezik, dostupni u štampi, tako da je svaki medij od piraterije do kindle-a pokriven i izgovora nema. Moj članak će biti sažetak jednog poglavlja iz Čiste Arhitekture pa ću pokušati da napišem neku skraćenu verziju kroz prizmu mog iskustva, a za dublje znanje, ne mogu dovoljno preporučiti originalni naslov. 

 Principi spajanja komponenata

 

Osnovni principi spajanja komponenata su Princip acikličnih zavisnosti, Princip stabilnih zavisnosti i Princip stabilne apstrakcije. Svi ovi principi su zapravo koncepti koji su primenjivi na mnoštvo programskih jezika i aplikacija, stoga je korisno razumeti ih, i uzeti ih u obzir kada se bavimo kompleksnim problemima i nemamo "inspiracije" za bolje rešenje. 

Princip acikličnih zavisnosti

 

Često slučajno, možemo da napravimo ciklučnu strukturu unutar našeg "grafikona zavisnosti". Recimo da imamo 3 celine koda (A, B i C). Ukoliko C uvlači funkcionalnost iz B, a B uvlači funkcionalnosti iz A, imamo acikličan grafikon poznatiji kao DAG (Directed Acyclic Diagram). Dakle ne možemo napraviti "krug" i menjanjem B komponente utičemo samo na komponentu C, a nemamo nesvesnih uticaja na kod iz celine A. To je situacija A->B->C, a recimo da imamo A->B->C->A, lako možemo promeniti nešto u B, da bismo nadogradili C, i slučajno pokvariti nešto iz celine A. To je problem kod cikličnih zavisnosti koji ume da se provuče i na produkciju ukoliko nemamo adekvatnih testova i nismo svesni ove zavisnosti budući da je baza koda velika, a naš zadatak obuhvata samo jednu stranicu ili flow (kako to često biva).

Da bismo rešili A->B->C->A rebus, uvodimo interfejs D. Dakle i A i C će implementovati interfejs D, efektivno "potpisati ugovor da će imati taj i taj input, i taj i taj output" tako da one više ne zavise jedna od druge, nego su usmerene ka zajedničkom interfejsu D (koji kao apstrakcija prati OCP SOLID princip, ali o tome nešto kasnije). Ovakvo rešenje je pozajmljeno iz objektno orijentisanog programiranja - to je D iz poznatog SOLID-a - Dependency Inversion Principle. Ovi problemi možda zvuče apstraktno, ali kada je vaš projekat sastavljen iz mikrofrontendova ili mikroservisa koje održavaju različite kolege, ili čak različiti timovi, greške umeju da se potkradu. One su skoro pa neizbežne budući da dinamični zahtevi kreiraju prilike za komponente sa višekratnom upotrebom (DRY princip), i skoro je nemoguće isplanirati neke stvari u napred, budući da takve greške nastaju tek u razvoju, i samo razvoj aplikacije "oslobađa" sile pogodnosti izgradnje i održavanja sistema koje zauzvrat, prouzrukuje ove greške. Refaktorisanje je validan i potreban proces. Takođe, razlog zašto težimo ispunjenju Principa acikličnih zavisnosti su SRP (Single responsibility princip) i CCP (Common Closure princip) koji imaju jasan cilj, a to je izolacija promenljivosti. Dakle, menjam B, da bih ga prilagodio C i moje promene ne smeju da utiču na A. 

Princip stabilnih zavisnosti

 

Jednostavno rečeno zavisnosti treba usmeriti ka stabilnosti. Šta ovo znači za nas? Komponenta za koju očekujemo da će često trepti promene NE treba da zavisi od komponente koju je teško promeniti. Recimo da komponenta X, uvlači funkcionalnost iz komponenti A, B i C. Međutim komponenta X je stabilna jer ne izvozi svoju funkcionalnost, ona je nezavisna i potrebe za promenom komponente X dolaze samo iz nje same. Međutim, zamislimo komponentu Y, ona exportuje svoje funkcije u sisteme A, B i C. To čini Y nestabilnom jer zahtev za promenom može stići iz 3 mesta (promene unutar A, B ili C mogu da zahtevaju promenu Y). Postoji metrika (ne)stabilnosti zvana I (Instability) koja se izražava kao odnos gore spomenutih izlaznih i ulaznih zavisnosti i izražava se u koeficijentu između 0 i 1. Princip stabilnih zavisnosti nalaže da metrika I komponente mora biti veća od metrike I celina koje zavise od nje. Više o ovome ćemo videti u Principu stabilne apstrakcije. 

Princip stabilne apstrakcije

 

Komponenta treba da je onoliko stabilna koliko je apstraktna. Dakle ne želimo da neke dinamične odluke koje mogu (i nekad treba) da se lako izmene, zakucamo u rigidne, stabilne komponente. Težimo da su komponente "reusable", i da ih je lako menjati, međutim, neke privremeno "čvrste" odluke možemo staviti u apstraktne komponente. Ove stabilne i apstraktne komponente su uglavnom interfejsi i apstraktne klase (koje imaju neki "ozbiljniji" jezici) i one prate OCP princip iz SOLID ekipe - dakle otvoreni su za ekstenzije ali zatvoreni za promene. Takođe ovo se sve lepo uklapa u DIP (Dependency Inversion princip) pa smo rešili dve muve jednim udarcem. Tu stvari postaju zanimljive. Ponavljam, komponenta treba da je onoliko stabilna, koliko je apstraktna. Već smo spomenuli metriku (ne)stabilnosti zvanu I, i isto tako možemo izračunati metriku apstrakcije zvanu A, kao odnos broja običnih klasa i komponenata naspram broja apstraktnih klasa i interfejsa u nekoj celini (većoj komponenti) koja takođe ima vrednost između 0 i 1. Zapamptite I i A. 

 Odnos stabilnost i apstrakcije

 

Računanje metrika I i A neke logičke celine nam dozvoljava da je smestimo u koordiantni sistem gde su I i A ose, pa tako dobijamo jednu dijagonalu, koju Martin zove Glavna sekvenca. Ta dijagonala je mesto gde su stabilnost i apstrakcija jednake vrednosti, a iznad i ispod, u ekstremnim ćoškovima imamo Zonu bola i Zonu beskorisnosti. Zona bola sadrži komponente koje su toliko stabilne i konkretne da ih je vrlo bolno menjati i proširivati (kače mnoge druge komponente, a nema deljenih interfejsa koji garantuju acikličnost zavisnosti itd), a Zona beskorisnosti je rezervisana za apstrakcije koje niko ne importuje, dakle same po sebi ne rade ništa, niko ih ne koristi i to je mahom zaostali, "mrtav" kod. 

 Zaključak

Ja sam se dosta površno dotakao nečega, što bih voleo da čitaoci imaju na umu. Dakle, spajanje komponenata može da ima svoju metriku i svoju logiku, ne svodi se na "iskusniji kolega ovako radi pa ću da kopiram" i ne mora da se svodi na "meni je ovako lepše". Takođe, važna napomena - komponenta u ovom tekstu nije jedna React komponenta ili jedan fajl (iako nekad može biti), već jedna programska celina. Često su te celine nešto što održava jedan programer ili tim, te celine nekad nisu fizički izdvojeni repozitorijumi i baš interakcija između tih celina je najteža za održavanje i proširivanje.

Naposletku, verovatno nećete uzeti papir i olovku i računati I i A ili crtati grafikon zavisnosti, ali ukoliko se sretnete sa problemom, ovi principi su izuzetno koristan alat za rezonovanje i guranje rešenja u jednom ili drugom pravcu. Nadam se da ćete poslušati preporuku i pročitati spomenute knjige, pa ako jednog dana naletim na vaš kod, ne moram da se mučim da ga održavam i vice versa. 

Napiši komentar
Siniša Nimčević Siniša Nimčević

Nakon frilans rada u zlatno doba Elance platforme i putešestvija (i radnog iskustva) po Londonu, vraća se u rodnu Suboticu leta gospodnjeg 2018. Sa oko 10 godina iskustva u vebu, specijalizuje se u javaskriptu i piskara ne bi li dublje istražio neke teme i preneo znanje. Uvek otvoren za ćaskanje, savete i konstruktivnu kritiku.

Iz ove kategorije