Danijel Ščukanec
Autor:
Danijel Ščukanec

Arhitekt rješenja

Overengineering ili kada stvari krenu po zlu

Svatko tko se bavio softverskim dizajnom prije ili kasnije naišao je na knjigu „Design Patterns: Elements of Reusable Object-Oriented Software“ čiji su autori Erich Gamma, Ralph Johnson, Richard Helm i John Vlissides poznatiji pod imenom „Gang of four". Objavom ove knjige u softverskoj je industriji na popularnosti dobilo nešto što znamo pod pojmom oblikovni obrasci. 

Da li oblikovni obrasci znače i dobar dizajn?

Oblikovni obrasci sadrže brojne korisne ideje za dizajniranje informatičkih sustava. Oni predstavljaju fleksibilan, sofisticiran i elegantan način uspostavljanja objektno-orijentiranog dizajna. Obrasci također pomažu pri razvoju fleksibilnih frameworka te izgradnji robusnih i proširivih informatičkih sustava.  Na temelju rečenog trebali bi doći do naizgled logičnog zaključka da se kvalitetnim softverskim inženjerom postaje poznavanjem čim većeg broja oblikovnih obrazaca. Međutim, da li je to točno? Odgovor na ovo pitanje je negativan. Povijest je pokazala da dobri poznavatelji oblikovnih obrazaca vrlo često većinu svojeg programskog koda oblikuju kroz obrasce pri tom ne uzevši u obzir stvarnu kompleksnost sustava, potrebu za budućim promjenama, funkcionalne i nefunkcionalne zahtjeve, rokove implementacije i slično.

Overengineering

Što zapravo predstavlja pojam overengineering? Kada programski kod bude fleksibilniji ili sofisticiraniji nego što je potrebno kaže se da je programski kod overengineeran. Softverski inženjeri često proizvode takav programski kod kada misle da znaju buduće korisničke zahtjeve. Oni smatraju da je pametnije napraviti fleksibilniji i sofisticiraniji programski kod sada kako bi u budućnosti bilo jednostavnije raditi promjene nad sustavom. Takva se odluka čini razumnom jedino ako su vidoviti. No, ako su predviđanja pogrešna uzalud je potrošeno vrijeme i novac. Nije neuobičajena praksa da se potroše dani pa čak i tjedni za podešavanje nepotrebno fleksibilnog i sofisticiranog softvera dok se istovremeno smanjuje vremenski okvir za implementaciju novih funkcionalnosti i popravak pronađenih grešaka.

U praksi sam se često susretao s primjerima koji su poslovnu problematiku cjelokupnog sustava pokušali svesti pod zajednički naziv. Primjerice, na nekim sustavima koriste se metode repozitorija koje kao ulazni parametar primaju lambda izraze koji se izravno prosljeđuju nekom OR maperu. Unatoč tome što se  to u početku čini kao dobra ideja kako se sustav sve više gradi tako i nastaje sve više iznimaka zbog kojih raste potreba za uvođenjem dodatnih metoda za dohvaćanje podataka. Rješenje je da se za svaku vrstu dohvata koristi posebna metodu koja kroz imenovanje jasno daje do znanja što iza nje stoji. Time se ujedno pruža mogućnost jediničnog testiranja pojedinih dohvata podataka što korištenjem lambda izraza nije bilo moguće. Još jedan primjer koji bih volio istaknuti odnosi se na pokušaj stvaranja ponovno iskoristivih UI kontrola kada imamo poglede sa sličnim podacima, ali iza kojih stoji drugačija poslovna problematika. S vremenom takve kontrole postaju „nakupina if-ova“ s obzirom na to da korisnik kroz svoje zahtjeve stvara sve veću razliku u podacima između dvaju ili više različitih poslovnih problematika. Takve je forme već u početku najbolje razdvojiti u zasebne poglede, a kontrole održavati na razini polja za unos ili pregled podataka.

Produktivnost

Koja je sudbina programskog koda proizvedenog radi predviđenih potreba koje se nikad ne materijaliziraju? On se nikad ne ukloni. Jedan je od mogućih razloga što je prošlo dosta vremena i to više nije lako izvedivo. No, još gori razlog može biti da se i dalje smatra da će taj suvišni programski kod jednom postati potreban. Stavivši sve moguće razloge po strani, kako se previše fleksibilan i nepotrebno sofisticiran kod počinje gomilati u sustavu tako se tim programera, pogotovo novopridošlica, mora snalaziti u programskom kodu koji je znatno složeniji od stvarnih potreba.  Programski kod utječe na produktivnost jer kada netko naslijedi projekt mora potrošiti suviše vremena kako bi upoznao dizajn sustava do te razine da se uopće osjeća sposobnim samostalno proširivati i održavati sustav koji je dizajniran na takav način.

Overengineering se najčešće pojavi neprimjetno. Softverski inženjeri nisu ni svjesni što čine dok nije prekasno. Prve znakove obično primijeti menadžment zbog pada timske produktivnosti, ali rijetki znaju da glavnu ulogu u tome ima overengineering.

Fokus na bitno

Kvalitetni i iskusni softverski arhitekti znaju da svoj fokus moraju usmjeriti s oblikovnih obrazaca na bit problema odnosno na funkcionalne i nefunkcionalne zahtjeve koji su u tome trenutku usuglašeni. Mnogim softverskim inženjerima nije jednostavno promijeniti dosadašnji način razmišljanja jer su potrošili mnogo svojeg vremena učeći oblikovne obrasce s ciljem da postanu bolji u svojem poslu. Uloga arhitekta je automatizacija i optimizacija postojećih poslovnih procesa, a ne priprema sustava za neke buduće poslovne procese koji sada ne postoje niti su korisniku potrebni. Naravno, to ne znači da ne treba predlagati nove poslovne procese pogotovo ako bi olakšali poslovanje ili izradu informatičkog sustava. Takvi su prijedlozi uvijek dobro došli, ali moraju biti realni i usuglašeni sa svim stranama koje sudjeluju u projektu kako bi se definirao novi opseg i plan projekta. 

Nakon pročitanog mnogi se vjerojatno pitaju kako je moguće da su oblikovni obrasci negativna pojava i uzrok overengineeringa. Nisu. Upravno suprotno jer ako se pametno i pravilno koriste tada daju veću vrijednost izgrađenom sustavu.

Underengineering

To nas vodi do drugog dijela priče koji govori o tome da unapređenje programskog koda ujedno znači i naučiti kako izbjeći underengineering. Underengineering znatno je češća pojava od overengineeringa. Underengineering predstavlja razvojni proces brzog dodavanja novih funkcionalnosti u sustav pri čemu se zbog nedostatka vremenskih ili ljudskih resursa ne pazi na dobar dizajn sustava, a time i kvalitetu programskog koda. Naravno, programeri bi vrlo rado htjeli unaprijediti takav kod jer su svjesni njegove nekvalitete, ali nemaju vremena za to. Ponekad kada i imaju vremena prihvate savjet menadžera ili korisnika da će projekt biti kompetitivniji i uspješniji ako se ne dira ono što nije pokvareno. No, uvijek se pokaže da taj savjet ne stoji i to već u bliskoj budućnosti. Naime, kad-tad dođe do sve većeg usporavanja procesa razvoja softvera.

Često sam se imao priliku sresti u situacijama gdje je zbog potreba ubrzanog razvoja stradala implementacija grafičkog dizajna aplikacije što ponekad dovede do točke gdje izmjena stila u CSS datoteci na jednoj stranici ispravlja problem dok na nekoliko drugih stranica uzrokuje problem koji nije postojao. Što se tiče pozadinskog dijela aplikacije često se javlja problem lošeg hvatanja iznimaka zbog kojeg se po cijelom sustavu ponavlja „try-catch fraza“. Hvatanje iznimki mora se postaviti na centralizirano mjesto kako bi programski kod ostao čist i bio fokusiran na problematiku, a ne na pojavu mogućih iznimki.

Evolucijsko dizajniranje

Evolucijsko dizajniranje je način dizajniranja softvera koji stvara ravnotežu između dviju suprotnih strana: overengineeringa i underengineeringa. Sastoji se od dvije prakse ekstremnog programiranja: programiranja pomoću testova (engl. test-first programing) i nemilosrdnog refaktoriranja (engl. merciless refactoring). Te dvije prakse znatno unaprjeđuju proces razvoja softvera stvarajući dobro dizajnirane sustave koji su isporučeni na vrijeme.

Programiranje pomoću testova predstavlja uspješnu evoluciju u načinu programiranja kroz tzv.  sokratski dijalog (Kent Beck). Najprije se napiše programski kod testa kako bi se sustavu postavilo pitanje, a tek se nakon toga piše programski kod funkcionalnosti unutar sustava kako bi se odgovorilo na to pitanje. Taj se dijalog nastavlja sve dok zahtjev koji je postavljen pred programera nije isprogramiran. Takav način programiranja nastoji usredotočiti programera na implementaciju jednog manjeg dijela ponašanja sustava koje ispravno radi prije nego što se podigne na višu sofisticiraniju razinu ako za to postoji potreba.

Nemilosrdno refaktoriranje dio je procesa evolucijskog dizajniranja. Refaktoriranje je transformacija programskog koda koja ne mijenja ponašanje sustava. Martin Fowler ga definira kao promjenu unutarnje strukture softvera koja ga čini lakšim za razumijevanje i izmjenu, a da se pri tome nije promijenilo promatrano ponašanje. Fowler je također definirao prirodnu vezu između oblikovnih obrazaca i refaktoriranja. Oblikovni obrasci su ono gdje želimo biti, a refaktoriranje je način kako doći do tog stanja iz trenutnog stanja. Stoga oblikovni obrasci predstavljaju cilj refaktoriranja odnosno strukture koje su rezultat refaktoriranja.

Potrebno je naučiti evoluirati vlastiti dizajn

Potaknuti iskustvima sa overengineeringom i underengineeringom  u mojoj tvrtki provode se određene prakse kako bi se takve situacije izbjegle. U svakom timu mora postojati najmanje jedan stariji programer koji se suočio sa overengineeringom i underengineeringom pa svojim iskustvom uklanja takve pojave. Svaka veća promjena nad sustavom zahtijeva u najmanju ruku dogovor na razini projektnog tima, a po potrebi i razgovor s timom arhitekata koji koordiniraju nad svim projektima u tvrtki. U svakom projektnom timu postoje poslovni analitičari koji sastavljaju funkcionalnu specifikaciju u suradnji s korisnicima koja kasnije služi programerima za upoznavanje poslovnih procesa. Naime, bez potpunog poznavanja poslovnih procesa nije moguće izraditi kvalitetno rješenje.  Također, nije moguće objaviti promjenu koda sve dok izmjene nije pregledao barem jedan programer.

Poznavanje dobrih razloga za refaktoriranje koda u oblikovni obrazac mnogo je vrijednije nego poznavanje samog oblikovnog obrasca. Kako bi postali bolji softverski inženjeri kvalitetnije je proučavati evoluciju kvalitetnih dizajna softvera nego dizajn po sebi. Strukture koje su rezultat evolucije mogu uvelike pomoći, ali ne znajući zašto su evoluirale u takav dizajn postoji veća vjerojatnost da će se pogrešno iskoristiti ili da će se projekt overengineerat. Ako želimo dobiti najveću vrijednost iz oblikovnih obrazaca moramo ih promatrati u kontekstu refaktoriranja, a ne ponovno iskoristivih elemenata. Naučivši evoluirati vlastiti dizajn postajemo bolji softverski inženjeri i smanjujemo količinu posla koji over ili under engineeramo

Popularne teme
.NET ABAP ADFS Agile Always On Anemic Model Angular Azure Backbone benchmark BI BI projekti Bootstrap building people business inteligence Business Intelligence Change Chrome CI CITCON Claims compile Continuous Delivery continuous deployment Continuous Integration CSR d3js data data visualization Data visualization alati DDD dekompozicija dependency injection dinamička forma dinamički parametri dinamički query distribuirani razvoj Domain-Driven design DOP društvena odgovornost edge-based video analytics Eliminating waste enkapsulacija enterprise razvoj softvera ERP ETL Excel FIORI Frontend game Geopackage GPKG GIS Git Groovy heat map HICCUPS Hichert HTML IBCS interoperability invision IoT IPSO izvještavanje java JavaFX Javascript Jazz Build Engine JBE Jenkins jquery jqueryui jsfiddle JVM Kaizen Kanban king KING ICT Kingovci Knockout kvaliteta lambde leadership Lean legacy code M language Management Maven Metodologija microservices Microsoft mobile Mobility mockups moć monday game NetWeaver network nodejs oblikovni obrasci OGC OKR open source optimizacija organizacija organizacijska struktura OutOfMemoryError outsourcing overengineering paginacija Performance performanse PERT PMI PMP; Agile; Project management; Scrum; KING ICT; razvoj; metodologija podatkovni skup pouzdanost Power BI Power Map Power Pivot Power Query Power View pretraga proces procjena Product Owner programming proizvod Project manager projektni plan radar Rational Team Concert razvoj tima refaktoriranje Release resize responsive charts REST retrospektiva Rich-Domain model Roko Roić rolling wave planning RTC SAP scale scatterplot chart Scrum scrum team scrum tim service boundaries single responsibility principle Single Sign-On smart metering SoapUI social responsibility softver Software software prototyping Software Testing Club Spring Boot SQL standard sustav videonadzora svg tdd Team team building team development Team Foundation Server tech tehnologije terminski plan Testing tim timesheet timovi Toggl.com touch transakcijski nadzor tražilica underengineering unit testing Uspjeh Visual Studio vodstvo vodstvo leadership moć društvena odgovornost DOP social responsibility CSR vođenje projekata WBS Web Zagreb STC

PRIJAVA NA NEWSLETTER

Najnovije novosti iz ICT svijeta