Softverska Metrika: Uvod I Primer

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 89

Softwerska

Metrika:
Uvod i Primer
Dejan Stuparić
U ovoj knjizi uvešdu Vas na teritoriju softverskih
metrika, i pokazati Vam kako izgleda njihova
upotreba u praksi.

Dejan Stuparid
stuparic@hotmail.com,
stuparic.dejan@gmail.com
+381606638281

7/1/2010
Dejan Stuparid, Softverska metrika

Dejan Stuparid

Softverska Metrika
- Diplomski rad -

Novi Sad, 2010.

1
Dejan Stuparid, Softverska metrika

Predgovor
U ovom diplomskom radu govoridemo o softverskim metrikama, relacijama
među metrikama i defektima u izvornom kôdu. Ova tri koncepta su neraskidivo
povezana, i čine osnovu za proces poboljšanja ved završenih softverskih projekata.

Vrlo je česta pojava da se u velikim državnim ili privatnim sistemima koristi


softver koji je pisan pre čak nekoliko decenija. Osnovne odlike ovakvog softvera je
zastarelost programerskih paradgmi, i veliki troškovi održavanja. Takođe neretko se
dešava da je dokumentacija ovakvih softverskih sistema nepotpuna, ili je potpuno
nepostojeda.
Kao rešenje za ovakve i slične probleme figuriraju reinženjerstvo i
refaktorisanje kao konkretan oblik softverskog reiženjerstva. Naš zadatak u cilju
poboljšanja izvornog kôda posmatranog softvera je pronalaženje karakterističnih
defekata (disharmonija) i primena konkretnih reinženjerskih zahvata. Kao osnovni
alat na ovom polju koriste se softverske metrike.

Ovaj diplomski rad je podeljen u četiri bitna segmenta, a to su:


 Uvod
 Problemi u softverskim projektima (Defekti)
 Relacije među softverskim metrikama u praksi
 Zaključak

U segmentu Uvod pričamo uopšteno o pojmovima softverske metrike,


reiženjerstvo i refaktorisanje. Takođe tu možemo nadi tabelu svih metrika koje de biti
korišdene u daljem toku rada, kao i detaljno objašnjenje najbitnijih softverskih
metrika.
Segment Problemi u softverskim projektima (Defekti) je centralni sadržaj ovoga
rada. U ovom poglavlju navodimo karakteristične nedostatke u izvornom kôdu, kao i
načine za njihovo pronalaženje i otklanjanje. Sadržaj ovog poglavlja je u određenoj
meri inspirisan sjajnim delom Object-Oriented Metrics in Practice autora Michele
Lanza i Radu Marinescu. Naime korišdeno je njihov vid kalsifikacije problema u
softveru, uz modifikacije i dopune od strane autora ovog rada.
U poglavlju Relacije među softverskim metrikama u praksi prelazimo na
praktičnu demonstraciju refaktorisanja i primenu softverskih metrika. Korištidemo
izvorni kôd koji je za ovu svrhu napisao autor rada, koji namerno sadrži veliki broj
karakterističnih defekata, čije demo pronalaženje i uklanjanje demonstrirati.
U Zaključku smo sumirali celokupnu materiju navedenu u prethodnim
poglavljima, i time zaokružili jednu celinu posvedenu Softverskim Metrikama.

2
Dejan Stuparid, Softverska metrika

Svrha ovog rada je da na jednostavan i koncizan način pruži zainteresovanom


čitaocu uvid u korisnost softverskih metrika i njihov značaj. Posebna pažnja je
posvedena defektima u softveru, jer su oni glavno „pogonsko gorivo“ softverskih
metrika. Složidete se da nema naročite potrebe za postojanjem alata za ispitivanje
defekata u softveru, ukoliko defekta uopšte ni nema. Suština ovog rada nije u samim
softverskim metrikama, niti u njihovoj teorijskoj definiciji, ved u njihovoj praktičnoj
primeni u otklanjanju nedostataka u izvornom kôdu. Tako da dete videti veliki broj
praktičnih primera i delova izvornog kôda, a sve u svrhu jasnijeg i jednostavnijeg
shvatanja materije.

Motivacija za nastanak ovakvog rada je dugogodišnja zainteresovanost autora


za polje softverske metrike. Akumulacija određene količine znanja i informisanosti na
ovu temu stvorili su mogudnost za kreiranje diplomskog rada na temu Softverskih
Metrika.

Ovom prilikom zahvalio bih se majci Radici, ocu Ivanu, bratu Ivici i ostatku
familije koji su mi mnogo pomogli na psihološkom i materijalnom planu, i bez kojih
ovaj radi ne bi bio mogud. Zahvalio bih se cimerima Adamu i Milošu čije su
prijateljstvo i pomod bili od velikog značaja. Želeo bih da se zahvalim asistenkinji
Gordani Rakic čija je nesebična pomod i velika angažovanost umnogome zaslužna za
uspešnost ovog rada. Takođe zahvalio bih se mentoru Dr Zoranu Budimcu na korisnim
sugestijama u izradi rada, kao i ostalim članovima komisije. Posebno bih se zahvalio
celokupnom osoblju PMF-a u Novom Sadu što su mi boravak na studijama učinili
lepim i nezaboravnim.

3
Dejan Stuparid, Softverska metrika

Sadržaj

PREDGOVOR ........................................................................................................... 2
1. UVOD ............................................................................................................... 6
1.1. O MERENJU .............................................................................................................. 6
1.2. O MERENJU SOFTVERA ............................................................................................... 8
1.2.1. Problemi pri merenju softvera ...................................................................... 9
1.2.2. Ciljevi merenja softvera ................................................................................. 9
1.3. O METRIKAMA I GRANIČNIM VREDNOSTIMA ................................................................. 11
1.3.1. Broj Linija Kôda (LOC) .................................................................................. 15
1.3.2. Kružna Složenost (CYCLO)............................................................................ 17
1.3.3. Čvrsta Kohezija Klase (TCC) ......................................................................... 18
1.3.4. Ukupan Težinski Koeficijent (WMC) ............................................................ 19
1.3.5. Broj Metoda u Jednoj Klasi (NOM) .............................................................. 19
1.3.6. Broj Redefinisanih Metoda (NORM) ........................................................... 19
1.3.7. Dubina Stabla Nasleđivanja (DIT) ................................................................ 20
1.4. O DALJEM TOKU RADA.............................................................................................. 20
2. PROBLEMI U SOFTVERSKIM PROJEKTIMA (DEFEKTI) .......................................... 22
2.1. O REIŽINJERSTVU ..................................................................................................... 22
2.1.1. Reinženjerstvo u velikim kompanijama? ..................................................... 22
2.1.2. Zašto se reinženjerstvo često završava neuspehom? ................................. 24
2.1.3. O refaktorisanju ........................................................................................... 25
2.2. PROBLEMI U SOFTVERSKIM PROJEKTIMA (TEHNOLOŠKI DEFEKTI) ...................................... 25
2.3. DISHARMONIJE IDENTITETA ....................................................................................... 26
2.3.1. Pravila harmonije......................................................................................... 26
2.3.1.1. Pravilo proporcijalnosti veličine ........................................................... 26
2.3.1.2. Pravilo prezentacije identiteta ............................................................. 27
2.3.1.3. Pravilo implementacije funkcionalnosti ............................................... 27
2.3.2. Lista disharmonija........................................................................................ 28
2.3.2.1. Božija klasa (eng. God Class) ................................................................. 29
2.3.2.2. Ljubomorni Metod (eng. Feature Envy) ............................................... 35
2.3.2.3. Klasa Podataka (eng. Data Class) .......................................................... 36
2.3.2.4. Mudra Klasa (eng. Brain Class) ............................................................. 37
2.3.2.5. Mudri Metod (eng. Long Method)........................................................ 39
2.3.2.6. Znatno Dupliciranje (eng. Significant Duplication) ............................... 40
2.3.3. Rezime ......................................................................................................... 43
2.4. DISHARMONIJE SARADNJE ........................................................................................ 43
2.4.1. Pravila Harmonije ........................................................................................ 44
2.4.1.1. Pravilo saradnje .................................................................................... 44

4
Dejan Stuparid, Softverska metrika

2.4.2. Lista disharmonija........................................................................................ 45


2.4.2.1. Prevelika Intimnost (eng. Inappropriate Intimacy) .............................. 46
2.4.2.2. Operacija Sačma (eng. Shotgun Surgery) ............................................. 48
2.4.2.3. Divirgentna Promena (eng. Divergent Change).................................... 49
2.4.2.4. Lanac Delegiranja (eng. Delegation Chain) ........................................... 50
2.4.2.5. Posrednik (eng. Middleman) ................................................................ 51
2.4.3. Rezime ......................................................................................................... 53
2.5. DISHARMONIJE KLASIFIKACIJE .................................................................................... 54
2.5.1. Pravila Harmonije ........................................................................................ 54
2.5.1.1. Pravilo Proporcije.................................................................................. 54
2.5.1.2. Pravilo Prezentacije .............................................................................. 54
2.5.1.3. Pravilo Implementacije ......................................................................... 55
2.5.2. Lista Disharmonija ....................................................................................... 55
2.5.2.1. Prekid Tradicije (eng. Tradition Breaker) .............................................. 56
2.5.2.2. Odbijanje Roditeljskog Nasleđa (eng. Refused Parent Bequest) ......... 59
2.5.3. Rezime ......................................................................................................... 61
3. RELACIJE MEĐU SOFTVERSKIM METRIKAMA U PRAKSI ...................................... 63
3.1. O RELACIJAMA MEĐU METRIKAMA ............................................................................. 63
3.2. PRIMERI RELACIJA MEĐU METRIKAMA ......................................................................... 63
3.2.1. Odnos između metrike Broj linija kôda (LOC) i metrike Kružna Složenost
(CYCLO), na primeru disharmonija Mudra Klasa/Mudri Metod ........................... 64
3.2.2. Relacije između metrika Pristup Stranim Podacima, Lokacije Korišdenih
Atributa i Snabdevači Stranog Sadržaja (ATFD – LAA – FDP), na primeru
disharmonije Ljubomorni Metod .......................................................................... 73
3.2.3. Relacije između metrika Broj Redefinisanih Metoda, Broj Naslednika, i
Dubina Stabla nasleđivanja (NORM – NOC – DIT), na primeru disharmonije
Prekid Tradicije ...................................................................................................... 76
3.2.4. Analiza finalne verzije programa ................................................................. 84
4. ZAKLJUČAK ........................................................................................................ 87
5. LITERATURA ...................................................................................................... 88
BIOGRAFIJA.......................................................... ERROR! BOOKMARK NOT DEFINED.

5
Dejan Stuparid, Softverska metrika

1. Uvod
1.1. O merenju
Od merenja zavisi naš odnos prema pojmovima i pojavama koje susredemo
tokom svakodnevnice. Ekonomska merenja određuju nivoe cena i plata. Merenje u
radarskim sistemima omogudava nam da vidimo letelicu iako nam je direktan vidik
opstruisan. Merenje doktorima omoguduje da pravilno uspostave dijagnozu. Merenje
atmosferskih pojava je osnova za uspešnu vremensku prognozu. Činjenica je da bez
merenja moderna tehnologija ne može da funkcijoniše.

Ali merenje nije zaključano u domen tehnološke primene, svako od nas meri
na dnevnoj bazi. Uzmimo za primer situacije u kojima merimo pojave u okolini, sa
ciljom da dobijemo kvalitetniju procenu.
Cena igra ulogu merne vrednosti određenog proizvoda ili usluge, tako da mi
računamo ukupnu vrednost kupljenih proizvoda, kako bi znali da li nam je prodavac
vratio dovoljno novca. Takođe koristimo mere visine i težine pri kupovini novih
pantalona kako bismo iz izdvojili one koje nam odgovaraju. Kada krenemo na put
računamo daljinu, biramo rutu putovanja, merimo brzinu, i predviđamo kada demo
stidi na odredište.
Činjenica je da nam merenje pomaže da shvatimo naš svet, da delujemo na
naše okruženje i tako poboljšavamo naše živote.

Jedna od fraza koja je stoji visoko na polici mudrosti svakog naučnika koji
proučava metrike i merenja je: „Ono što nije merljivo, napravi da bude“ i pripisuje se
Galileu Galileju (1564-1642). Ona nam kaže da bi cilj nauke o merenju trebao da
bude pronalaženje novih metrika i načina da se one primene na realni svet oko nas.
Tako da u cilju povedavanja efikasnosti posla koji obavljamo treba da stremimo ka
kreiranju novih metrika na poljima gde one ne postoje, kao i poboljšanju ved
postojedih metrika. U svetlu ove izreke možemo uporediti neke od metrika koje
koristimo u današnjem društvu, a koje su nastale u drugim vremenskim epohama, pa
su stoga u različitim stupnjevima razvoja. Na primer temperatura ili brzina su metrike
koje su ustoličene u našem društvu, dostupne su i lako merljive od strane gotovo
svakoga. Sa druge strane stoje metrike poput koeficijenta ljudske inteligencije ili
ekonomske inflacije, koje nisu dovoljno rafinirane, ali su jednako bitne u
svakodnevnom životu. Činjenica da ljudi ranije nisu imali način da precizno izmere
pojave poput brzne ili temperature. Stoga dolazimo do pretpostavke da de u
bududnosti mere koje danas nisu dovoljno rafinirane biti na višem stepenu razvitka, a
da demo koristiti neke druge nove metrike koje nisu dovoljno rafinirane, ali su
neophodne za društveno funkcionisanje. Što nas dovodi do zaključka da su merenja i

6
Dejan Stuparid, Softverska metrika

metrike u stalnom procesu razvoja, i da se nikada ne sme pretpostaviti da imamo


konačan skup metriki u nekoj oblasti. (3)

Sport možemo iskoristiti kao dobru platformu za prikaz primera metrika koje
se mogu primeniti i na softversku industriju. Prvenstveno je to zbog činjenice da su
pravila za svaki sport univerzalno prihvadena, iako se konstantno vodi diskusija o
njihovoj modifikaciji.
Primer 1: U atletskoj disciplini dekatlon merimo brzinu takmičara na raznim
distancama, daljinu skoka u skakačkim disciplinama, kao i dužinu leta koplja. Ove
metrike se kasnije kombinuju u jedinstveni brojčani skor koji je kompozicija
koeficijenata svake discipline. Ovaj skor se koristi kako bi se izabrao nabolji
dekatlonac, a takođe vlada mišlenje da je pobednik Olimpijskog dekatlona najbolji
svetski sportista.
Primer 2: U engleskoj fudbalskoj ligi koristi se brojčani skor kako bi se odredio
najbolji tim tekude sezone. 1981. godine promenjen je sistem bodovanja, po novom
sistemu pobeda je donosila tri umesto dva boda, koliko je nosila u prethodnom
pravilniku, Remi je i dalje donosio jedan bod. Ova promena je nastala jer je vladalo
mišljenje da je veda razlika između pobede i remija, nego što je razlika između remija i
poraza. Ovaj sistem bodovanja je kasnije usvojen širom sveta, jer je očigledno
izabrano dobro preslikavanje atributa iz realnog sveta na apstraktne činioce. (3)
Lako je uvideti paralele između datih primera i pojava u softverskom
inženjerstvu. U softverskom inženjerstvu ponekad nam je potreban ukupan skor koji
de nam pomodi oko donošenja odluka u konkretnim situacijama. Takođe, često demo
menjati težinske koeficijente nekih operacija kako bismo bolje reprezentovali
promene u sistemu. Promene mogu nastati usled korišdenja druge tehnologije, novih
sintaksnih pravila, ili menjanja uslova rada.

Merenje možemo definisati kao proces u kojem atributima iz realnog sveta


dodeljujemo brojčane ili simboličke vrednosti, na način detaljno opisan definisanim
pravilima. Nažalost merenje nije uvek tako očigledno, postoji veliki broj različitih
interpretacija objekata koji mogu biti mereni.

Da bismo shvatili kako meriti moramo odgovoriti na nekoliko pitanja:


 Ako predpostavimo da je boja atribut sobe. Da li je u sobi sa plavim
zidovima, plavo mera te sobe?
 Visina osobe je široko prihvadena kao atribut koji se može izmeriti. Šta je sa
inteligencijom? Da li de inteligencija osobe biti tačno izmerena IQ testom?
 Uzmimo za primer merenje kvaliteta vina. Možemo pouzdano izmeriti
procenat alkohola u vinu. A da li nam procenat alkohola govori nešto o
geografskom poreklu vina, ili starosti vina? Na koji način demo vrednovati
subjektivno mišljenje eksperata o kvalitetu vina?
 Merenje takođe zavisi i od preciznosti mernog instrumenta, kao i od načina
na koji je definisano samo merenje. Na primer dužina se može lako i

7
Dejan Stuparid, Softverska metrika

precizno izmeriti sve dok se odgovarajudi metar koristi na pravi način. Sa


druge strane merenja kao što su ljudska inteligencija ili ukus vina nisu
egzaktni, treba li ih odbaciti?
 Čak iako su merni instrumenti pouzdani i pravilno se koriste, postoji
margina za gresku. Na primer rezultati merenja visine neke osobe mogu
znatno da variraju u zavisnosti da li osoba nosi cipele prilikom merenja.
Pitanje je kako odrediti marginu greške?
 Visinu čoveka možemo da merimo u milimetrima, metrima ili kilometrima.
Visina de biti ista jedino demo je drugačije zapisivati u zavisnosti koju
jedinicu odaberemo. Kako odabrati jedinicu koju demo koristiti?
 Kada završimo meranja, dobijene rezultate možemo analizirati i izvlačiti
zaključke o entitetima iz kojih su nastali. Kakve manipulacije rezultatima
imaju smisla? Na primer, zašto je prihvatljivo da kažemo da je Milan duplo
viši od Jovane, a nije prihvatljivo da kažemo da je danas duplo toplije nego
juče. Takođe ima smisla izračunati prosečnu visinu zgrada u Novom Sadu,
ali nema preterano smisla računati srednju vrednost brojeva na dresovima
fudbalskog tima. (3)

Ako imamo odgovore na ova pitanja, znači da podižemo proces merenja na viši
(apstraktniji) nivo i da ga takvog možemo primeniti na tehnološki aspekt koji nam je
potreban, u našem slučaju softversku industriju.

1.2. O merenju softvera


Merenje softvera je na početku razvoja softverskog inženjerstva kao
inženjerske discipline bila “ezoterična niša” rezervisana za manju grupu entuzijasta.
Kasnije se ispostavilo da je ono neophodno za kvalitetno softversko inženjerstvo.
Veliki broj najboljih programera meri karakteristike programa kako bi proverili
da li su zahtevi konzistentni i potpuni, da li je dizajn urađen na zadovoljavajudem
nivou, kao i da bi proverili da li je kôd spreman za testiranje. Efikasan rukovodilac
projekta (eng. project manager) meri atriburte procesa i proizvoda kako bi imao
predstavu o datumu završetka rada, i da li de se projekat zadržati u granicama
predviđenog budžeta. Informisan kupac ispituje aspekte gotovog proizvoda kako bi
utvrdio da li ispunjava postavljene zahteve i naveden kvalitet. Takođe programeri
zaduženi za održavanje sistema moraju biti u stanju da procene trenutno stanje
projekta, kako bi bili u mogudnosti da ga nadograđuju i unapređuju. Za sve ove
učesnike u izradi projekata neophodno je da mere softver, stoga se ova grana
softverskog inženjerstva sve više razvija.(14)

Kada merimo karakteristike softvera jako je bitno da uvedemo pravila.


Moramo znati šta se u konkretnoj metrici meri, šta ne, i koliko se vrednuje koja
osobina. Tokom razvoja pojedinačnih metrika razni subjekti dolaze do različitih

8
Dejan Stuparid, Softverska metrika

intrepretacija iste stvari. Tako da je neophodno da se uz svaku metriku navede i


specifikacija svega što se meri.

1.2.1. Problemi pri merenju softvera


Kod vedine softverskih projekata često dolazi do problematičnih odluka i
situacija pri merenju softvera, nabrojademo neke:
 Ne uspevamo da zadamo merljive ciljeve. Na primer obedamo klijentu da de
program biti lak za korišdenje (eng. user-fliendly), da de biti pouzdan i lak za
održavanje, a da pre toga ne specificiramo šta koji termin konkretno znači. Kao
rezultat dobijamo završen projekat za koji ne možemo jasno da kažemo da li je
ispunio svoje ciljeve.
 Ne uspevamo da definišemo cenu pojedinačne komponente. Na primer, vedina
projekatanata ne može da napravi razliku u ceni razvoja softvera, dizajniranja
ili testiranja. Klijenti se često žale na prekoračenje budžeta, jer mi ne možemo
da kontrolišemo troškove koji znatno fluktuiraju, jer ne znamo koliko koja
komponenta košta.
 Ne uspešno predviđanje kvaliteta softvera nas dovodi u situaciju da ne
možemo da tvrdimo koliko de naš softver biti siguran. Ili koliko vremena de
nam trebati da prenesemo program na neku drugu platformu.
 Dozvoljavamo da nas neformalni dokazi ubede da pređemo na nove
tehnologije. Bez prethodnog temeljnog testiranja, kako bismo utvrdili da li
demo efikasnije i efektivnije obavljati svoj posao.

Često se dešava da i kada se softver meri merenje obavlja retko,


nekonzistentno i nepotpuno. Na primer ako se merenje ne obavi u potpunosti
dolazimo do situacije da znamo da postoje 55 grešaka na 1000 linija kôda, ali da nam
nije prezentovano na koji način je izvršeno merenje. Bez dodatnih informacija
ostajemo skeptični, i neodlučni da li da uvažimo konkretno merenje.

1.2.2. Ciljevi merenja softvera


Čak i kada nam se projekat razvija po planu potrebno je konstantno izvršavati
merenja. Kako inače možemo redi da je projekat kvalitetno izrađen, ako ne merimo
kvalitet njegove izrade? Tako da nam je merenje neophodno i za samo utvrđivanje u
kom stadijumu razvoja nam se trenutno projekat nalazi. Moramo dokumentovati
trendove, dostignuda, i izmene kako bismo mogli da kontrolišemo razvoj projekta.

Ciljevi merenja moraju biti specifični, i orjentisani ka tome šta je potrebno


menadžerima, programerima ili korisnicima. Zbog toga se ciljevi mogu razlikovati, u
zavisnosti od profila osoblja koje de stremiti ka njihovom ispunjenju. Navešdemo neke
primere ciljeva ka kojima de stremiti osoblje, iz perspektive programera i menadžera.

9
Dejan Stuparid, Softverska metrika

Menadžeri:
Koliko svaki proces košta? Možemo izmeriti koliko koja aktivnost iziskuje
vremena i truda. Na primer možemo izračunati cenu faze odlučivanja o
zahtevima projekta, cenu faze dizajniranja, cenu pisanja izvornog kôda, i cenu
testiranja. Na ovaj način dobijamo ukupnu vrednost projekta, kao i uvid u udeo
svake faze u ukupnoj ceni projekta.
Koliko nam je osoblje produktivno? Možemo meriti vreme koje je potrebno
osoblju da napravi specifikaciju sistema, da dizajnira isti, kao i vreme za pisanje
izvornog kôda i testiranje. Na ovaj način utvrđujemo koliko je osoblje
produktivno u svakoj fazi, i na taj način demo praviti promene u organizaciji.
Koliko je kvalitetan kôd koji proizvodimo? Pažljivim beleženjem problema,
grešaka i promena, dolazimo do procene kvaliteta softvera. Što nam
omogudava da naš projekat poredimo sa drugim referentnim projektima, i u
zavisnosti od dobijenih zaključaka sprovodimo potrebne reforme.
Da li de korisnik biti zadovoljan sistemom? Možemo meriti da li su sve
zahtevane funkcionalnosti implementirane na odgovarajudi način. Takođe
možemo meriti upotrebljivost, pouzdanost i brzinu izvršavanja. Na taj način
predviđamo da li de korisnici biti zadovoljni postignutim funkcionalnostima, ili
performansama.
Kako poboljšati projekat? Možemo meriti vreme i trud potrebni za svaku
značajnu izmenu sistema. Na taj način odlučujemo da li nam je isplativo da
izvršavamo zamišljenu promenu.

Programeri:
Da li je mogude testirati specificirani zahtev? Na primer možemo analizirati
zahtev da proizvod mora biti pouzdan. Pošto taj zahtev nije formalno
definisan, možemo ga zameniti zahtevom da program mora da radi bez greške
više od 15 sati procesorskohg vremena.
Da li smo pronašli sve greške? Možemo meriti broj nađenih grešaka u
specifikaciji, dizajnu, pisanju izvornog kôda i testiranju. I koristedi statistiku o
broju grešaka po fazi razvoja, odrediti da li smo pronašli dovoljan broj grešaka,
i da li nam je projekat spreman da napreduje u slededu razvojnu fazu.
Da li smo ispunili ciljeve proizvoda ili proizvodnje? Meredi karakteristike
proizvoda ili proizvodnje možemo da kažemo da li smo ispunili standarde,
zahteve ili ciljeve istih. Na primer sertifikat možda nalaže da naš proizvod ima
manje od 20 fatalnih grešaka za određeni vremenski period beta-testiranja. Ili
po standardu ni jedan od naših modula ne sme imati više od 100 linija izvornog
kôda (eng. LOC).
Šta de se desiti u bududnosti? Merimo atribute trenutnog stanja proizvoda ili
procesa proizvodnje, kako bismo mogli da predviđamo njihove atribute u
bududnosti. Na primer merenje broja linija izvornog kôda u trenutnoj fazi
sistema može nam redi koliko de linija imati konačni sistem. Ili pouzdanost

10
Dejan Stuparid, Softverska metrika

sistema tokom testiranja nam može pomodi prlikom predviđanja pouzdanosti


završnog sistema. (3)

1.3. O metrikama i graničnim vrednostima


Kako bismo bili u mogudnosti da pravilno ocenjujemo softver moramo imati
razvijene konkretne načine merenja (metrike), kao i vrednosti koje nam govore da li
je dobijeni rezultat prevelik, premali ili srednje vrednosti.
U Tabeli 1 navešdemo listu metrika koje demo koristiti u ovom radu, zajedno sa
kratkim objašnjenjem.

Disharmonija u kojoj
Metrika Opis
figurira1
Odbijanje roditeljskog
Prosečna Težina Metoda – Prosečna kružna
nasleđa (eng. Refused Parent
AMW (eng. Awerage kompleksnost svih metoda u
Bequest), Prekid tradicije
Method Weight) jednoj klasi
(eng. Tradition Breaker)
Božija klasa forma ponašanja
(eng. God Class behavioral
Pristup Stranim Podacima – Broj atributa drugih klasa
form), Ljubomorni Metod
ATFD (eng. Access To kojima se pristupa preko
(eng. Feature Envy),
Foreign Data) getera i setera ili direktno
Prevelika Intimnost (eng.
Inappropriate Intimacy)
Broj metoda posmatrane
Nivo Redefinisanih Metoda klase koji redefinišu metode
Odbijanje roditeljskog
Bazične Klase – BOvR (eng. iz bazične klase, podeljen sa
nasleđa
Base Class Overriding Ratio) ukupnim brojem metoda u
klasi
Broj nasleđenih entiteta koji
Nivo Korišdenja Entiteta iz
se koriste u posmatranoj Odbijanje roditeljskog
Bazične Klase – BUR (eng.
klasi, podeljen sa ukupnim nasleđa
Base Class Usage Ratio)
brojem nasleđenih entiteta
Broj klasa u kojima je
Izmenljive klase – CC (eng. Operacija sačma (eng.
definisan metod koji poziva
Changing Classes) Shotgun surgery)
posmatrani metod
Izmenjivi Metodi – CM (eng. Broj različitih metoda koji
Operacija Sačma
Changing Methods) pozivaju posmatrani metod
Broj različitih metoda
Intenzitet Sparivanja – CINT
pozvanih od strane Prevelika intimnost
(eng. Coupling Intensity)
posmatranog metoda

1
Disharmonije su objašnjene u poglavljima od 2.3.2.1. do 2.5.2.2.

11
Dejan Stuparid, Softverska metrika

Kružna Složenost – CYCLO


Broj nezavisnih puteva kroz Mudri metod (eng. Long
(eng. Cyclomatic
graf algoritma Method)
Complexity)

Dubina nasleđivanja na kojoj


Dubina Stabla Nasleđivanja
se klasa nalazi. Inicijelna
– DIT (eng. Depth of Primer
dubina je 1, jer je svaka klasa
Inheretance Three)
podklasa klase Object
Snabdevači Stranih Broj klasa u kojima su
Podataka – FDP (eng. definisani atributi kojima Ljubomorni Metod
Foreign Data Providers) pristupamo
Broj atibuta klase u kojoj je
Lokacija Korištenih Atributa
metod definisan, podeljen sa
– LAA (eng. Locality of Ljubomorni Metod
ukupnim brojem korištenih
Attribute Accesses)
promenljivih
Broj Linija Kôda – LOC (eng. Broj linija izvornog kôda na Mudri metod, Mudra klasa
Line of Code) merenoj sekciji programa (eng. Brain Class)
Dužina Lanca Delegiranja – Broj polja koje se nalaze u
Lanac Delegiranja (eng.
LDC (eng. Length of nizu prosleđivanja
Delegation Chain)
Delegation Chain) odgovornosti
Broj Lanaca Delegiranja sa
Broj Lanaca Delegiranja –
dužinom vedom od
NDC (eng. Number of Posrednik (eng. Middleman)
naznačene (u našim
Delegation Chains)
primerima koristidemo 7)
Broj metoda u merenoj klasi
Broj Dodatih Servisa – NAS
koji nisu redefinisani ili
(eng. Number of Added Prekid tradicije, Posrednik
specijalizovani metodi klase
Services)
predaka
Broj Metoda za Pristup – Broj metoda kojima se
Božija klasa forma podataka
NOAM (eng. Number of pristupa ili menja neka
(eng. God Class data form)
Accessor Methods) promenljiva (get i set metodi
Broj Korišdenih Promenljivih
Ukupan broj promenljivih
– NOAV (eng. Number of Mudri metod
kojima pristupamo direktno
Accessed Variables)
Broj Naslednika – NOC (eng. Ukupan broj podklasa
Primer
Number of Children) posmatrane klase
Broj Klasa – NCL (eng. Ukupan broj klasa unutar
Primer
Number of Classes) paketa
Broj Metoda – NOM (eng. Ukupan broj metoda u Odbijanje roditeljskog
Number of Methods) posmatranoj klasi nasleđa, Prekid tradicije
Broj Atributa Sa Ukupan broj atributa sa
Indentifikatorom public – indentifikatorom public
Božija klasa forma podataka
NOPA (eng. Number of unutar klase na kojoj je
Public Attributes) primenjena metrika

12
Dejan Stuparid, Softverska metrika

Broj Metoda Definisanih u


Broj metoda u nekoj klasi koji
Interfejsu – NOMD (eng.
je definisan u interfejsu te Prevelika Intimnost
Number Of Methods
klase
Defined in Interface)
Broj Redefinisanih Metoda – Broj metoda definisanih u
NORM (eng. Number of klasi roditelj koji su Primer
Overridden Methods) redefinisani u klasi dete
Broj Entiteta sa Ukupan broj atributa i
Indentifikatorom protected metoda sa indentifikatorom Odbijanje roditeljskog
– NProtM (eng. Number of protected unutar posmatrane nasleđa
Protected Members) klase
Broj metoda sa
indentifikatorom public u
posmatranoj klasi koji nisu
Procenat Novih Servisa –
redefinisani ili specijalizovani Prekid tradicije
PNAS (eng. Percentage of
metodi klase roditelja,
Newly Added Service)
podeljen sa ukupnim brojem
metoda sa indefikatorom
public
Veličina Indentičnog Dela Broj linija dela izvornog kôda
Znatno Dupliciranje (eng.
Izvornog Kôda – SEC (eng. koji se podudara sa delom
Significant Duplication)
Size of Exact Clone) koji merimo
Broj linija dela izvornog kôda
Daljina Dupliciranja – LB
koji razdvaja dva segmenta Znatno Dupliciranje
(eng. Line Bias)
dupliciranog kôda
Globalni pogled na
dupliranje. Broj linija dela
Veličina Niza Dupliciranja
izvornog kôda koji se sastoji
SDC – (eng. Size of Znatno Dupliciranje
od skupa istih sekcija kôda
Dupliceted Chain)
čija je DD vrednost manja od
određene granične vrednosti
Broj parova metoda koji
Čvrsto Sparivanje Klasa –
pristupaju zajedničkom Božija klasa forma
TCC (eng. Tight Class
atributu unutar posmatrane ponašanja, Mudra klasa
Cohesion)
klase
Odbijanje roditeljskog
Ukupnan težinski koeficijent
Težina Metoda – WMC (eng. nasleđa, Prekid tradicije,
svih metoda klase na koju je
Weighted Method Count) Božija klasa forma ponašanja
primenjena metrika
i podataka, Mudra klasa
Broj funkcionalnih metoda sa
indentifikatorom public,
Težina Klase – WOC (eng.
podeljen sa ukupnim brojem Božija klasa forma podataka
Weight Of a Class)
metoda sa indentifikatorom
public
Tabela 1 – Lista disharmonija

13
Dejan Stuparid, Softverska metrika

Ključni faktor u radu sa metrikama je znanje da pravilno interpretiramo


dobijenu vrednost. U tu svrhu uvodimo granične vrednosti. Granična vrednost deli
dobijene vrednosti na različite oblasti. Uzmimo za primer metriku težine odraslog
muškarca. Uzmimo vrednost 150kg kao prag za jako teške ljude. Ovako jednostavna
odluka može imati mnogo posledičnih pitanja: Kako smo došli do vrednosti od 150kg?
Zašto ne 145kg, ili 145000g? Da li je čovek od 160kg, težak u odnosu na onog od
200kg? Da li nam ova granična vrednost nešto znači na populaciji gde je nateži čovek
težak 100kg? Poenta ovog primera je da nam predoči da ne postoje savršene granične
vrednosti, ali je njihvo postojenje svakako korisno jer nam daje osedaj perspektive.
Granične vrednosti određujemo statistički ili ved prihvadenim semantičkim
konvencijama. (1)
Navešdemo primere (Tabela 2) graničnih vrednosti na nekoliko najbitnijih
metrika, nastalih statističkom analizom velikog broja Java i C++ projekata.

Java C++

Jako Jako
Metrika Malo Srednje Veliko Malo Srednje Veliko
Veliko Veliko
CYCLO/LOC 0.16 0.20 0.24 0.36 0.20 0.25 0.30 0.45
LOC/NOM 7 10 13 19.5 5 10 16 24
NOM/NOCL 4 7 10 15 4 9 15 22.5
WMC 5 14 31 47 4 23 72 108
AMW 1.1 2.0 3.1 4.7 1.0 2.5 4.8 7.0
LOC/NOCL 28 70 130 195 20 90 240 360
NOM/NOCL 4 7 10 15 4 9 15 23
Tabela 2 – Granične vrednosti nekih metrika u Javi i C++-u

U Tabeli 2 imamo granične vrednosti nekih metrika u jezicima Java i C++, one
su grupisane u kategorije (Malo, Srednje, Veliko, Jako Veliko) na osnovu vrednosti.
Kada primenimo metriku na sekciju izvornog programa dobijamo vrednost, i na
osnovu te vrednosti posmatranu sekciju izvornog programa možemo smestiti u
odgovarajudu lategoriju. Kategorije vrednosti metrika de nam biti od koristi pri
definisanju defekata, koje de biti obrađeno u poglavlju 2 (PROBLEMI U SOFTVERSKIM
PROJEKTIMA - DEFEKTI).
Ako imamo u vidu ovakve statističke rezultate lakše demo uvideti kada neki
deo izvornog kôda prekoračuje standardna ograničenja. Posedovanje ovakvih
informacija nam omoguduje da brže rezonujemo, i lakše izvršavamo popravke u
softveru.

U Tabeli 3 navedimo granične vrednosti koje su prihvadene semantičke


konvencije.

14
Dejan Stuparid, Softverska metrika

Numerička Vrednost Semantička Vrednost


0,25 Četvrtina
0,33 Tredina
0,5 Polovina
0,66 Dve tredine
0,75 Tri četvrtine
0 Ništa
1 Jedan/Plitko
2-5 Dva/Tri/Par/Nekoliko
7-8 Kapacitet kratkoročne memorije
8-12 Desetak
Tabela 3 – Mapiranje numeričkih na semantičke vrednosti
Kod ovih graničnih vrednosti praktično preslikavamo numeričke vrednosti na
pojmove koje demo koristiti pri razmatranju rezultata metrika. Ovi pragovi nisu
univerzalno prihvadeni, ali de biti korišdeni tokom ovog rada kako bismo se lakše
snašli u moru informacija.
U ovom radu nekim metrikama demo posvetiti malo više pažnje u odnosu na
neke druge, pa stoga je potrebno bliže ih objasniti.

1.3.1. Broj Linija Kôda (LOC)


Ova metrika je jedna od najkorišdenijih metrika u svakodnevnom radu, i
prevashodno je taj status zaslužila zbog velike upotrebne vrednosti i jednostavnog
načina izračunavanja. Broj linija izvornog kôda je često glavni odraz kompleksnosti
nekog softverskog programa, ali takođe može biti izvor velikog broja zabluda. Ovom
metrikom merimo broj linija u izvornom kôdu programa. Linije se mogu meriti na
nivou celog programa, na nivou paketa, klasa ili metoda. Samo izračunavanje može se
obavljati ručno, ali je znatno lakše i preciznije brojanje prepustiti nekom od velikog
broja raspoloživih softverskih alata. (9)
Broj linija kôda je vrlo prosta metrika, čije računanje predstavlja jednostavan
pravolinijski posao. Ovo tvrđenje je delimično tačno, naime samo računanje ove
metrike je jednostavno, ali moramo obratiti pažnju na to koje linije brojimo. Potrebno
je odrediti šta se broji, a šta ne.
Razmotrimo konkretan primer meranja LOC, i na koja se sve pitanja mora
odgovoriti pre nego što predstavimo rezultat ove naizgled jednostavne metrike.
Američki institut za softversko inženjerstvo univerziteta Carnegie Mellon iz
Pitsburga je napravio svojevrsnu listu čijim pradenjem možemo shvatiti šta zaista ulazi
u merenje linija kôda. U prvoj koloni Tabele 4 navodimo osobine konkretne linije (tip
naredbe koja se nalazi u posmatranoj liniji, nastanak ili poreklo linije). Prva i druga
kolona se popunjavanju u zavisnosti od osobina linija izvornog kôda koje želimo da

15
Dejan Stuparid, Softverska metrika

uključimo u brojanje. Na primer, ukoliko želimo da stavimo do znanja da ce u brojanje


biti uključene linije koje su nastale programiranjem kudica Uključeno de biti označena
pored osobine programirana.

Osobine posmatrane linije Uključeno Nije uključeno


Tip naredbe?
Izvršne
Neizvršne:
Deklaracije
Direktive kompajleru
Komentari:
U sopstvenoj liniji
U istoj liniji sa izvornim kôdom
Prazni komentari
Prazne linije
Kako je linija nastala?
Programirana
Generisana od strane softvera
Konvertovana automatskim prevodiocem
Kopirana bez izmene
Modifikovana
Izbrisana
Poreklo?
Potpuno nova linija
Uzeto iz drugog projekta:
Prethodne verzije istog proizvoda
Komercijalni softver, ne računajudi
biblioteke
Softver napravljen od strane drževe,
ne računajudi biblioteke
Neki drugi proizvod
Vlasnička biblioteka za podršku jezika
(ne modifikovana)
Vlasnički operativni sistem ili uslužni
program (ne modifikovan)
Modifikovana vlasnička biblioteka ili
operativni sistem
Biblioteka namenjena za ponovno
korišdenje
Druge softverske komponente ili
biblioteke
Tabela 4 – Specifikacija LOC univirziteta Carnegie Mellon

16
Dejan Stuparid, Softverska metrika

Najbitniji koncept vezan za merenje linija izvornog kôda je konzistentnost,


naime kada utvrdimo šta sve želimo da brojimo, moramo se držati toga. Nedostatak
konzistentnosti može da dovede do velikih problema pri poređenju nekih entiteta u
izvornom kôdu koji su mereni na različiti način. Na primer, ukoliko poredimo metod
koji ima 30 linija kôda pri čemu ne računamo komentare, sa metodom od 30 linija u
koje spadaju i komentari, vrlo je lako dodi do pogrešnog zaključka.

1.3.2. Kružna Složenost (CYCLO)


Najpoznatija i verovatno najpopularnija metrika kompleksnosti je svakako
MekKejbova Kružna Složenost (eng. McCabe`s Cyclomatic Complexity), koja meri broj
nezavisnih puteva kroz sekciju izvornog kôda. Ona se bazira na klasičnoj teoriji
grafova, gde mi u suštini merimo broj puteva kroz graf, čije čvorove predstavljaju
različiti entiteti u izvornom kôdu.

Kružna složenost se računa brojanjem čvorova i grana grafa koji reprezentuje


softverski modul koji želimo da merimo. Ovo brojanje je reprezentovano slededom
formulom:
( ) , gde je g graf modula koji merimo, e je broj grana u grafu, a
n je broj čvorova.

Navedimo jedan primer pomodu koga demo lakše razumeti proces računanja
kružne složenosti.

Slika 1 – Grafovi kružne složenosti

Na Slici 1 vidimo tri grafa koji predstavljaju tri različita softverska entiteta,
izmerimo im kružnu složenost (CYCLO).

17
Dejan Stuparid, Softverska metrika

 V(A) = 5 – 5 + 2 = 2 -- Kružna složenost ovog grafa je 2.


 V(B) = 6 – 5 + 2 = 3 -- Kružna složenost ovog grafa je 3.
 V(C) = 6 – 5 + 2 = 3 -- Kružna složenost ovog grafa je 3.

Koeficijent kružne složenosti je proporcijalan sa kompleksnošdu programa, a to


u praksi znači da je program koji ima vedu kružnu složenost kompleksniji za testiranje
i održavanje. Kružna složenost slično kao i broj linija kôda može imati više
reprezentacija. Vrednost metrike Kružna složenost zavisi od načina na koji brojimo
pojedine jezičke konstrukcije (boolean operatori, uslovne naredbe, petlje)

U Tabeli 5 navešdemo skup metoda koji su raspoređeni u različite kategorije na


ostnovu vrednosti metrike Kružna složenost primenjene na posmatrani metod. Naime
ova tabela predstavlja pojednostavljenje i pogled iz drugog ugla na deo Tabele 2
fokusiran samo na metriku Kružne složenosti. Razliku predstavlja činjenica da smo u
Tabeli 2 koristili kružnu složenost po liniji izvornog kôda, dok u Tabeli 5 kružnu
složenost merimo na nivou metoda. Pošto dobijemo koeficijent kružne složenosti
primenom metrike na posmatrani metod, smeštamo ga u odgovarajudu kategoriju u
zavisnosti od visine koeficijenta kružne složenosti za posmatrani metod.

Vrednost metrike
Tip Metoda Kategorija
Kružna Složenost
1–4 Jednostavan metod Mali
Dobro struktuiran, stabilan
5 – 10 Mali
metod
11 – 20 Prilično kompleksan metod Srednji
Kompleksan metod,
21 – 50 Veliki
zabrinjavajude
Veoma kompleksan metod,
>50 Jako Veliki
sklon greškama
Tabela 5 – Metodi različite kružne složenosti raspoređeni po kategorijama

1.3.3. Čvrsta Kohezija Klase (TCC)


Metrika TCC meri stepen kohezije među metodima sa modifikatorom pablik
(eng. public) unutar jedne klase. Rezultat metrike predstavlja relativni koeficijent
direktno povezanih metoda sa modifikatorom pablik. Klase sa malim TCC verovatno
sadrže greške pri dizajniranju, i treba ih ispitati.
TCC je izvedena metrika koja se sastoji od odnosa broja direktno sparenih
pablik metoda unutar klase (NDC(C)), i maksimalnog mogudeg broja direktno sparenih
metoda za tu klasu (NP(C)). Dva metoda su dirtektno sparena ukoliko pristupaju istoj
instanci neke klase.
( )
( ) , gde n je jedan od direktno sparenih metoda,

18
Dejan Stuparid, Softverska metrika

( )
Dok TCC računamo slededom formulom: , pri čemu NDC
( )
prikupljamo direktnim merenjem.

1.3.4. Ukupan Težinski Koeficijent (WMC)


Ova metrika predstavlju sumu težinskih koeficijenata svih metoda unutar
posmatrane klase. Na svaki metod se posebno primenjuje metrika WMC, pa se onda
koeficijenti parametrizuju i normalizuju kako bi činili jedinstvenu metriku.
Metrike kompleksnosti koje se koriste za računanje težinskog koeficijenta
metoda su:
 LOC
 CYCLO
 NAS (Number of Added Services)
 NOAM (Number of Accesor Methods)
 …

WMC je orginalno konstruisana kao objektno orjentisana metrika, fokusirana


na merenje karakteristika modernih programskih jezika. Ali takođe WMC se vrlo lako
može koristiti i za merenje proceduralnih jezika, pritom demo meriti procedure,
funkcije, module…

1.3.5. Broj Metoda u Jednoj Klasi (NOM)


NOM je vrlo jednostavna metrika koja nam može dati jako dobru predstavu o
kompleksnosti neke klase. NOM možemo shvatiti kao LOC metriku objekto-
orjentisanih jezika, jednostavnu za merenje i poređenje, ali takođe i metriku koja
nam može dati pogrešnu predstavu o klasi koju merimo.
U NOM metrici idemo redom kroz izvorni kôd klase koju merimo i beležimo sve
metode koje brojimo. Postoje situacije kada je brojanje metoda selektivno, na primer
kada želimo da izbrojimo sve statičke metode, sve redefinisane metode ili metode sa
modifikatorom prajvat (eng. private)… Kada radimo sa ovom metrikom vrlo je korisno
imati neku graničnu vrednost sa kojom možemo porediti naše vrednosti. Granične
vrednosti koje koristimo vezano za ovu metriku su statistički prikupljene i možete ih
nadi u Tabeli 2.

1.3.6. Broj Redefinisanih Metoda (NORM)


Metrika NORM predstavlja jednostavno brojanje metoda definisanih u nadklasi
koji se redefinišu u posmatranoj klasi. Ova metrika nam može biti od koristi pri
evaluiranju struktura nasleđivanja, i pronalaženju ne odgovarajudih odnosa roditelj-

19
Dejan Stuparid, Softverska metrika

dete. Drugim rečima metrikom NORM možemo odrediti nivo specijalizacije klase na
kojoj je primenjena metrika, i pomodu dobijene informacije proceniti da li
nasleđivanje odgovara zadatim standardima.

1.3.7. Dubina Stabla Nasleđivanja (DIT)


Jedna od metrika kojom možemo ocenjivati kvalitet hijerarhije nasleđivanja u
našem programu. Ova metrika je nastala usled potrebe da se pronađu klase koje se
nalaze preduboko u hijerarhiji nasleđivanja, zbog čega postaju teške za održavanje i
testiranje. Naime metrika vrada vrednost koja predstavlja dubinu u hijerarhiji
nasleđivanja za merenu klasu. Drugim rečima dobijamo poziciju posmatrane klase u
stablu nasleđivanja.

C1

C2 C3

C4

C5

Slika 2 – Hijerarhija nasleđivanja

Navedimo vrednosti DIT metrike za svaku klasu na Slici 2. (12)

 DIT(C1) = 1
 DIT(C2) = 2
 DIT(C3) = 2
 DIT(C4) = 3
 DIT(C5) = 4

Primetimo da klasa na prvom mestu u hijerarhiji ima dubinu stabla


nasleđivanja 1. Razlog za ovo je činjenica da je svaka klasa u Java programskom jeziku
podklasa klase Object.

1.4. O daljem toku rada

20
Dejan Stuparid, Softverska metrika

U nastavku trudidemo sa da opišemo odnose među metrikama. Pokušademo


da odgovorimo na pitanja kao što su: Kako de povedanje broja LOC uticati na kružnu
složenost te klase? Da li de intenzitet sparivanja u klasi (eng. coupling), uticati na broj
metoda te klase?
Takođe deo rada odnosi de se na defekte, poglavlje softverskog inženjerstva
koje se veoma oslanja na softverske metrike. Tu demo nabrojati brojne defekte klasa,
metoda ili paketa, šta oni predstavljaju i načine kako da ih izbegavamo, ili u krajnjem
slučaju kako da ih učinimo manje opasnim.

21
Dejan Stuparid, Softverska metrika

2. Problemi u softverskim
projektima (Defekti)
Tokom ovog poglavlja trudidemo se da predstavimo reižinjerstvo kao deo
softverskog inženjerstva, koji je u mnogome zavistan od softverskih metrika i njihovih
primena. Fokusirademo se na probleme pri realizaciji softverskih projekta, jer se iz
grešaka pri realizaciji može mnogo naučiti, a novostečeno znanje primeniti na druge
projekte. Obradidemo veliki broj različitih problema koji pogađaju različite
podsisteme svakog projekta, i predstavidemo načine da se oni otklone ili bar dovedu
na prihvatljiv nivo.

2.1. O reižinjerstvu
Reižinjerstvo je proces restruktuiranja softverskih projekata koji je postao
popularan kasnih 80-ih i ranih 90-ih godina prošlog veka. Osnovni cilj reižinjerstva
softvera je smanjenje troškove, dok u isto vreme povedava produktivnost i kvalitet
izrade softverskih projekata. Koncept koji se nalazi u suštini reižinjerstva je potreba
da se ostane konkurentan u današnjem poslovnom svetu. Kroz reižinjerstvo
pokušavamo da napravimo bolje modele troškova, kvaliteta, produktivnosti, kao i sve
druge sekcije poslovanja. Ove modele poboljšavamo drastičnim koracima, kako
bismo iz korena promenili strukturu našeg poslovanja.(11)
Kompanije se najčešde odlučuju za reinženjerstvo kao zadnju meru, tek kada su
sve druge mogude mere propale. To znači da je situacija dovoljno ozbiljna da se
moraju preduzeti drastični koraci. Kada se odlučimo za reinženjerstvo, moraju nam
biti poznati svi problemi koji postoje u organizaciji, kao i plan da se oni otklone. Kada
ispunimo preduslove, počinjemo sa bazičnim reinženjerstvom. Unapređujemo
razvojni model kompanije, i diskutujemo ili redizajniramo osnovne načine zarade
kompanije. Kao zadnji korak uzimamo usvajanje novog dizajna.
Iako ovo izgleda kao vrlo jednostavan plan, istina je da se čak između 50 i 70
procenata reižinjerskih zahvata završi neuspehom. Kao osnovni uzrok ove pojave
figuriraju, loš novi dizajn, ili nemogudnost da se novi dizajn kvalitetno
implemementira. Takođe nedostatak podrške od menadžmenta organizacije ili njenih
zaposlenih dovodi povedanju stope ne uspešnosti reinženjerskih projekata.

2.1.1. Reinženjerstvo u velikim kompanijama?


Reinženjerstvo u velikim kompanijama se najčešde svodi na dva koncepta:
otpuštanje radnika, i potraga za tehnološkim defektima unutar izvornog kôda.

22
Dejan Stuparid, Softverska metrika

Bliže demo objasniti oba koncepta, počevši sa otpuštanjem radnika.

Koncept koji je najčešde korišden kod reinženjerskih poduhvata je otpuštanje


radnika. Da bi se ovaj često bolan posao optimalno priveo kraju, potrebno je uneti
neke strateške elemente. Kada otpuštamo radnike, uvek gledamo da to ne budu ljudi
koji čine jezgero poslovnog procesa naše organizacije. Razlozi su dvojaki, ukoliko
otpustimo nekoga ko je dugo tu i bitan je za organizaciju, rizikujemo ne samo da
izgubimo kvalitetan kadar, ved i da ostatku jezgra usadimo mišljenje da su oni možda
slededi.
Sa druge strane ako se odlučimo za zamenu rukovodede garniture
(menadžmenta kompanije), potrebno je da novi rukovodioci okupe ostatak firme i
predstave im novi dizajn kompanijskih procesa, kao i plan za njegovo sprovođenje.
Najbolji način da formiramo novi rukovodedi tim je da potražimo ljude što različitijih
mišljenja, jer de nam na taj način biti na raspolaganju najširi spektar ideja. Stoga demo
birati zaposlene unutar kompanije koji su različitih specijalnosti i interesovanja.
Oformljen tim ne bi trebao da broji više od deset članova, jer bi komunikacija među
članovima postala otežana, što nas može sputavati pri drastičnim rezovima koji nam
predstoje. (16)
Otpuštanje zna da bude turbolentan proces za zaposlene u kompaniji, moguda
je nervoza zaposlenih, strah od gubitka radnog mesta ili smanjenje produktivnosti.
Zadak menadžmenta kompanije je da ohrabri ljude, uveri ih da je u njihovom interesu
da se proces promene sprovede do kraja, i da de i oni sami imati ličnu korist ako
kompanija poveda produktivnost.
Celokupne promene je najbolje obavljati u velikim strmoglavim koracima kako
bismo kompaniju brzo doveli u normalno stanje. Suprotno oveome, ukoliko promene
obavljamo postepeno, postoji realna mogudnost da se radnici vrate na stari način
obavljanja posla, što bi dovelo do propasti celokupnog projekta.

Potraga za tehnološkim defektima je znatno različitiji proces od prethodno


opisanog, jer krivca tražimo u tehnologiji, a ne u ljudima kako je to slučaj pri
otpuštanju radne snage. Samim tim ovaj koncept je manje emocijalan, a više
racionalan, i mi demo se baviti prevashodno ovim konceptom u nastavku poglavlja.
Kada kažemo tehnološki defekt, mislimo na sekciju izvornog kôda koja se
ponaša drugačije od definisanog obrazca ispravnog ponašanja. To znači da pre nego
što počnemo da tražimo defekte u programu moramo da znamo da prepoznamo
defekat kada ga vidimo. Uspostavljaju se liste defekata, sa njihovim imenima,
oblikom, ponašanjem, mestima gde se najčešde nalaze, navodi se ozbiljnost takvog
defekta, kao i način da se on otkloni ili ublaži. Kada imamo kvalitetnu bazu defekata
najčede se mašinski pretražuje sistem u potrazi za zadatim obrazcima. Kada se
pronađu kandidati pristupa se njihovom ručnom pregledavanju i razvrstavanju po
kategorijama. Kada odaberemo kandidate koji zaista predstavljaju nedostatak ili lošu
praksu u programiranju, predidemo na otklanjanje tih problema – refaktorisanje (više
o refaktorisanju u poglavlju 2.1.3.).

23
Dejan Stuparid, Softverska metrika

U nastavku detaljno demo predstaviti svaki skup tehnoloških defakata,


navešdemo načine za njihovo primedivanje, kao i akcije za njihovo suzbijanje.

2.1.2. Zašto se reinženjerstvo često završava neuspehom?


Kao što smo napomenuli preko 50 procenata reinženjerskih poduhvata se
završava neuspehom. Sa ovoliko velikom verovatnodom neuspeha, pitanje zašto
uopšte sprovoditi reižinjerski proces. Pre nego što otpočnemo reinženjerski proces,
uđimo malo dublje u glavne razloge za neuspeh.
Glavni razlog za neuspeh procesa je nedostatak podrške visokih rukovodedih
struktura. Iako se reininjerski proces najčešde obavlja inicijelno po njihovoj zamisli, u
nekom trenutku procesa otpuštanja radnika ili potrage za tehnološkim defektima
menadžerima proces postaje prerizičan ili preskup. Ovo dovodi do raznoraznih
kompromisa. Sa jedne strane potraga za defektima de poboljšati ukupnu sliku i ako
promenimo samo mali delid programa, ali to poboljšanje nede biti previše značajno za
ukupnu sliku. Sa druge strane otpuštanje radnika ne trpi kompromise, mora se uraditi
do kraja i sa što manje sentimentalnosti. Zato krajnji rezultat uglavnom predstavlja
veliki pomak unapred ili unazad, u zavisnosti da li smo proces pravilno obavili.
Ukoliko je podrška visokih menadžerskih struktura konstantna i ne oseda se
nedostatak vođstva i resursa velika je verovatnoda da de reinženjerski zahvat uspeti.

Drugi bitan razlog za neuspeh reižinjerskih projekata je nedostatak


komunikacije ili iskrenosti ununatr radne organizacije. Stoga je potrebno definisati
kanale komunikacije koji se moraju poštovati. Takođe je vrlo bitno da su svi nivoi
kompanije voljni da se promene i daju sve od sebe kako bismo poboljšali poslovanje
kompanije.

Još jedan bitan razlog je nedostatak strategije. Pre samog početka


reinženjerskog procesa potrebo je sastaviti detaljni akcioni plan koji se mora
poštovati. Vrlo često je potrebno uraditi potpunu reviziju karaktera firme, kako bi ga
usaglasili sa trenutnom situacijom na tržištu. Neki koncepti poslovanja koji su bili
važedi, i vrlo uspešni u trenutku osnivanja firme možda više nisu na snazi. Pa je
potrebno napraviti radikalan plan da se kompanija u potpunosti preorjentiše na novo
stanje stvari.

Postoji još razloga za neuspeh reižinjerskih zahvata. Nekada firme sebi zadaju
preradikalni plan promena, i nisu u mogudnosti da ga ispoštuju. U nekim situacijama
radnici nisu voljni da toliko menjaju svoj radni ritam. Nekada se pogrešno proceni
stanje tržišta, pa silne radikalne promene odlaze u pogrešnom smeru, što nas dovodi
na prag neuspeha.

24
Dejan Stuparid, Softverska metrika

2.1.3. O refaktorisanju
Refaktorisanje možemo shvatiti kao preoces tokom koga otklanjamo
nedostatke i greške iz izvornog kôda nekog programa. Refaktorisanje je vrlo često
upareno sa nekim alatom koji otkriva defekte u softverskim projektima, pa zatim na
otkrivenim defektima primenjujemo refaktorisanje. Kompleksnost procesa
refaktorisanja krede se od kozmetičkih(?) promena kao što su promene imena
entiteta u izvornom kôdu, do kompletne revizije strukture programa.

Navedimo ukratko neke thenike refaktorisanja:


 Preimenovanje
 Dodavanje/oduzimanje parametara
 Izmeštanje metoda
 Promena reference u vrednost
 Učvršdivanje uslovnih izraza
 Enkapsulacija svih entiteta u izvornom kôdu
 Oblikovanje hijerarhije nasleđivanja
 Izmeštanje hijerarhije
 Parametrizacija metoda
 Uvođenje polimorfizma

Ovom kratkom listom smo naveli samo mali broj mogudih tehnika
refaktorisanja, i navodimo je prevashodno kako bismo shvatili koliko je raznolik
proces refaktorisanja. Nekada je defekte mogude rešiti intervencijom na jednoj maloj
sekciji izvornog kôda, dok je neki put potreban holistički aspekat posmatranja.(8)
U poglavlju 3. videdemo konkretne primene nekih tehnika refaktorisanja, i
modi demo da uvidimo blagodetna dejstva ovakvih akcija.

2.2. Problemi u softverskim projektima


(tehnološki defekti)
U ovom odeljku navešdemo tehnološke defekte koji su najčešdi i imaju najvedi
uticaj na funkcionisanje softverskih projekata. Defekte demo razdvojiti na tri grupe u
zavisnosti od njihovog karaktera, tj. disharmonjije koja se javlja u njima, i to na
Disharmonije identiteda, Disharmonije saradnje, i Disharmonije klasifikacije.
Jedan od ključnih koncepata koji de se provlačiti kroz čitavo poglaje je dualitet
harmonija/disharmonija. Tehnički radovi, pogotovo u računarstvu retko sadrže
nestriktne termine kao što je harmonija, ali u ovom radu definisademo pojam
harmonije/disharmonije i koristiti ga kao tehnički uobičajen termin. Metrike kao lista
brojeva i imena ne opisuju zadovoljavajude probleme u softveru, stoga je potrebno
staviti ih u kontekst. Ovde uvodimo pojam harmonije. Klase i metodi se mogu

25
Dejan Stuparid, Softverska metrika

implementirati na veliki broj sintaksno tačnih načina, ali vrlo malo de biti
implementirano tako da ispunjava svoje dužnosti, ne obavlja mnogo tuđih poslova, i
svoje zadatke obavlja unutar svog domena, tj. ponaša se harmonično. Disharmonija je
potpuna suprotnost, tj. devijacija od skupa principa, pravila i heuristika koje čine
harmoniju. Uvek treba težiti da klase i metode implementiramo harmonično,
obazirudi se na listu harmonija i disharmonija koju demo navesti u nastavku.

Svaka od disharmonija de imati svoje poglavlje, a svako poglavlje de sadržati tri


bitna dela:
1. Pravila harmonije: Kako bismo formirali listu disharmonija moramo imati
pravila po kojima demo ih razlikovati od regularnih delova izvornog kôda (ili
delove izvornog kôda koji su pogođeni nekom drugom disharmonijom). Pravila
harmonije bi trebalo da budu koncizna, i da sadrže kompilaciju heuristika i
dizajnerskih pravila vezanih za konkretnu disharmoniju.
2. Lista disharmonija: Centralni deo svakog poglavlja je nabrajanje svih mogudih
disharmonija koje se mogu detektovati korišdenjem softverskih metrika. Svaka
od disharmonija bide podrobo objašnjena, uključujudi i konkretne primere.
3. Rezime: U ovom delu diskutovademo o prethodno definisanim
disharmonijama i njihovom uticaju na projekat u kojem se nalaze.

2.3. Disharmonije identiteta


Disharmoje identiteta pogađaju konkretne entitete unutar nekog softverskog
programa, često se mogu posmatrati izolovano u odnosu na svoje okruženje.

2.3.1. Pravila harmonije


Pre nego što navedemo konkretne disharmonije, nevedimo pravila po kojima
demo ih tražiti. Za detektovanje disharmonija identiteta koristidemo tri pravila, i to:
pravilo proporcijalnosti veličine, pravilo prezentacije identiteta, i pravilo
implementacije funkcionalnosti.(1)

2.3.1.1. Pravilo proporcijalnosti veličine

Kada razmatramo harmoničnost entiteta na koji demo primenjivati metrike


prvo nam na pamet pada njegova veličina. Veličina je relativna karakteristika
softverskog entiteta, jer je podjednako loše imati i prevelike i premale entitete.
Preglomazni entiteti onemogudavaju lako razumevanje sadržaja, tako da njihovo
održavanje predstavlja ogroman problem. Sa druge strane premali entiteti dovode do
prezasidenja pozivima koji ne rade gotovo ništa, i preterane fragmentacije izvornog
kôda, što ponovo dovodi do otežanog održavanja izvornog kôda. Idealno je da

26
Dejan Stuparid, Softverska metrika

softverski entiteti ne budu ni preveliki ni premali u zavisnosti od funkcije koju


obavljaju.

Uzmimo za primer metod koji računa odnose između koordinata dva pokretna
objekta različitih brzina i pravaca. Ovakav metod može biti prilično velik i
komplikovan, jer je sastavljen od niza komplikovanih aritmetičkih operacija. Ali
takođe znamo da je ne praktično deliti ga na više manjih metoda, jer bi to dovelo do
otežanog razumevanja izvornog kôda usled cepanja logičke celine.
Drugi ekstrem je konstrukcija klase sa jednim metodom, koji sadrži jedan poziv
metoda neke druge klase. Ovakve pojave su u potpunoj suprotnosti sa dobrom
praksom objektno-orjentisanog stila programiranja, i treba ih izbegavati.

Suština je proporcijalnost veličine entiteta i zadatka koji on obavlja, poštujudi


ovaj princip možemo izbedi veliki deo disharmonija identiteta.

2.3.1.2. Pravilo prezentacije identiteta

Ovim pravilom obezbeđujemo da se softverski entitet ponaša unutar


normativa koje smo zadali ranije, da ispunjava svoje dužnosti u potpunosti, i da ne
zadire u domen drugih entiteta.

Šta to konkretno znači:


 Komunikacija između klasa bi trebala da se ograniči na interfejse i javne
metode. Klasa ne bi trebala da javno prezentuje svoje podatke, jer time krši
enkapsulaciju.
 Klasa bi trebelo da opravdava svrhu svog postojanja, a ne da bude kontejner za
pristupne metode (geteri i seteri).
 Klase ili metodi bi trebali da budu jedinstveni. Dupliciranje izvornog kôda
predstavlja kršenje harmonije identiteta.

2.3.1.3. Pravilo implementacije funkcionalnosti

Ovim pravilom obuhvatamo neke od ključnih postulata objektno-orjentisanog


programiranja. Enkapsulacija osigurava da se operacije i podaci nalaze unutar jednog
entiteta, i da se mogu pozivati iz drugih. Apstrakcija nam pomaže da lakše obradimo
komplikovanije situacije.

To konkretno znači:
 Da bi operacije trebale da se nalaze unutar klasa.
 Da bi funkcionalnosti trebalo da budu ravnomerno distribuirane.
 Da je dobra praksa držati podatke u klasama u kojima su potrebni.

27
Dejan Stuparid, Softverska metrika

 Da metodi unutar klase treba da imaju što je više mogude zajedničkih


argumenata.

2.3.2. Lista disharmonija


U ovom odeljku navešdemo najbitnije disharmonije identiteta, uzroke njihovog
nastajanja, njihovo ponašanje unutar sistema, kao i načine da se one otklone. Takođe
pokazademo koje konkretne metrike nam mogu redi da li je neki softverski entitet
pogođen nekom disharmonijom identiteta.

Slika 3 – Disharmonije Identiteta

Na Slici 3 vidimo šematski prikaz svih disharmonija identiteta koje de biti


obrađene u okviru ovog poglavlja. Sa slike primedujemo da postoje različite relacije
među disharmonijama, kao i da su neke disharmonije slične, a neke različite.
Objasnidemo ukratko neke odnose među disharmonijama:
 Božija Klasa se može manifestovati kao Božija Klasa Forme Podataka, i kao
Božija Klasa Forme Ponašanja
 Klasa Podataka je specijalni slučaj Božije Klase u Formi Podataka
 Mudra Klasa uvek sadrži bar jedan Mudri Metod
 Ukoliko je sekcija izvornog kôda pogođena disharmonijom Mudri Metod, velika
je verovatnoda da ista sekcija sadrži bar neke faktore Znatnog Dupliciranja
 Božija Klasa (obe forme) i Mudri Metod sadrže bar neke činioce disharmonije
Ljubomorni Metod
 Disharmonije Božija Klasa i Mudra Klasa, imaju veliki broj sličnosti među
sobom.

28
Dejan Stuparid, Softverska metrika

2.3.2.1. Božija klasa (eng. God Class)

„One Class to rule them all, and in the darkness bind them.“
„Jedna klasa da vlada nad svima, i u tami ih ujedini“ (13)

Ova disharmonija je jedna od najbitnijih, i srede se u velikom broju softverskih


projekata. To je situacija kada jedna klasa dominira u sistemu, grabedi veliki pocenat
ukupne funkcionalnosti. Ovaj tip klase sam obavlja gro zadataka, i koristi podatke iz
drugih klasa. Samo mali broj minornih aktivnosti delegira se drugim klasama. Ovakvo
ponašanje može da utiče na sposobnost klasa da se ponovo iskoriste, a takođe
otežava algoritamsko razumevanje od strane drugih programera.
Božije klase možemo detektovati slededom šemom u kojoj figuriraju rezultati
metrika u merenom sistemu.

Slika 4 – Šema Božije Klase

Kao što vidimo na Slici 4 disharmonija Božija Klasa mora da ispunjava neke
kriterijume. Mora imati više od nekoliko atributa drugih klasa kojima pristupa, kružna
složenost klase mora biti vrlo veika, a delovi klase moraju biti slabo povezani.

Božija klasa se može susresti u dve različite forme. Prva je forma ponašanja, a
druga forma podataka.

Forma ponašanja je oblik božije klase koja okuplja sve klase koja teži da
preuzme što je više mogude funkcionalnosti drugih klasa. Za razliku od forme
podataka ovakve klase ne sadrže veliki broj podataka drugih klasa, ved se fokusiraju
na funkcionalnosti. Kako bismo pisali kvalitetniji izvorni kôd konstrusisan je set
heuristika čijim pradenjem značajno možemo umanjiti verovatnodu za formiranje
božije klase, dok de nas neke uputiti na mogude klase pogođene ovom
disharmonijom.

29
Dejan Stuparid, Softverska metrika

 Heuristika 1: Pokušajmo da horizontalno distribuiramo informacije o sistemu


ravnomerno na sve klase istog nivoa.
 Heuristika 2: Ne stvarati prekompleksne klase. Posebnu pažnju obratiti na
klase imena kao što je Driver, Manager, System, Subsystem...
 Heuristika 3: Treba obratiti pažnju na klase koje imaju veliki broj javnih
metoda za pristup (get i set metodi). Ovo implicira da se funkcionalnost i
podaci ne drže na jednom mestu, a ovakvo ponašanje treba izbegavati.
 Heuristika 4: Pripaziti na nekomunikativno ponašanje metoda u klasi. Ovakvo
ponašanje se manifestuje kroz metode koji funkcionišu na podskupu atributa
te klase, i ne utiču na druge atribute posmatrane klase.
 Heuristika 5: Kod objektno-orjentisanih modela sa korisničkim interfejsom,
pravilno je da interfejs zavisi od implementacije modela. Nikad ne dozvoliti da
vaš model postane zavistan od interfejsa.

Uvažavanjem gore navedenih karakteristika umnogome demo popraviti dizajn


našeg programa, izbegavademo pravljenje božijih klasa, i iskoristiti sve pogodnosti
objektno-orjentisanog programiranja. Na jednostavnom primeru pokazademo kako,
poboljšati kvalitet dela izvornog kôda, i eliminisati pojave disharmonije Božija Klasa.

Primer: Na Slici 5 vidimo tri klase: Kurs, Student, i IzborKursa. Kako


bismo u IzborKursa dodali novog studenta koristimo metod addStudent(), a
ovaj metod zahteva podatke iz klasa Kurs i Student. Iz klase Student uzimamo
listu kurseva koje student pohađa, a iz klase Kurs dobijamo informaciju da li student
ispunjava potrebne preduslove za pohađanje kursa. Ovakvu funkcionalnost možemo
implementirati na dva načina navedena na slici.

Slika 5 – Primer za Božiju Klasu

Do problema dolazimo jer u oba dizajna kršimo principe objektno-orjentisanog


programiranja, koji kažu da podaci i funkconalnosti ne bi trebalo da se nalaze u jednoj
klasi, jer time onemogudujemo ponovno korišdenje klase (eng. reusing).

30
Dejan Stuparid, Softverska metrika

Kako bismo rešili ovaj problem oslanjamo se na jednu od dve sledede strategije
predstavljene na Slici 6.

Slika 6 – Primer za Božiju Klasu posle jednog refaktorisanja

Prva strategija je da klasa IzborKursa dobije obe liste (kursevi i preduslovi)


kao i da izvršava proveru preko metoda check(). Na ovaj način odvojidemo
funkcionalnost od specifičnog domena podataka i učiniti klasu upotrebljivijom u
nekim drugim situacijama.
Druga strategija se zasniva na uvođenju klase ProvPreduslova koja de biti
zadužena za izvršavanje operacije proveri(). Ova klasa je specijalnog tipa i naziva
se kontroler (eng. controller). Uvođenje kontrolorske klase je prilično česta pojava u
velikim prijektima, jer se na taj način klasi proširuje domen delovanja i mogude je
pozivati je iz drugih klasa. Ali ova strategija ima i lošije strane, jer se na ovaj način
stvaraju dodatne klase koje nemaju veliku funkcionalnost. Stoga je stvaranje
kontrolerskih klasa preporučljivo samo kada radimo sa vedim brojem operacija, pa se
isplati stvarati dodatne klase.

Forma podataka je druga forma božije klase, i ona se najčešde javlja pri
prevođenju starih sistema u neki noviji programski jezik, kao i kod nekih drugih
tehnika refaktorisanja. Znatno je češda pojava da programer obnavlja ved postojedi
sistem, nego da dizajnira potpuno novi, stoga postoji veliko interesovanje da se ova
forma božije klase što efikasnije eliminiše. Glavni problem koji se javlja kod klasa
pogođenih ovom disharmonijom je ne racionalni pristup podacima, tj. potpuno
odsustvo objektno-orjentisanih tekovina. Nemamo nasleđivanje ni pristupanje
objektima neke klase, ved se za svaki pristup podacima piše potpuno nova sekcija
izvornog kôda, što dovodi do znatno komplikovanijih sistema.
Kako bismo bolje ilustrovali ovaj problem navešdemo primer jednog sistema u
Seizmičkom Institutu koji je napisan u proceduralnom jeziku starije generacije, ali je
sticajem okolnosti potrebno prevesti ga u objektno-orjentisan jezik nove generacije.

Na Slici 7 vidimo trivijalizaciju ovoga sistema u početnom stadijumu (u


proceduralnom jeziku). Kao što vidimo na slici isečak našeg programa se sastoji od
jedne sveprisutne klase (KlasaZaObraduSeizmickihAktivnosti), u kojoj se

31
Dejan Stuparid, Softverska metrika

nalazi veliki broj podataka. Klasa takođe sadrži i veliki broj operacija (operacije
funkc1() do funkc7()), koje na različiti način manipulišu podacima iz iste klase.
Sistem u sadašnjem stanju ne predstavlja reprezentativan primer dobrog stila
programiranja, i stoga ga treba refaktorisati.

Slika 7 – Primer Božije Klase forme podataka

Kada je razvojni tim počeo obnovu sistemu prvo su dodali getere i setere za sve
podatke koji postoje u modulu KlasaZaObraduSeizmickihAktivnosti, i na
taj način otklonili opasnost da se podacima pristupa direktno. Potom su podelili
funkcije koje pristupaju podacima na grupe i smestili ih u četiri kontrolorske klase, na
ovaj način omogudeno je da se metodi mogu ponovo koristiti jednostavnim pozivima.
Ovakav dizajn je svakako korak u pravom smeru, ali svakako nije idealno rešenje.

32
Dejan Stuparid, Softverska metrika

Slika 8 – Božija Klasa forme podataka posle jendog refaktorisanja

Iako smo završili sa prvom sesijom refaktorisanja naš program još uvek sadrži
Božiju Klasu, a ona još uvek sadrži sve podatke, i svi metod zavise od nje. Takođe
kontrolerske klase stvaraju dilemu, jer demo znatno manje vremena i truda uložiti
ukoliko ih implementiramo kao na slici, ali de one tada kršiti pravilo o ne držanju
podataka i operacija u istoj klasi.

Slika 9 – Finalna verzija Božije Klase forme podataka

Kao konačnu verziju uzimamo model isečka sistema sa Slike 9. U ovom modelu
klasa KlasaZaObraduSeizmickihAktivnosti je podeljena tako da opslužuje

33
Dejan Stuparid, Softverska metrika

svaku od klasa Seizmika. Dok su metodi grupisani po podskupu podataka koji


koriste u odgovarajudoj Seizmika klasi.

U Izvornom Kôdu 1 navodimo reprezentativne isečke izvornog kôda jedne klase


koja je klasičan primer Božije Klase. Svrha ovog primera je da pokaže koje
karakteristike može da sadrži neka klasa sa ovim tipom disharmonije.

import Class1.*;
import Class2.*;

class GodClass extends Class9 implements Class8 {


...
public int s;
public String n;
public String k;
public Calendar c;
...
public GodClass(int s, int p, Date m){
this.t = s;
super(p,m)
}
public GodClass(){
...
}
...

public String get_name(){


...
t = new Class1.getInstance();
t.get_name;
return t;
}
public void set_name(String n){
...
t = new Class1.getInstance();
t.set_name(n);
}
....
public int listName(ClassType1 cs1, ClassType2 cs2,....){
if (cs2! = null){
List<Class1> lcs1 = get_name();
}
}
...
}
Izvorni Kôd 1 – Primer Božije Klase

Na ovome primeru vidimo prekomernu komplikovanost klase GodClass koja


proističe iz prevelikog broja podataka, pozivanja promenljivih iz drugih klasa,
polimorfizma… Ali takođe dosta toga i ne vidimo, jer je prava osobenost Božije Klase

34
Dejan Stuparid, Softverska metrika

ponavljanje operacija koje se međusobno pozivaju. Na primeru vidimo tek


nagoveštaje kako bi Božija Klasa mogla da izgleda ukoliko joj dopustimo da raste.

2.3.2.2. Ljubomorni Metod (eng. Feature Envy)

Ova disharmonija se odnosi na metode koji su više orjentisani na podatke


drugih klasa, nego na one iz klase u kojoj se nalaze. Ovakvi metodi pristupaju direktno
ili preko get i set metoda atributima drugih klasa.

Slika 10 – Šema Ljubomornog Metoda

Kako bismo detektovali Ljubomorni Metod, pribegavamo brojanju atributa


kojima mereni metod pristupa. Kao što vidimo sa šeme mereni metod treba direktno
da koristi bar dva atributa stranih klasa. Takođe metod koji je pogođen ovom
disharmonijom koristi tek nešto manje od tredine atributa iz klase u kojoj se nalazi. I
na kraju po tredoj klauzoli korišdeni atributi ne smeju da se nalaze u više od dve klase.
Treda klauzula je bitna iz razloga što pomodu nje parvimo razliku između
disharmonije Mudri Metod i Ljubomorni Metod. Ako imamo metod koji koristi
atribute samo nekoliko klasa, postoji mogudnost da je on postavljen u pogrešnu klasu,
i smatrademo da je pogođen disharmonijom Ljubomorni Metod. Ukoliko metod
pristupa podacima iz mnoštva klasa imamo kompleksniju situaciju, i o njoj demo više
pričati u poglavlju o disharmoniji Mudri Metod.

Postoje i dva alternativna načina za otkrivanje metoda pogođenih


Ljubomornim Metodom:
1. Brojanje svih zavisnosti: Umesto da brojimo strane atribute, možemo da
brojimo zavisnosti iz drugih klasa koje se odnose na sve članove posmatranog
metoda. Na ovaj načina možemo sa istom efikasnošdu otkriti nedostatke kao i
korišdenjem principa brojanja atributa.

35
Dejan Stuparid, Softverska metrika

2. Ignorisanje disperzije: Ukoliko ignorišemo ograničenje da atribute treba tražiti


samo u nekoliko različitih klasa, možemo dodi do metoda koji preterano
koriste atrubute drugih klasa i pokušademo da ih izmestimo na drugu lokaciju.

Navedimo jedan vrlo jednostavan isečak izvornog kôda (Izvorni Kôd 2)


pogođenog Ljubomornim Metodom.

class Kupovina(){
public Cena c;
public cena() {
c = Proizvod.vrednost + Proizvod.porez + Prodavac.marza
}
}
Izvorni Kôd 2 – Primer Ljubomornog Metoda

U primeru vidimo metod cena() koji se nalazi u klasi Kupovina, ali koristi
isključivo atribute klasa Proizvod i Prodavac. Metod sa ovakvim
karakteristikama i u ovakvom okruženju je najlakše premestiti u drugu klasu, a u
našem slučaju bi to bila klasa Proizvod jer se njaviše atributa koristi upravo iz te
klase.

Za rešavanje ovog problema postoji naizgled vrlo prosta strategija.


Jednostavno premestimo metod koji teži da bude u drugoj klasi u klasu u kojoj želi da
bude. Ali nažalost u realnom svetu situacija često nije ovako jednostavna. Možemo
imati metod koji koristi podjednak broj metoda iz dve strane klase, pa ostajemo u
dilemi u koju od te dve ga premestiti. Ili postoji mogudnost da je metod čvrsto sparen
sa drugim metodima koji se nalaze u klasi, pa bi se njegovim premeštanjem morali i
oni menjati ili premeštati.
Kada se razmotre sledede pojave i njihove implikacije, dolazimo do zaključka
da se rešavanje ovog problema uglavnom ne svodi na puko premeštanje, ved je
potrebno uporedno korišdenje više tehnika refaktorisanja.

2.3.2.3. Klasa Podataka (eng. Data Class)

Ovaj vid disfunkionalnosti izvornog kôda se odnosi na klase koje služe gotovo
isključino kao kontejneri za podatake. Ovakve klase su sukp podataka kojima druge
klase pristupaju, i od funkcionalnosti sadrže samo metode za pristup (get i set
metodi). Odvajanje podataka od funkcionalnosti je kršenje principa enkapsulacije, jer
su klase koje sadrže metode primorane da koriste atribute klasa koje sadrže podatke.
Tanka je linija između disharmonije Klasa Podataka i forme podataka Božije
Klase, kao glavnu razliku uzimamo to što Božija Klasa teži da pokupi sve podatke do
kojih može da dođe, dok su Klase Podataka više lokalizovane. Tako da Klasa Podataka
ne mora biti ogromna klasa koja sadrži stotine atributa, kojima pristupa na desetine

36
Dejan Stuparid, Softverska metrika

različitih metoda. To može biti i manja klasa u kojoj ne postoji gotovo nikava
funkcionalnost sem metoda za pristup podacima.

Na Slici 11 predstavidemo šemu uz pomod koje demo modi da detektujemo


veliki broj kandidata za Klase Podataka.

Slika 11 – Šema Klase Podataka

Počedemo tako što demo izbrojati koliko se javnih atributa (metrika NOPA) i
metoda za pristup (metrika NOAM) nalazi unutar klase na koju primenjujemo
metrike. Ukoliko je njihov zbir vedi od NEKOLIKO, možemo nastaviti ka slededem
algoritamskom koraku. Potrebno je da izmerimo kružnu složenost svih metoda te
klase (metrika WMC) i ukoliko je ona manja od VISOKO imamo ispunjene sve
formalne zahteve za Klasu Podataka. Na kraju uvodimo i dodatan neformalan korak,
kvalifikovana osoba izdvaja klase kandidate koje su prošle prva dva kruga i analizira ih
kako bismo utvrdili da li ispunjavaju zahteve disharmonije, i da li su mogle drugačije
da se implementiraju.

Za klase zaražene ovom disharmonijom postoji jedina logična strategija za


eliminisanje. Uzedemo podatke iz klasa i postaviti ih u klase u kojima se koriste. Ovo
rešenje izgleda previše jednostavno da bi bilo univerzalno. Naime, dolazidemo do
slučajeva kad se istom podataku pristupa iz dve i više klasa pa demo se nalaziti u
nedoumici u koju klasu da ga premestimo. Nekad demo imati situaciju da se u klasi
nalazi metod koji obavlja neku jednostavnu operaciju nad podacima, i njegovim
premeštanjem stvoridemo dodatno sparivanje klasa u sistemu. Pri refaktorisanju
ovakvih sistema neophodno je da imamo uvid u celokupan sistem kako ne bismo došli
u situaciju da pravimo izmene koje de otežati razumevanje programa u celosti.

2.3.2.4. Mudra Klasa (eng. Brain Class)

37
Dejan Stuparid, Softverska metrika

Kada klasa sadrži preveliki broj metoda koji obavljaju prevelik broj funkcija
dolazimo do disharmonije Mudra Klasa. Mudra Klasa je gotovo uvek centralna klasa
sistema i sadrži, veliki broj linija izvornog kôda. Mudra Klasa takođe gotovo uvek
sadrži Mudri Metod (disharmonija kojom demo se kasnije pozabaviti), a u ekstremnim
slučajevima može da sadrži više Mudrih Metoda. Ova disharmonija se često meša sa
Božijim Klasama forme ponašanja, u neku ruku slično kao slučaj Klase Podataka i
forme podataka Božije Klase.
Glavna razlka je u tome što Mudre Klase nisu toliko agresivne kao Božije Klase,
ne pristupaju velikom broju podataka drugih klasa, i ređe se zatrpavaju ogromnom
funkcionalnošdu na ograničenom skupu podataka.

Na Slici 12 navešdemo strategiju za detektovanje ovakvih klasa.

Slika 12 – Šema Mudre Klase

Sa šeme lako uočavamo dva različita načina za detektovanje Mudre Klase,


situaciju sa jednim i situaciju sa više Mudrih Metoda. Zajedničko u obe situacije je to
što demo proveravati da li klasa ved spada u kategoriju Božija Klasa.

Ukoiliko imamo samo jedan Mudri Metod on mora biti izrazito dugačak i
kompleksan, čak dva puta vedi od utvrđenih graničnih vrednosti za veoma duge i
kompleksne metode. Metodi sa ovakvim karakteristikama su uglavnom odraz ne

38
Dejan Stuparid, Softverska metrika

poštovanja dobre prakse u objektno-orjentisanim jezicim, mada postoje situacije


kada su ovakvi metodi jedino mogude rešenje (na primer metod za parsiranje teksta
je uvek velik i kompleksan).
Druga sitacija je postojanje više od jednog Mudrog Metoda. Tada metodi ne
moraju da budu izrazitio kompleksni kao u prethodnoj situaciji, jer de brojnošdu
nadomestiti nedostatak kompleksnosti.

Najbolji lek za ovu disarmoniju je da pokušamo da podelimo metod na više


smislenih celina (ukoliko imamo klasu sa jednim Mudrim Metodom) koja de zdržarti
određeni stepen autonomije. A ukoliko imamo klasu sa više Mudrih Metoda logično je
da pokušamo da neke od njih premestimo u druge klase. Ovakav pristup uglavnom
nije jednostavan proces, pa demo imati dosta strateških odluka i kompromisa o
bududoj arhitekturi sistema.

2.3.2.5. Mudri Metod (eng. Long Method)

Disharmonija Mudri Metod (u literaturi poznata i kao Dugi Metod – eng. Long
Method) se nalazi u srcu Mudre Klase, koju smo obradili u prethodnom odeljku.
Mudri Metod je metod koji je po definiciji izrazito kompleksan, koristi veliki broj
promenljivih i ima veliki broja linija izvornog kôda. (4)

Slika 13 – Šema Mudrog Metoda

Na Slici 13 vidimo šemu preko koje možemo otkriti gotovo sve metode
zaražene disharmonijom Mudri Metod. Kako bismo neki metod svrstali u ovu
kategoriju on mora da ispunjava sledede uslove: Mora imati izrazito veliki broj linija

39
Dejan Stuparid, Softverska metrika

izvornog kôda, veliku kružnu složenost (koja nekad prevazilazi kružnu solženost 5 - 8
klasičnih metoda), veliki broj pristupa rezličitim promenljavama (uglavnom se uzima
vrednost od bar 8 promenljivih), i više pristupa promenljivama direktno nego preko
metoda za pristup.

Za uklanjanje disharmonije Mudri Metod, je u 98% slučajeva dovoljno prosto


deljenje metoda na celine koje obavljaju neku funkcionalnost. Mada postoje situacije
kada je ovako nešto nemogude ili teško izvodljivo, činjenica je da su ti slučajevi su
izrazito retki. Stoga se ovde može govoriti o uniformnoj strategiji za rešavanje
problema Mudrog Metoda.

Kada se mlađi programer upoznaje sa objektno-orjentisanim stilom


programiranja (ako je program napisan po konvencijama), često de se pitati gde se
zaista obavlja računanje, jer se naizgled susrede samo sa beskrajnim delegiranjem
odgovornosti sa metoda na metod. Ovakvi kratki metodi, i njihovo pozivanje su prava
vrednost objektno-orjentisanog stila programiranja, jer znatno poboljšavaju čitljivost
programa, i umanjuju protrebu za komentarisanje izvornog kôda. Posebnu pažnju pri
korišdenju velikog broja kratkih metoda treba obratiti na imenovanje tih metoda, jer
ovaj naizgled mala stvar može znatno poboljšati čitljivost našeg programa.

2.3.2.6. Znatno Dupliciranje (eng. Significant Duplication)

Vrlo česta pojava pri Copy-Paste-Modify programiranju (kopiranje jedne sekcije


izvornog kôda na drugo mesto sa vrlo malim izmenama) je dupliranje izvornog kôda.
Dešava se da programeri jednostavno kopiraju čitave metode i klase kako bi olakšali
posao, ali ovom praksom znatno otežavaju snalaženje u izvornom kôdu i umanjuju
njegovu efikasnost. (7)

Ključni koncept koji se javlja u radu sa disharmonijom Znatno Dupliciranje je


određivanje šta je zapravo duplicirani izvorni kôd, a šta ne. Kao i prirodni jezici i
programski jezici se sastoje od reči i rečenica koje koristimo više puta. Pre nego što
neki deo izvornog kôda označimo kao duplikat, on mora da prelazi prag obimnosti koji
smo utvrdili. Takđe uzimamo u obzir da je izvorni kôd možda modifikovan, pa
duplikate moramo tražiti u celom sistemu, a ne samo u „obližnjim“ sekcijama
izvornog kôda.

Znatno Dupliranje detektujemo pomodu sledede šeme na Slici 14.

40
Dejan Stuparid, Softverska metrika

Slika 14 – Šema Znatnog Dupliciranja

Vidimo da se detekcija može podeliti na dve strategije. Prva strategija se


odnosi na duplikate koji figuriraju kao celina; tj. tražidemo sekciju dupliciranog
izvornog kôda koji je vedi od granične vrednosti (za graničnu vrednost uzeli smo
prosečan broj linija izvornog kôda u metodu).
Druga strategija je nešto kompleksnija i odnosi se na lančano dupliciranje. Prvo
utvrđujemo da li naš lanac prelazi granicu relevantnosti (SDC je bar dva puta vedi od
prosečnog broja linija izvornog kôda u metodu). Zatim proveravamo da li je svaka
karika dovoljno velika, da ne bismo pod dupliciranje svrstali neke standardne jezičke
konstrukcije. I na kraju proveravamo da li je udaljenost između dve karike našeg lanca
u predviđenim granicama (ne više od 3 - 6 linija izvornog kôda).

Kao vodič za eliminisanje ove disharmonije uzmimo slededu rečenicu.

“Eliminacijom duplikata, osiguravamo da naš izvorni kôd sve


kaže jednom i samo jednom, a to je osnova dobrog dizajna.”

(eng. “By eliminating the duplicates, you ensure that the


code says everything once and only once, which is the
essence of good design.”)(17)

Stoga kada refaktorišemo izvorni kôd koji je dupliciran pokušavamo da


eliminišemo duplikat i zamenimo ga pozivom orginalne sekcije izvornog kôda, ili
pokušavamo da duplikat spojimo orginalom modifikujudi oba, dok zadržavamo
funkcionalnost. Kada Značajno Dupliciranje pogađa hijerarhiju klasa, pravilo je da se

41
Dejan Stuparid, Softverska metrika

original postavi u klasu roditelj, a da se iz nasledničke klasa original koristi


pozivanjem.
Navedimo jedan primer (Tabela 6) dupliciranog izvornog kôda u prvoj koloni, a
u drugoj koloni imademo izvorni kôd koji je prerađen tako da eliminiše pojave
disharmonije Znatno Dupliciranje.
Prođimo ukratko kroz primer.
 U prvom delu tabele vidimo izvorni kôd u levoj koloni koji nije refaktorisan,
vidimo da se uslovna naredba koristi dva puta sa potpuno istim istim uslovnim
izrazom. Ovo je loša praksa, bespotrebno otežavamo razumevanje izvornog
kôda, i povedavamo kompleksnost. Sa druge strane u desnoj koloni vidimo
poboljšano rešenje nastalo refakorisanjem kako bismo eliminisali disharmoniju
Znatno Dupliciranje.
 U levoj koloni drugoog dela imamo tri metoda koja obavljaju istu
funkcionalnost, ali za različiti tip podataka. Imamo veliku količinu dupliciranog
izvornog kôda, a to možemo popraviti refaktorisanjem. Stoga u desnoj koloni
navodimo izvorni kôd u kojem koristimo polimorfizam kako bismo eliminisali
duplicirani izvorni kôd.

Ne refaktorisano Refaktorisano
if (student.ime = Goran){ if (student.ime = Goran){
kurs1.add(student); kurs1.add(student);
} kurs2.add(student);
if (student.ime = Goran){ }
kurs2.add(student);
}
public findManager { public find(type){
for (employee e : Employees){ for (employee e :
if (e.isManager){ Employees){
return e; if (e.isType(type)){
} else { return e;
return nil; } else {
} return nil;
} }
} }
}
public findWorker{
for (employee e : Employees){
if (e.isWorker){
return e;
} else {
return nil;
}
}
}

public findTester {
for (employee e : Employees){
if (e.isTester){

42
Dejan Stuparid, Softverska metrika

return e;
} else {
return nil;
}
}
}
Tabela 6 – Primer Znatnog Dupliciranja

2.3.3. Rezime
Disharmonije identiteta je uglavnom najlakše pronadi od svih disharmonija.
One su najčešde izdvojene i ne zavise jedna od druge, pa ih je pomodu odgovarajude
statistike i definicije lako prepoznati.
Kada otklanjamo disharmonije identiteta potrebno je voditi se listom prioriteta
kako bismo lakše i efikasnije eliminisali što je mogude više zaraženih entiteta.
Navedimo listu prioriteta:
 Obratimo pažnju na klase kod kojih je više od jednog metoda zaraženo
nekom disharmonijom.
 Zatim prelazimo na analizu klasa kod kojih postoji više od jedne
disharmonije identiteta.
 Prioritet imaju i klase koje su pogođene drugim tipovima disharmonija
(disharmonije saradnje ili klasifikacje).

Navedimo korake u procesu eliminacije disharmonija identiteta:


1. Korak 1: Prvo demo obraditi klase pogođene defektima Božija Klasa i
Mudra Klasa.
2. Korak 2: Zatim je potrebno prekontrolisati sve klase iz Koraka 1 i
testirati njihove metode na disharmonije Mudri Metod, Znatno
Dupliciranje i Ljubomorni Metod.
3. Korak 3: Testirajmo metode iz Koraka 2 na ostale disharmonije
identiteta.

Kada smo uspostavili hijerarhiju prioriteta potrebno je izvršiti konkretno


refaktorisanje, čime demo eleminisati nedostatke u klasama pogođenim
disharmonijama identiteta.

2.4. Disharmonije Saradnje


U ovom poglavlju pričademo o Disharmonijama Saradnje. Za razliku od
predhodnog poglavlja ovog rada gde smo se bavili disharmonijama koje su se

43
Dejan Stuparid, Softverska metrika

odnosile na konkretne entitete u izvornom kôdu, ovde demo se fokusirati na odnose


među entitetima, i na oblike saradnje (ili ne saradnje) među njima.
Disharmonije saradnje su čvrsto povezane sa pojmom sparivanja (coupling).
Ovaj pojam je jedan od ključnih u objektno-orjentisanoj programerskoj paradigmi.
Sparivanje definišemo kao nivo zavisnosti svakog metoda od metoda i klasa iz
okruženja.

Najčešde dolazimo u kontakt s dva tipa sparivanja: Čvrsto sparivanje i labavo


sparivanje. Navedimo neke prednosti i mane:
 Čvrsto sparivanje uglavnom uzimamo kao negativnu osobinu. Navešdemo
negativne pojave koje nastaju kao posledice čvrstog sparivanja:
1. Promena u jednoj klasi često prouzrokuje potrebu za izmenama u
nizu drugih klasa.
2. Okupljanje metoda u određenu klasu iziskuje više rada zbog velike
međusobne povezanosti.
3. Otežano je ponovno korišdenje metoda, jer ga moramo preuzeti
zajedno sa metodom sa kojim je sparen.
4. Veliki rizik od pojave sporednih efekata (eng. Side Effect).
 Labavo sparivanje posmatramo kao dobru programersku praksu, zbog
pozitivnih konotacija koje idu uz njega:
1. Promene u jednoj klasi nemaju uticaj na druge klase.
2. Metodima lakše pronalazimo klase-kontejnere.
3. Olakšano je ponovno korišdenje metoda, jer ne postoje zavisni metodi
koje takođe treba uvoziti.
4. Mali rizik od pojeve sporednih efekata (eng. Side Effect).

Dobra saradnja među članovima programa (klase, metodi…) je esencijalna, jer


de nam savršeni pojedinačni entiteti malo vredeti ukoliko je komunikacija među njima
manjkava.

Navedimo pravilo saradnje koje de nam biti ideja vodilja u ovoj sekciji rada.

2.4.1. Pravila Harmonije


Jedino pravilo koje demo obraditi u ovom segmentu je pravilo saradnje među
entitetima objektno-orjentisanog sistema.(1)

2.4.1.1. Pravilo saradnje

Saradnju među entitetima bi trebalo ograničiti na pozive metoda. Takođe


treba biti obazriv da ne pozivamo previše, da ne pozivamo previše iz jedne klase, i da
ne pozivamo iz svih delova sistema.

44
Dejan Stuparid, Softverska metrika

Pravilo važi za oba smera pozivanja. Ukoliko klasa poziva previše metoda
drugih klasa postaje ranjiva na probleme koje pogađaju te klase. Sa druge strane, ako
previše klasa koristi metod merene klase ona postaje pre-odgovorna, pa se greška u
ovakvoj klasi može osetiti na velikom broju drugih klasa. Veliki broj poziva nekoj klasi
može da znači i veliki potencijal za ponovno korišdenje, ali to zavisi od stabilnosti
klase koju koriste druge klase.
Veliku pomod u saradnji među entitetima pružaju interfejsi. Oni omoguduju da
se sakriju podaci o implementaciji neke operacije, i dozvoljavaju pristup samo nekim
servisima odgovarajude klase.

Navedimo uputstva koja treba pratiti kako bismo izbegli disharmonije


saradnje:
 Ograničimo intenzitet saradnje – Ne želimo klasu koja de samo pozivati
metode drugih klasa. Ovakvu klasu možemo lako eliminisati.
 Ograničimo broj servisa koje proizvodimo – Ne želimo klasu sa kojom de
komunicirati vedina drugih klasa. Ovako otvaramo vrata velikom broju
grešaka.
 Ograničimo razuđenost poziva u sistemu – Ne želimo klasu koja ne poštuje
hijerarhiju unutar sistema. – Ne sme svaka klasa pozivati svaku klasu.

2.4.2. Lista disharmonija


U okviru skupa disharmonija saradnje navešdemo šest klasičnih primera
poremedaja saradnje među entitetima objekjtno-orjentisanog programa. Govoridemo
o disharmonijama: Prevelika Intimnost, Lanac Delegiranja, Posrednik, Operecija
Sačma i Divirgentna Promena. Neke od ovih disharmonija su srodne među sobom i
veliki deo svog indentiteta duguju jedna drugoj, ali su različite u ključnim detaljima,
pa predstavljaju zaseban obrazac ponašanja.

45
Dejan Stuparid, Softverska metrika

Slika 15 – Disharmonije Saradnje

Na Slici 15 vidimo šemu disharmonija saradnje koje de biti obrađene unutar


ovog poglavlja. Primetimo tri različite grupacije disharmonija saradnje:
 Disharmonije Lanac Delegiranja i Posrednik su vrlo slične, jer obrađuju dva
ekstremna slučaja jedne te iste pojave – delegiranja odgovornosti.
 Sa druge strane disharmonije Operacija Sačma, i Divirgentna Promena postoje
na istom domenu, ali obrađuju suprotne aspekte.
 Disharmonija Prevelika Intimnost nije specijalno vezana ni za jednu od
navedene dve grupacije. Ali zato predstavlja najbitniju disharmoniju saradnje,
jer se prevashodno bavi problematikom čvrstog sparivanja.

2.4.2.1. Prevelika Intimnost (eng. Inappropriate Intimacy)

Prevelika Intimnost je vrlo slična disharmoniji identiteta Ljubomorni Metod,


razlika je u tome što se prva odnosi na klase, a druga na metode. Ova disharmonija
označava klase koje dele previše informacija među sobom, i na taj način obezvređuju
koncept enkapsulacije. Kada su klase zaražene disharmonijom Prevelika Intimnost,
one sigurno spadaju u grupu čvrsto sparenih klasa, što je samo po sebi negativna
karakteristika.
Enkapsulacija je jedan od osnovnih koncepata objektno-orjentisanog
programiranja, i ona od nas zahteva da konstruišemo komponente programa na što je
mogude manje zavisan način jedan od drugog. Ukoliko naše klase poštuju ovaj
koncept, i ne znaju o drugim klasama više nego što je neophodno, naš de izvorni kôd
biti stabilniji, svrsishodniji i pogodniji za ponovno korišdenje.

Preveliku intimnost detektujemo pomodu sledede šeme na Slici 16.

46
Dejan Stuparid, Softverska metrika

Slika 16 – Šema Prevelike Intimnosti

Prvo demo ograničiti metrike tako da posmatraju samo jedan par klasa, kako
bismo mogli da dobijemo sliku o intimnosti te dve klase. Izmeridemo broj stranih
atributa koji se koriste u merenoj klasi, kao i broj metoda koji se pozivaju iz metoda
na koji je primenjena metrika. Ukoliko ove mere prevazilaze navedene pragove
postoji velika verovatnoda da imamo neki vid disharmonije Prevelika Intimnost. Na
kraju proverimo i da li postoje javni metodi koji nisu definisani u interfejsu klase, a
pristupa im se iz merene klase.

Šta konkretno znači nedostatak enkapsulacije, tesno sparivanje i postojanje


disharmonije Prevelika Intimnost? Znači da naš korisnički interfejs (eng. UI) ne bi
trebao da zna na koji način sloj pristupa podataka (eng. Data Access Layer - DAL)
pristupa podacima. Poslovni sloj (eng. Busines Object Layer - BO) ne bi trebao da zna
da UI pristupa SharePoint-u u svrhu pretrage podataka. Nijedan drugi sloj sem DAL-a
ne bi trebao da zna da kao bazu koristimo MySQL.
Primeri koje smo naveli samo su ilustracija šta treba izbegavati kako bismo
imali kvalitetan sistem. Najbolji način da ostvarimo ovakvu harmoničnost je da
pristup resursima klasa ograničimo isključivo na pristup preko inrerfejsa. Potrebno je
konstruisati interfejs za svaku klasu koja ostvarauje bilo koji vid komunikacije sa
okolinom. Tako na primer imamo klase StudentAdresaDALImpl, SudentAdresaBOImpl
i StudentAdresaUIImpl koje se nalaze u različitim slojemima aplikacije.
Konstruisademo interfejse StudentAdresaDAL, StudentAdresaBO, StudentAdresaUI
koji de biti odgovorni za svu horizontalnu i vertikalnu komunikaciju ovih klasa, i oni de
biti jedini pravilan način za pristup tim klasama. Ovako demo eliminisati najvedi broj
pojava disharmonije Prevelika Intimnost.

Na slededem primeru (Izvorni Kôd 3) videdemo kako bi trebao da izgleda jedan


kvalitetan interfejs koji ograničava pristup informacijama iz klase u kojoj se nalaze
metodi, ali takođe pruža uvid u sve neophodne informacije o tim metodima.

47
Dejan Stuparid, Softverska metrika

public interface StudentAdresa{

String getAddressLine();
String setAddressLine();
String getCity();
String setcity();
String getState();
String setState();
String getZip();
String setZip();
bool isPrimary();
bool isMailing();
void DataBind();
void Validate();
}
Izvorni Kôd 3 – Primer dobro organizovanog interfejsa

2.4.2.2. Operacija Sačma (eng. Shotgun Surgery)

Kada objašnjavamo ovu disharmoniju imajmo na umu da je mnogo teže


napraviti izmenu ukoliko to moramo da radimo na nekoliko različitih mesta. Upravo
se definicija disharmonije Operacija Sačma zasniva na ovom principu. Održavanje i
razumevanje izvornog kôda je znatno otežano ukoliko promena bilo koje
funkcionalnosti zahteva izmenu velikog broja metoda u različitim klasama. Idealna
situacija bi bila kada bi sve promene mogle biti izvršene na jednom mestu (u jednom
metodu), bez dodatnih modifikacija i sporednih efekata.
Disharmoniju Operacija Sačma detektujemo pomode šeme na Slici 17.

Slika 17 – Šema Operacije Sačma

Sa šeme vidimo da u detekciji figuriraju samo dva faktora: broj poziva ka


merenom metodu – preko vrednosti metrike CM, i broj klasa koje služe kao
kontejneri za metode koji pozivaju posmatrani metod – preko vrednosti metrike CC.

48
Dejan Stuparid, Softverska metrika

Znamo da je prekomeran broj poziva ka metodu otežavajuda okolnost za razumevanje


funkcionalnosti sistema. Teško je upamtiti koje sve operacije treba izmeniti, stoga je
neminovnost zaboravljanje pojedinih izmena. Ako još pritom metodi koje treba
menjati dolaze iz znatnog broja različitih klasa, dolazimo do situacije da je gotovo ne
mogude izvršititi sve promene bez detaljnog debagovanja izvornog kôda. Ovakav
način rada je neizbežno zamoran, i ubija kreativnost.
U disharmoniji Operacija Sačma težimo da okupimo klase čija de izmene (i
eventualna greška pri izmeni) uticati na što vedi broj klasa. Tako da uzimamo u obzir i
čvrstinu sparivanja entiteta izvornog kôda, kao i rasprostranjenost njihovog
sparivanja u sistemu.

Kako rešavati probleme koji se odnose na disharmoniju Operacija Sačma:


 Premeštanjem metoda koje poziva posmatrani metod u klasu u kojoj se nalazi
posmatrani metod. Ovaj sistem je izrazito koristan za kratke metode male
kružne složenosti, koji se nalaze u klasama koje prete da postanu Klase
Podataka.
 Posebnu pažnju treba obratiti na kompleksne metode (koji teže da postanu
Mudri Metodi) jer su uglavnom zaraženi ovom disharmonijom. Potrebno je
analizirati ih i sprovesti neki oblik refaktorisanja (podela na nekoliko metoda,
smanjenje broja operativnih atributa…)
 Kreiranje dodatne klase koja de sadržati metode koje poziva metod na koji
primenjujemo metriku. Ovaj način koristiti samo kad nijedna od ved postojedih
klasa nije odgovarajudi kontejner za te metode.

2.4.2.3. Divirgentna Promena (eng. Divergent Change)

Ova disharmonija je suprotnost Operaciji Sačma, ali je takođe vrlo srodna toj
disharmoniji. Divirgentna Promena je ponašanje koje se manifestuje čestom
promenom jedne klase na različite načine u različite svrhe. To znači da demo
modifikovati veliki broj metoda jedne klase, za razliku od situacije u Operaciji Sačma
kada smo menjali veliki broj metoda različitih klasa.
Divirgentna Promena je logična posledica čvrstog sparivanja. Kako su naši
objekti čvrsto povezani među sobom, pojavljuje se veliki broj referenca na njih, što
dovodi do velikog posla ukoliko je potrebno nešto izmeniti.

Na Slici 18 vidimo šemu Divirgentne Promene

49
Dejan Stuparid, Softverska metrika

Slika 18 – Šema Divirgentne Promene

Strategija detekcije je gotovo identična onoj kod Operacije Sačma, stim što
imamo malu ali izuzetno bitnu razliku – pozivani metodi su ograničeni na klasu u kojoj
se nalazi posmatrani metod. Naša detekcija de se svesti na potragu za kompleksnim
metodom koji poziva veliki broj metoda iz sopstvene klase.

Ovakvo ponašanje neizbežno dovodi do situacije da bilo kakva izmena zahteva


ekstenzivan rad na velikom broju metoda. Na primer, promena stanja baze podataka
koja zahteva tri izmene podataka de nas primoratavati da konstantno izvršavamo iste
tri promene na ista tri metoda. Takođe i promena tipa podataka nekog atributa
prouzrokovade potrebu za izmenom u svim metodima koji koriste taj atribut.

2.4.2.4. Lanac Delegiranja (eng. Delegation Chain)

Ova disharmonija se odnosi na jedan konkretan primer koji se dosta često


susrede u programiranju i može znatno da oteža razumevanje programa. Naime pri
pozivu neke funkcionalnosti iz metoda ili atributa neke klase, često moramo da
prođemo kroz dugačak niz poziva kako bismo došli do tražene informacije. Najčešde
prolazimo kroz nizove get i set metoda, koji su međusobno povezani zajedničkim
atributom. Ova disharmonija sama po sebi nije alarmantna pojava, ali se može
pojaviti unutar bilo koje disharmonije i time pogoršati ved lošu situaciju. Stoga je
dobrar stil programiranja izbegavati duge lance delegiranja kako bismo olakšali
razumevanje programa.

Disharmonije Lanac Delegiranja možemo pronadi pomodu sledede šeme.

50
Dejan Stuparid, Softverska metrika

Slika 19 – Šema Lanca Delegiranja

Na Slici 19 vidimo šemu koja nam na vrlo jasan način objašnjava koje pojave
možemo podvesti pod kategoriju Lanac Delegiranja. Takođe ni uzetu graničnu
vrednost nije potrebno dodatno objašnjavati, jer svakako ne želimo lanac poruka koji
ne možemo da zapamtimo.

U Izvornom Kôdu 4 vidimo primer jednog niza delegiranja

a.getCountry().getGroupOrganization().getOrganizationId().getTeamId(
).getTeamMemberId().getTeamMemberAddress().setZipCode();
Izvorni Kôd 4 – Primer Lanca Delegiranja

Složidemo se da ovakav niz nije najpregledniji, i da je vrlo teško zapamtiti sve


korake koje moramo prodi kako bismo došli do konkretnog polja koje nam je
potrebno.

U Izvornom Kôdu 5 vidimo refaktorisanu verziju u kojoj smo eliminisali neke


korake kako bismo došli do optimalnog lanca delegiranja.

getOrganizationShort =
getCountry().getGroupOrganization().getOrganizationId();
getTeamMemberShort =
getTeamId().getTeamMemberId().getTeamMemberAddress();
a.getOrganizationShort().getTeamMemberShort().setZipCode();
Izvorni Kôd 5 – Lanac Delegiranja posle refaktorisanja

U Izvornom Kôdu 5 zamenili smo dva česta niza delegiranja kradim nizovima, i
na taj način napravili program čitljivijim. Kao što vidimo ni jedan od tri niza
delegiranja koje koristimo u primeru nema više od tri člana, stoga su naši nizovi laki za
pamdenje.

2.4.2.5. Posrednik (eng. Middleman)

Disharmonija Posrednik je u neku ruku suprotnost disharmoniji Lanac


Delegiranja. Naime ovde se radi o klasi čiji se najvedi deo funkcionalnosti odnosi na
delegiranje odgovornosti ka drugim klasama. Drugim rečima radi se o skupu jezičkih
konstrukcija navedenih u primeru Lanca Delegiranja koje de nam skratiti lanac i time

51
Dejan Stuparid, Softverska metrika

olakšati razumevanje. Ovakve jezičke konstrukcije same po sebi ne predstavljaju


problem, ved je problem u eventualnom izostanaku funkcionalnosti u ostatku klase.
Kod Lanca Delegiranja uobičajeno je da se polja koja skraduju lanac nalaze u istoj
klasi, dok nagomilavanje ovakvih polja dovodi do specifičnog problema, tj.
disharmonije Posrednik.
Još jedna osobenost ovakvih klasa je da reimenuju metode drugih klasa i
prosleđuju ih tredim klasama na korišdenje. Ovakvim ponašanjem se može ostvarati
poželjan efekat (regulisanje vidljivosti, nasleđivanje…), ali samo dok se to obavlja na
pravi način, uz pravu funkcionalnost, a ne beskonačno delegiranje.

Na Slici 20 videdemo šemu po kojoj možemo prepoznati disharmoniju


Posrednik.

Slika 20 – Šema Posrednika

Sa šeme vidimo da disharmonija Posrednik pogađa klase koje su izvršilie


uklanjanje disharmonije Lanac Delegiranja, i to na bar 2 - 5 takvih lanaca. Ovime se
postiže zasidenje jezičkim konstrukcijama velike dužine, a male funkcionjalne
kompleksnosti.
Drugi način da se klasa “zarazi” disharmonijom Posrednik, je prekomerno
preimenovanje (delegiranje) metoda drugih klasa u svrhu rešavanja ved navedenih
problema.

Rešenje za otklanjanje disharmonije je očigledno, i javlja se prilično intuitivno.


Ukoliko imamo preveliki broj “skradivača” lanaca delegiranja, jednostavno ih
premestimo u klasu u kojoj se lanci nalaze, pa možemo ukloniti tu klasu. Sa druge
strane ukoliko imamo veliki broj delegiranih metoda, bolje napraviti interfejs i tako
eliminisati potrebu za klasom u kojoj reimenujemo metode.

52
Dejan Stuparid, Softverska metrika

Kod ove disharmonije se ne susredemo ni sa jednim aspektom programiranja


koji je nezaobilazno loš. Kljudna stvar je ravnomerna upotreba jezičkih konstrukcija
koje nam olakšavaju razumevanje i funkcionalnosti koje opravdavaju postojanje klase.

2.4.3. Rezime
Kao i kod disharmonija identiteta i kod disharmonija saradnje postoje
prioritetni defekti koje treba uzeti u razmatranje pre drugih defakata. To su defekti
čijim rešavanjem možemo značajno popraviti ukupne performanse projekta, ili
njihovom analizom možemo otkriti značajan broj drugih disharmonija.
Defekte možemo poređati po prioritetu po slededem kriterijumu:
 Klase koje sadrže više od jednog metoda koji je zaražen nekom od
disharmonija saradnje.
 Klase koje uz disharmonije saradnje sadrže i disharmonije identiteta ili
klasifikacije.

Za razliku od disharmonija identiteta ovde ne možemo predstaviti


formalizovanu listu koraka za najefikasnije eliminisanje disharmonija saradnje. Stoga
demo predstaviti listu konkretnih smernica koje možemo koristiti pri refaktorisanju
naših projekata.

1. Kada je klasa pogođena disharmonijom Prevelika Intimnost uvek postoje


metodi iz različitih klasa koji su “previše intimni” među sobom. Pokušajmo da
indentifikujemo takve grupacije metoda i da uvedemo novi metod u kojem
demo objedinjavati funkcionalnost grupacije metoda. Ovo de dovesti do toga
da pozive ka više metoda zamenimo jedinstvenim pozivom metoda -
“objedinjavča”.
 Česta je pojava da metodi iz navedenih grupacija sadrže disharmoniju
Operacija Sačma. Dobra praksa je da eliminišemo pojave ove disharmonije,
jer demo time smanjiti broj klijenata metoda iz odabrane grupacije.
Ukanjanje klijentskih metoda umanjide sparivanje tih metoda.
 Disharmonije Operacije Sačma i Divirgentna Promena su kao dve strane
istog novčida, tako da je pravilna strategija testirati grupacije intimnih
metoda i na disharmoniju Divirgentna Promena.
 Klase koje sadrže “previše intimne” metode često ne sadrže nikakvu drugu
funkcionalnost, pa je dobra praksa testirati ih na disharmoniju Klasa
Podataka, i usmeriti refaktorisanje ka uklanjanju te disharmonije.
2. Disharmonije Posrednik i Lanac Delegiranja se mogu nalaziti u bilo kojoj klasi i
ne postoji obrazac njihovog pojavljivanja. Stoga je najbolja strategija da svaku
klasu proverimo na ove disharmonje.

53
Dejan Stuparid, Softverska metrika

2.5. Disharmonije Klasifikacije


Na kraju pozabavidemo se disharmonijama klasifikacije. Ove disharmonije
nastaju kao posledica jednog od najbitnijih koncepata objektno orjentisanog stila
programiranja – nasleđivanja. Kada nasleđivanje koristimo isključivo kao način za
ponovno iskorišdenje izvornog kôda, često dolazi do problema u održavanju sistema
ili čitkosti izvornog kôda. Nasleđivanje daje najbolje rezultate kada se koristi kao
sredstvo za upotrebu specijalizovanih objekata umesto njihove generalizovane
verzije.
U ovom radu prezentovademo dve disharmonije klasifikacije koje su klasični
primeri najčešdih problema koji se javljaju u softveru, a imaju veze sa nasleđivanjem.

2.5.1. Pravila Harmonije


Za detektovanje disharmonija klasifikacije koristidemo slededa tri pravila:
pravilo proporcije, pravlo prezentacije i pravilo imoplementacije.(1)

2.5.1.1. Pravilo Proporcije

Nasleđivanje u objektno-orjentisanim jezicima može da izazove podjednaku


količinu problema i kada se koristi i kada se ne koristi. Naime jedan ekstrem je
potpuno odsustvo nasleđivanja, čime dolazimo do programa koji po globalnoj
strukturi izrazito podsedaju na stare proceduralne programe. Ovakvi programi su
znatno ograničeni na polju ponovnog korišdenja različitih modula u sistemu. Drugi
ekstrem je preterano korišdenje nasleđivanja, što dovodi do izrazito rascepkanih
struktura, čije je razumevanje veoma teško.
Od ključne je važnosti proporcijalno korišdenje nasleđivanja, samo kad je
potrebno, i uvek kad ima smisla.

Šta treba izbegavati:


 Izrazito široke hijerarhije: Izbegavati izrazitio široke hijerarhije, ne želimo
podklase koje su to samo da bi se ispunila kvota nasleđivanja.
 Izrazito visoke Hijerarhije: Takođe izbegavajmo visoke hijerarhije, jer
nepregladan niz potomaka neke klase može da oteža razumevanje programa.

2.5.1.2. Pravilo Prezentacije

Nasleđivanje nam omogudava da pravimo sintaksno jednostavnije programe,


tako što demo neke delove izvornog kôda napisati u roditeljskoj klasi i samo ih
pozivati u klasama naslednicama. Od klasa naslednica se očekuje da budu obazrive na

54
Dejan Stuparid, Softverska metrika

promene u roditeljskoj klasi, da ne redefišu metode koji ispunjavaju svrhu, ni da


dupliciraju izvorni kôd roditeljske klase.

U praksi treba poštovati sledede smernice:


 Pažljivo proširenje interfejsa: Treba obratiti pažnju na to koju demo
funkcionalnost dodati u interfejs kojim klasa komunicira, jer prevelik broj
funkcionalnosti može da izazove problem
 Pažljivo specijalizivati klasu: Klasu naslednicu je potrebno specijalizovati, ali
moramo da budemo obazrivi da ne napravimo previše skučenu definiciju klase.
 Pažljivo smanjivati nivo apstrakcije: Nivo apstrakcije bi trebalo da bude u
korelaciji sa nivoom hijerarhije u kojoj se klasa nalazi. Klasa roditelj mora biti
na višem stepenu apstrakcije od klase naslednika.

2.5.1.3. Pravilo Implementacije

Ovo pravilo se odnosi na konstataciju koju smo naveli na početku poglavlja o


disharmonijama klasifikacije. Kao što smo rekli nasleđivanje treba koristiti da bismo
rafinisali celokupnu komunikaciju među klasama sistema, a ne samo u svrhu
ponovnog korišdenja raznih modula programa.

Ovo praktično znači:


 Zavisnost treba da funkcioniše samo u smeru dole-gore: Klase roditelji ne bi
trebalo da zavise od njihovih naslednika.
 Zavisnost u svrhu specijalizacije: Nasleđene operacije bi trebalo da se koriste
u svrhu specijalizacije objekta, a ne u kao pozivi u okviru novonastalih
operacija.

2.5.2. Lista Disharmonija


U ovom odeljku navešdemo dve disharmonije klasifikacije. I to Prekid Tradicije,
i Odbijanje Roditeljskog Nasleđa.

55
Dejan Stuparid, Softverska metrika

Slika 21 – Disharmonije Klasifikacije

Na Slici 21 imamo šematski prikaz disharmonija klasifikacije. Kao što se može


naslutiti sa slike, ove dve disharmonije nisu međusobno povezane kao neke od
disharmonija koje smo obrađivali u ranijim poglavljima. Disharmonije Prekid Tradicije
i Odbijanje Nasledstva su slične po tome što obe obrađuju koncept nasleđivanja, ali to
rade na dva različita načina. Više o ovim disharmonijama zaznademo u nastavku rada.

2.5.2.1. Prekid Tradicije (eng. Tradition Breaker)

U srcu disharmonije Prekid Tradicije nalazi se komunikacija među klasama


unutar hijerarhije nasleđivanja putem interfejsa. Naime klasa naslednica ne bi trebalo
da sadrži preteran broj novih usluga, ved se mora prevashodno uzdati u redefinasanje
metoda klase roditelja. Naravno klasa naslednica može da implementira potpuno
nove metode, ali je bitno da ona ostane u duhu hijerarhije u kojoj se nalazi. Ukoliko
imamo klasu koja gotovo da ni ne redefiniše metode iz roditeljske klase, evidentno je
da imamo problem kojim se moramo pozabaviti.

Kako bi neka klasa ispunjavala zahteve disharmonije Prekid Tradicije, mora


prodi šemu detekcije sa Slike 22.

56
Dejan Stuparid, Softverska metrika

Slika 22 – Šema Prekida Tradicije

Na šemi jasno vidimo tri različite grupe uslova koji moraju biti ispunjeni kako
bismo problem u klasifikaciji mogli da okarakterišemo kao disharmoniju Prekid
Tradicije.

1. Preterano uvedanje interfejsa nasledničke klase: Kako bismo ispitali tačnost


ovog uslova upotrebidemo dve softverske metrike, i to NAS (broj novih
metoda) i PNAS (procenat novih metoda u klasi naslednici). Pomodu metrike
NAS merimo broj novih metoda koje dodajemo u nasledničku klasu, i
poredimo ga sa srednjom vrednošdu za ovu metriku (vrednost je statistički
određena, i možemo je nadi u Tabeli 2). Metrika PNAS je normalizovana
metrika i ona nam daje predstavu o udelu novih metoda u celokupnom broju
metoda klase naslednice. Procenat novih metoda mora biti bar dve tredine

57
Dejan Stuparid, Softverska metrika

kako bi problem bio dovoljno ozbiljan, a klasa potencijalno pogođena


disharmonijom Prekid Tradicije.
2. Klasa naslednica je znatne kompleksnosti i veličine: Klasa naslednica mora biti
znatne kompleksnosti i veličine kako bi ušla u razmatranje (koristidemo
metrike AMW, WMC i NOM). Stoga merimo prosečnu kompleksnost metoda
(AMW) i ukupnu kompleksnost klase (WMC), i bar jedna od ovih metrika mora
dati VISOKU vrednost kako bi klasa ušla u razmatranje. Kao dodatni uslov
uvodimo prost broj metoda u klasi (NOM), a vrednost ove metrike bi trebalo
da prelazi graničnu vrednost VRLO VISOKO. Ovaj uslov je uveden kako u skup
kandidata ne bi upadale klase male složenosti koje dodaju znatan broj prostih
metoda.
3. Klasa roditelj nije zanemarljive kompleksnosti. Ova grupacija uslova se oslanja
na identičan princip merenja kompleksnosti kao u slučaju klase naslednice.
Zbog toga koristimo identičan skup metrika (AMW, WMC i NOM), a jedinu
razliku predstavljaju granične vrednosti vezane za te metrike. Prosečna
kompleksnost metoda (AMW) ima identičnu graničnu vrednost kao kod klase
naslednice, time osiguravamo da metodi roditeljske klase nisu trivijalni.
Granične vrednosti druge dve metrike (NOM i WMC) su prepolovljeni u odnosu
na vrednosti klase naslednice. Ovim uslovima osiguravamo da roditeljska klasa
nije ni mala niti “glupa”i da predstavlja znatan izvor metoda i drugih usluga
koje naslednička klasa može da koristi. Takođe ovime otpisujemo apstraktne
klase, koje zasigurno nede modi da prođu gore navedene uslove.

Pošto je disharmonija Prekid Tradicije sama po sebi prilično kompleksna za


definisanje i detektovanje, posledično je da je i algoritam za njeno uklanjanje nešto
komplikovaniji. Razmotridemo četiri forme u kojima se klasa može javiti, i način da se
oslobodimo problema.

 Slučaj 1 – Nebitna Tradicija: Ovde se problem ograničava na pogrešnu


upotrebu modifikatora public odnosno protected. Potrebno je da sve metode
koje nedemo koristiti u drugim klasama obeležiti modifikatorom protected, i ne
navoditi ih u interfejsu.
 Slučaj 2 – Odbijena Tradicija: Ako roditeljska klasa ne implementira metode
koji se nalaze u vedini nasledničkih klasa problem se nalazi u samoj roditeljskoj
klasi. Rešenje vidimo u premeštanju metoda u roditeljsku klasu, a u
naslednicama samo pozivamo metode. Ovime otklanjamo i Znatno Dupliciranje
u klasama naslednicama nastalo kao posledica.
 Slučaj 3 – Dvolični naslednik: Deo klase naslednice je povezan sa
funkcionalnostima iz roditeljske klase, dok je drugi deo potpuno ne vezan za
tradiciju uspostavljenu u klasama na višem nivou hijerarhije. Kao logično
rešenje figurira premeštanje nevezanog dela van hijerarhije u novu klasu, ili
unutar ved postojede klase kojoj više odgovara.

58
Dejan Stuparid, Softverska metrika

 Slučaj 4 – Neodgovarajudi naslednik: Ovo je ekstreman slučaj Slučaja 3, i javlja


se kada je celukupna funkcionalnost nasledničke klase ne vezena za roditeljsku
klasu. Logično rešenje predstavlja premeštanje celokupne nasledničke klase
izvan hijerarhije.

Uklanjanjem disharmonije Prekid Tradicije naš izvorni kôd može postati znatno
efikasniji, a svakako je čitkiji i u skladu sa ustaljenim stilom lepog programiranja.

2.5.2.2. Odbijanje Roditeljskog Nasleđa (eng. Refused Parent


Bequest)

Nasleđivanje je zamišljeno kao koncept objektno-orjentisanog programiranja


koji de se zasnivati na intimnoj komunikaciji među klasama članicama hijerarhije.
Klasa na višem hijerarhijskom stepeniku bi trebala da konstruiše usluge, koje de klase
na nižem hijerarhijskom stepeniku koristiti. Ukoliko klase naslednice ne komuniciraju
dovoljno initmno sa svojim roditeljskim klasama mogude je da su pogođene
disharmonijom Odbijanje Roditeljskog Nasleđa.

Kao što smo ranije navodili osnovni cilj nasleđivanja je ponovno iskorišdenje
sekcija izvornog kôda iz klasa na kojima je primenjeno nasleđivanje. Kada
uspostavljamo hijerarhiju nasleđivanja veoma je bitno da krenemo sa dna i da
pokušamo da prebacimo što je više funkcionalnosti u nadklasu posmatrane klase. Na
taj način smanjujemo dupliciranje izvornog kôda i specijalizujemo komunikaciju među
klasama unutar hijerarhije.

Na Slici 23 vidimo šemu pomodu koje detektujemo klase pogođene


disharmonijom Odbijanje Roditeljskog Nasleđa.

59
Dejan Stuparid, Softverska metrika

Slika 23 – Šema Odbijanja Roditeljskog Nasleđa

Klase potencijalno pogođene Odbijanjem Roditeljskog Nasleđa moraju biti ne


zanemarljive veličine i kompleksnosti, baš kao i kod disharmonije Prekid Tradicije. Ova
grupa uslova je gotovo identična za ove dve disharmonije, stoga koristimo indentične
metrike (AMW, WMC i NOM), dok su granične vrednosti postavljene na SREDNJE.
Prvi deo šeme je znatno zanimljiviji i odnosi se na skup uslova čije de ispunjenje
značiti da klasa naslednik ignoriše nasledstvo iz roditeljske klase. Ovde demo koristiti
metrike NProtM, BUR i BOvR. Naime pomodu metrike BUR (Base Class Usage Ratio)
procenjujemo da li klasa naslednica ignoriše dovoljan broj usluga roditeljke klase kako
bi ušla u uži izbor, u našem slučaju prag je TREDINA usluga roditeljske klase. Metrikom
NProtM (Number of Protected Members) samo osiguravamo da postoji bar nekoliko
naslednih usluga/metoda iz roditeljske klase koje možemo koristiti u klasi naslednici.
Ukoliko klasa ne prelazi pragove neke od prethodne dve metrike, dovoljno je da
pređe prag metrike BOvR (Base Class Override Ratio), tj. da naslednica redefiniše
manje od TREDINE metoda iz roditeljske klase.

Iz samih uslova čije ispunjenje je potrebno da se detektuje disharmonija


Odbijanje Roditeljskog Nasleđa vidimo da su unutar klase na nižem hijerarhiskom
stepeniku sistematski ignoriše nasleđe iz roditeljske klase. Kako bismo ispoštovali

60
Dejan Stuparid, Softverska metrika

dobar stil programiranja, i olakšali snalaženje u programu moramo promeniti trenutni


hijerarhijski poredak.

Slično kao u slučaju Prekida Tradicije algoritam za otklanjanje disharmonije je


podeljen na slučajeve u zavisnosti koja forma disharmonije de se pojaviti.
 Slučaj 1 – Pogrešni Naslednik : Nekada klasa jednostavno ne pripada hijerarhiji
u kojoj se nalazi, pa iz tog razloga slabo koristi nasleđene funkcionalnosti.
Ovakve klase treba potpuno premestiti iz hijerarhije na mesto koje de im bolje
odgovarati sa aspekta komunikacije. Specijalni slučaj ove forme je kada je
samo nivo u hijerarhiji pogrešno određen, nekada je unuk bolji naslednik od
deteta.
 Slučaj 2 – Irelevantno Nasleđe : Ukoliko je roditeljska klasa pretrpana
metodima koji nemaju nikakvu funkciju u klasama naslednicama, ved se koriste
samo unutar same klase, postavlja se pitanje svrhe same hijerarhije. U ovakvim
situacijama iz hijererhija se najčešde uklanja nadklasa klasa, a sve ostale klase
se pomeraju za jedan stepenik nagore na hijerarhijskoj lestvici.
 Slučaj 3 – Diskriminatorsko Nasleđe : Nekada je nasleđe iz roditeljske klase
relevantno samo za neke naslednike. Ovo se uglavnom dešava kod širokih
hijerarhija, kada pojedičana klasa naslednik koristi samo mali deo od ukupnog
skupa metoda roditeljske klase. Uobičajno rešenje za ovakvu formu
disharmonije Odbijanje Roditeljskog Nasleđa, je da roditeljsku klasu podelimo
na nekoliko manjih potklasa, dok demo u roditeljskoj klasi zadržati samo
metode koji se koriste na više od jednog mesta.

2.5.3. Rezime
Disharmonije klasifikacije ili poblemi sa hijerarhijama nasleđivanja se ne mogu
rešavati posmatranjem individualnih klasa, niti individualnih veza među klasama.
Moramo posmatrati program kao celinu i sve veze među klasama unutar tog
programa.
Kao i kod disharmonija identiteta i saradnje i kod disharmonija klasifikacije
postoje defekti koji imaju viši prioritet od drugih, navedimo listu prioritetnih
defekata:
 Hijerarhije nasleđivanja pogođene sa nekoliko disharmonija klasifikacije.
 Hijerarhije nasleđivanja pogođene disharmonijama klasifikacije na više
različitih nivoa nasleđivanja.
 Hijerarhije nasleđivanja pogođene disharmonijama identiteta i saradnje pored
disharmonija klasifikacije.
Kako bismo odredili proritete među defektima klasifikacije koristimo nekoliko
specifičnih metrika koje se koriste isključivo u ove svrhe. Navedimo te metrike:

61
Dejan Stuparid, Softverska metrika

 Broj klasa sa disharmonijama klasifikacije (eng. Number of Classes with


Colaboration Disharmonies) – pomodu ove metrike saznajemo koliko su
disharmonije klasifikacije raširene unutar jedne hijerarhije nasleđivanja.
 Dubina hijererhije pogođene disharmonijama klasifikacije (eng. Hierarchy
Depth of Disharmonious Classes) – uz prethodnu metriku, ova metrika nam
može biti od velike pomodi pri proceni raširenosti disharmoničnosti unutar
hijerarhije.
 Broj različitih disharmonija klasifikacije unutar hijerarhije (eng. Distinct
Classification Disharmonies in Hierarchy) – posmatranjem vrednosti ove
metrike utvrđujemo koliko je naš problem kompleksan. Otklanjanje različitih
problema je teže nego otklanjanje istih.
 Broj ostalih disharmonija unutar hijerarhije (eng. Distinct Number of Other
Disharmonies in Hierarchy) – kako bismo bolje shvatili situaciju u našoj
hijerarhiji nasleđivanja brojimo i ostale disharmonije (identiteta i saradnje).(1)

Sada kada smo utvrdili kojim redom demo obavljati refaktorisanje klasa
pogođenih disharmonijama klasifikacije, i kada imamo metrike da to izmerimo,
možemo predi na efektivno refaktorisanje.

62
Dejan Stuparid, Softverska metrika

3. Relacije među softverskim


metrikama u praksi
3.1. O relacijama među metrikama
Kao što smo mogli da primetimo iz prethodnih primera defekata u softverskim
projektima, vrlo je lako pogrešiti, a takođe postoji i mnogo načina da se pogreši. - Na
sredu takođe postoji i veliki broj načina da se greška ispravi.

Kada pokušavamo da ispravimo defekt u izvornom kôdu, pribegavamo raznim


strategijama, i menjamo razne parametre i strukture u programu. A ovo može dovesti
do različitih implikacija na izvorni kôd koji menjamo ili izvorni kôd koji komunicira sa
menjanim izvornim kôdom. Neke implikacije de biti pozitivne (kradi izvorni kôd,
razumljivija sintaksa, povedan faktor ponovnog iskorištenja izvornog kôda…), dok de
neke biti negativne (kršenje enkapsulacije, povedano sparivanje među klasama,
otžano razumevanje izvornog kôda…), pa je stoga potrebno utvrditi nekakve relacije
među njima. Kao operandi u ovim relacijama figuriranju softverske metrike. Metrike
demo koristiti kao reprezentacije promena unutar izvornog kôda nastale određenim
zahvatom.

U nastavku teksta promenu neke sekcije izvornog kôda reprezentovademo


metrikom na koju je ova promena uticala. Ovakvo izražavanjenije nije u potpunosti
ispravno, ali nam znatno može olakšati razumevanje konkretne oblasti koju
obrađujemo. Tako da demo zameniti sintaksnu ispravnost za lakodu razumevanja, ali
demo pri manje jasnim situacijama navoditi podrobnija objašnjenja u zagradi.

Pošto su ove relacije izrazito zavisne od konkretnog primera, vrlo je teško (ako
ne i nemogude) potpuno formalizovati njihovu prezentaciju. Tako da demo relacije
prezentovati skupom primera na konkretnom izvornom kôdu i sa konkretnim
izmenama. Relacije de se razlikovati po broju metrika koje figuriraju u njima, jer
nekad promena jedne metrike može uticati na čitav niz drugih, dok promene nekad
utiču samo na jednu metriku.(5)

3.2. Primeri relacija među metrikama


U ovom odeljku navešdemo konkretne primere pomodu kojih demo lakše modi
da shvatimo odnose među softverskim metrikama. Prikazadamo tabelarno i praktično

63
Dejan Stuparid, Softverska metrika

anomalije u izvornom kôdu nastale usled nepoštovanja određenih konvencija ili


pogrešnog pristupanju resursima.
Za računanje softverskih metrika koristidemo dodatak za Eclipse IDE zvan
Metrics. Pomodu ovog dodatka mogude je na vrlo jednostavan način računati
vrednosti velikog broja metrika. Uz to dodatak je potpuno besplatan i otvorenog je
izvornog kôda (eng. open source). Dodatak Metrics je objavljen je pod licencom “The
Common Public Licence – v 1.0”, isto kao i sam projekat Eclipse.

3.2.1. Odnos između metrike Broj linija kôda (LOC) i metrike


Kružna Složenost (CYCLO), na primeru disharmonija Mudra
Klasa/Mudri Metod
Ovo je jedan od klasičnih primera, koji je prilično lak za razumevanje. Logično
je da de dodavanje ili oduzimanje izvornog kôda (metrika LOC), na neki način uticati
na ukupnu kompleksnost tog izvornog kôda (metrika CYCLO). Svaka linija izvornog
kôda nosi sa sobom određen težinski koeficijent koji utiče na ukupnu kompleksnost
metoda, klasa i paketa u kojima se ona nalazi. Težinski koeficijent linije zavisi od tipa
linije (kompleksan logički uslov, poziv naredbe, komentar…), pa de manipulisanje
različitim tipovima linija različito uticati na obe metrike koje figuriraju u našoj relaciji.

Naš zadatak je da utvrdimo obrazac ponašanja vrednosti metrika, pri


izmenama raznih komponenti izvornog kôda. Navešdemo jednu klasu koja de biti
klasični predstavnik defekta Mudra Klasa koju demo analizirati sa fokusom na metrike
LOC i CYCLO. Ovaj primer kao i svaki drugi koji bismo mogli da navedemo, a da ne
prekoracimo opseg ovog rada je samo trivijalizacija postupaka iz realnih situacija.

U ovu svrhu koristidemo jedan mali projekat koji sadrži sve klasične primere
defekata u softveru. Projekat sam po sebi se sastoji od tri klase i obavlja funkciju CD
Kluba u kome možete iznajmljivati diskove. Klasa JedanCD je jednostavna Klasa
Podataka koja sadrži polja za indentifikaciju pojedinačnog CD-a. Druga klasa je
CDKlub koja je takođe Klasa Podataka i sadrži promenljive vezane za konkretna
iznajmiljivanja. Klasa Musterija je Mudra Klasa i u njoj se obavljaju svi proračuni.

U odeljku Izvornom Kôdu 6 navedimo izvorni kôd klase JedanCD.

package testPaket;
public class JedanCD {

private String naslov;


private int cena;
private int kvalitetZvuka;
private String zanr;

public static final int IGRA = 2;


public static final int PROGRAM = 3;

64
Dejan Stuparid, Softverska metrika

public static final int MUZIKA = 1;


public static final int FILM = 0;

public JedanCD (String naslov, int cena, int kvalitetZvuka,


String zanr){
this.naslov = naslov;
this.cena = cena;
this.kvalitetZvuka = kvalitetZvuka;
this.zanr = zanr;
}

public String getNaslov() {


return naslov;
}
public void setNaslov(String naslov) {
this.naslov = naslov;
}
public int getCena() {
return cena;
}
public void setCena(int cena) {
this.cena = cena;
}
public int getKvalitetZvuka() {
return kvalitetZvuka;
}
public void setKvalitetZvuka(int kvalitetZvuka) {
this.kvalitetZvuka = kvalitetZvuka;
}
public String getZanr() {
return zanr;
}
public void setZanr(String zanr) {
this.zanr = zanr;
}
}
Izvorni Kôd 6 – Klasa JedanCD

Zatim u Izvornom Kôdu 7 pogledajmo klasu CDKlub.

package testPaket;
public class CDKlub {

public JedanCD cd;


private int duzinaIznajmljivanja;
private int koeficijentSadrzaja;

public CDKlub (JedanCD cd, int duzinaIznajmljivanja, int


koeficijentSadrzaja){
this.cd = cd;
this.duzinaIznajmljivanja = duzinaIznajmljivanja;
this.koeficijentSadrzaja = koeficijentSadrzaja;
}

65
Dejan Stuparid, Softverska metrika

public JedanCD getCd() {


return cd;
}
public void setCd(JedanCD cd) {
this.cd = cd;
}
public int getDuzinaIznajmljivanja() {
return duzinaIznajmljivanja;
}
public void setDuzinaIznajmljivanja(int duzinaIznajmljivanja) {
this.duzinaIznajmljivanja = duzinaIznajmljivanja;
}
public int getKoeficijentSadrzaja() {
return koeficijentSadrzaja;
}
public void setKoeficijentSadrzaja(int koeficijentSadrzaja) {
this.koeficijentSadrzaja = koeficijentSadrzaja;
}
}
Izvorni Kôd 7 – Klasa CDKlub

I na kraju u Izvornom Kôdu 8 imamo prikaz klase Musterija.

package testPaket;
public class Musterija {

private String ime;


private String prezime;
private Vector iznajmljivanje = new Vector();

public Musterija (String ime, String prezime){


this.ime = ime;
this.prezime = prezime;
}
public String getIme() {
return ime;
}
public void setIme(String ime) {
this.ime = ime;
}
public String getPrezime() {
return prezime;
}
public void setPrezime(String prezime) {
this.prezime = prezime;
}
@SuppressWarnings("unchecked")
public void novoIzdavanje(CDKlub a){
iznajmljivanje.addElement(a);
}
@SuppressWarnings("unchecked")
public String priznanica(){

double ukupno = 0;

66
Dejan Stuparid, Softverska metrika

int cestoIznajmljeni = 0;

String rez = "Podaci o iznajmljivanju za osobu" +getIme()


+getPrezime() + "su:";
Enumeration iznajmljivanje =
this.iznajmljivanje.elements();

while (iznajmljivanje.hasMoreElements()){
double trenutnaKolicina = 0;
CDKlub porudzbina = (CDKlub)
iznajmljivanje.nextElement();

switch (porudzbina.getCd().getCena()){
case JedanCD.FILM:
trenutnaKolicina += 1;
if (porudzbina.getDuzinaIznajmljivanja()
> 2){
trenutnaKolicina +=
(porudzbina.getDuzinaIznajmljivanja() - 2)*1.5;
}
break;
case JedanCD.MUZIKA:
trenutnaKolicina += 2;
if (porudzbina.getCd().
getKvalitetZvuka() > 3){
trenutnaKolicina *= porudzbina.
getCd().getKvalitetZvuka()/3;
}
break;
case JedanCD.IGRA:
trenutnaKolicina += 3;
if (porudzbina.getCd().getZanr() ==
"Akcija"){
trenutnaKolicina *= 1.5;
}else if (porudzbina.getCd().getZanr()
== "Strategija"){
trenutnaKolicina *= 1.4;
}else {
trenutnaKolicina *= 1;
}
break;
case JedanCD.PROGRAM:
trenutnaKolicina += 4;
if (porudzbina.getKoeficijentSadrzaja() >
3){
trenutnaKolicina *= porudzbina.
getKoeficijentSadrzaja()/3;
}
break;
}
cestoIznajmljeni++;
if (porudzbina.getDuzinaIznajmljivanja() > 3){
cestoIznajmljeni ++;
}
rez += porudzbina.getCd().getNaslov() + "sa vrednoscu"
+String.valueOf(trenutnaKolicina);

67
Dejan Stuparid, Softverska metrika

ukupno +=trenutnaKolicina;
}
rez += "Ukupno zaduzenje:" + String.valueOf(ukupno);
return rez;
}
}
Izvorni Kôd 8 – Klasa Musterija

U Tabeli 7 navedimo neke karakteristike projekta izražene kroz sledede


softverske metrike, svrstane po klasama:

Klasa Metrika Vrednost


LOC 41
CYCLO (Za najkompleksniji metod) 1
JedanCD NOM 9
NOA 4
WMC 9
LOC 29
CYCLO (Za najkompleksniji metod) 1
CDKlub NOM 7
NOA 3
WMC 7
LOC 77
CYCLO (Za najkompleksniji metod) 12
Musterija NOM 7
NOA 3
WMC 18
LOC 149
CYCLO (Za najkompleksniji metod) 12
NOM 23
Ukupno
NOA 10
WMC 34
NOCL 4
Tabela 7 – Metrike pre refaktorisanja

Kao što smo naglasili najvedi deo sadržaja i kompleksnosti nalazi se u klasi
Musterija, koja sadrži metod priznanica koji je izuzetno kompleksan i dobar je
kandidat za Mudri Metod. Navedimo karakteristike metoda priznanicau Tabeli 8.

68
Dejan Stuparid, Softverska metrika

Metod Metrika Vrednost


LOC 45
CYCLO 12
priznanica
NOM 9
CYCLO (Za celu klasu Musterija) 2.571
Tabela 8 – Metrike za metod priznanica

Pošto smo naveli osnovne karakteristike možemo ih analizirati.

Kao što smo naveli vedina funkcionalnosti smeštena je u klasu Musterija.


Ovo tvrđenje je zasnovano na metrikama LOC i CYCLO. Naime broj linija izvornog kôda
metoda priznanica je jednak broju linija izvornog kôda ostatka klase. Dok je
CYCLO najkompleksnijeg metoda klase Musterija (metod priznanica) čak 12
puta vedi nego CYCLO prvog slededeg metoda po kompleksnosti. Klasa JedanCD ima
najviše metoda, (NOM = 9) ali su svi metodi ove klase metodi za pristup (get i set).
Primetimo da klase JedanCD i CDKlub imaju WMC jednak NOM-u, po čemu
zaključujemo da je svaki metod kompleksnosti jedan, i da u klasama ne postoji
nikakva kompleksnija operacija ili naredba. Što očigledno stavlja klase JedanCD i
CDKlub u kategoriju Klasa Podataka.
Analizirajmo bliže klasu Musterija. Ovaj metod sadrži preko dve trdine LOC
klase Musterija, dok je njegova CYCLO vrednost za najkompleksniji metod daleko
iznad proseka kružne složenosti za tu klasu. Ovim merenjima zaključujemo da je
metod priznanica zapravo Mudri Metod, a da je klasa Musterija Mudra Klasa
koja sadrži jedan izrazito kompleksan metod.

Pošto smo detaljno analizirali kompletan projekat, krenudemo na


prekopotrebno refakorisanje.
Prvo demo se pozabaviti metodom priznanica, on je najkompleksniji i
najlošije struktuiran i očigledno mu treba posvetiti najviše pažnje. Pregledavanjem
izvornog kôda metoda priznanica, možemo jasno uočiti segment u kojem se
nalazi switch naredba. Ovaj segment obavlja funkciju određivanja težinskog
koeficijenta svakog tipa CD-a, a čini jednu celina i mogli bismo ga premestiti iz
metoda u kome se nalazi. Eclipse IDE sadrži komandu Extract Method, tako da je
pomodu nje ovaj posao gotovo trivijalan.

Navešdemo izmene u Izvornom Kôdu 9.

package testPaket;
public String priznanica(){
double ukupno = 0;
int cestoIznajmljeni = 0;
String rez = "Podaci o iznajmljivanju za osobu" +getIme()
+getPrezime() + "su:";

69
Dejan Stuparid, Softverska metrika

Enumeration iznajmljivanje =
this.iznajmljivanje.elements();

while (iznajmljivanje.hasMoreElements()){

double trenutnaKolicina = 0;
CDKlub porudzbina = (CDKlub)
iznajmljivanje.nextElement();

trenutnaKolicina = odretiKolicinu(trenutnaKolicina,
porudzbina);
if (porudzbina.getDuzinaIznajmljivanja() > 3){
cestoIznajmljeni ++;
}

rez += porudzbina.getCd().getNaslov() + "sa vrednoscu" +


String.valueOf(trenutnaKolicina);
ukupno +=trenutnaKolicina;

}
rez += "Ukupno zaduzenje:" + String.valueOf(ukupno);

return rez;
}
private double odretiKolicinu(double trenutnaKolicina, CDKlub
porudzbina) {
switch (porudzbina.getCd().getCena()){
case JedanCD.FILM:
trenutnaKolicina += 1;
if (porudzbina.getDuzinaIznajmljivanja() > 2){
trenutnaKolicina +=
(porudzbina.getDuzinaIznajmljivanja() - 2)*1.5;
}
break;
case JedanCD.MUZIKA:
trenutnaKolicina += 2;
if (porudzbina.getCd().getKvalitetZvuka() >
3){
trenutnaKolicina *=
porudzbina.getCd().getKvalitetZvuka()/3;
}
break;
case JedanCD.IGRA:
trenutnaKolicina += 3;
if (porudzbina.getCd().getZanr() == "Akcija"){
trenutnaKolicina *= 1.5;
}else if (porudzbina.getCd().getZanr() ==
"Strategija"){
trenutnaKolicina *= 1.4;
}else {
trenutnaKolicina *= 1;
}
break;
case JedanCD.PROGRAM:
trenutnaKolicina += 4;
if (porudzbina.getKoeficijentSadrzaja() > 3){

70
Dejan Stuparid, Softverska metrika

trenutnaKolicina *=
porudzbina.getKoeficijentSadrzaja()/3;
}
break;
}
return trenutnaKolicina;
}
Izvorni Kôd 9 – Refaktorisanje metoda priznanica

Kao što vidimo celina oko switch naredbe je premeštena u drugi metod, a
promenljiva trenutnaKolicina dobija vrednost pozivanjem metoda
odreditiKolicinu sa parametrima trenutnaKolicina = 0 i poruzbina
(tipa CDKlub).
Ponovo primenimo metrike na klasu Musterija, Tabela 9:

Klasa Metrika Vrednost


LOC 81
CYCLO 2.375
CYCLO (Za najkompleksniji metod) 10
Musterija
NOM 8
NOA 3
WMC 19
Tabela 9 – Karakteristike klase Musterija posle prvog refaktorisanja

Takođe primenimo metrike i na metode priznanica i


odreditiKolicinu, Tabela 10:

Metod Metrika Vrednost


LOC 16
priznanica CYCLO (Za celu klasu) 2.375
CYCLO 3
LOC 31
odreditiKoliicinu CYCLO (Za celu klasu) 2.375
CYCLO 10
Tabela 10 – Karakteristike metoda priznanica i odreditiKolicinu posle prvog
refaktorisanja

Kada uporedimo karakteristike ova dva metoda vidimo da je novonastali


metod odreditiKolicinu kompleksniji (i po LOC i po CYCLO) od ostatka metoda
priznanica, ali primedujemo i da je maksimalna kompleksnost opala (na 10), što
naše metode čini jednostavnijim. Naš metod priznanica je sada tek iznad proseka
kompleksnosti po metrici CYCLO, što ga čini znatno jednostavnijim za razumevanje.

71
Dejan Stuparid, Softverska metrika

Daljim promatranjem izvornog kôda možemo primetiti još jednu celinu unutar
metoda priznanica, koju bismo mogli da premestimo u zaseban metod. Naime
radi se o segmentu oko primenljive cestoIznajmljeni koji se može izmestiti u
zaseban metod.
Pogledajmo ovo u Izvornom Kôdu 10,

package testPaket;
public class{

cestoIznajmljeni = getPoeneZaCestoIznajmljene(cestoIznajmljeni,
porudzbina);


private int getPoeneZaCestoIznajmljene(int cestoIznajmljeni,
CDKlub porudzbina) {
cestoIznajmljeni++;
if (porudzbina.getDuzinaIznajmljivanja() > 3){
cestoIznajmljeni ++;
}
return cestoIznajmljeni;
}
}
Izvorni Kôd 10 – Metod getPoeneZaCestoIznajmljivanje

Ovom promenom je još umanjena kompleksnost metoda priznanica, čime


je ona dovadena na prihvatljiv nivo. Takođe dosta je urađeno na povedanju
razumljivosti cele klase, što može dovesti do velikih ušteda u fazi održavanja softvera
(naravno na projektima koji su mnogo vedeg obima). Još jedna prednost ovoga
rešenja je mogudnost da se metod getPoeneZaCestoIznajmljene poziva i na
drugim mestima, u situacijiama kada nam je potrebna njegova funkcijonalnst.

Pored ved navedenih izmeštanja određenih celina u posebne metode, mogili


smo to uraditi sa još nekim segmentima. Naime, u okviru svake case grane ved
pomenutog segmenta oko switch naredbe imamo uslovne izraze koje bismo mogli da
premestimo u zasebne metode. Ova promena bi doprinula boljoj raspodeli kružne
složenosti po metodima, ali bi umanjila razumljivost programa zbog prevelikog broja
delegiranja odgovornosti. Ipak odlučili smo da te segmente ne izmeštamo u zasebne
metode presvega jer je ovo pokazni primer, a slično izmeštanje je ved urađeno u
ovom poglavlju.
Promenama koje smo izvršili, poboljšali smo znatno funkcionalnost našeg
programa, ali je on još uvek sadrži mane koje treba ispraviti. Preostalim manama
pozabavidemo se u slededim poglavljima.

72
Dejan Stuparid, Softverska metrika

3.2.2. Relacije između metrika Pristup Stranim Podacima,


Lokacije Korišdenih Atributa i Snabdevači Stranog Sadržaja
(ATFD – LAA – FDP), na primeru disharmonije Ljubomorni
Metod
Da podsetimo disharmonija Ljubomorni Metod predstavlja situaciju u kojoj
imamo metod koji se očigledno nalazi u pogrešnoj klasi. Ovakvu disharmoniju
možemo najlakše primetiti ukoliko se fokusiramo na atribute koji se koriste unutar
metoda i na klase u kojima se ti metodi nalaze. Naime u našem primeru metod
odreditiKolicinu očigledno koristi previše usluga iz klase CDKlub,
pogledajmo ovo kroz metrike u Tabeli 11.

Metod Metrika Vrednost


LOC 31
CYCLO 10
ATFD 13
LAA Nijedan atribut koji se
odreditiKoliicinu
koriste u metodu
odreditiKolicinu nije
lokalan
FDP 2
Tabela 11 – Karakteristike metoda odreditiKolicinu pre refaktorisanja

U Tabeli 11 sačuvali smo vrednosti metrika LOC i CYCLO kako bismo mogli da
pratimo kompleksnost metoda kroz njegovu evoluciju. Videdemo da je metrika ATFD
(koja je modifikovana tako da meri ukupan broj pojava stranih atributa u metodu)
ima vrlo veliku vrednost, čak 13. Što nam sugeriše da se naš metod previše orjentiše
ka drugim klasama. Zatim pomodu metrike LAA utvrđujemo da naš metod ne koristi
niti jedan element koji je definisan u klasi u kojoj se nalazi, što ovaj slučaj čini
ekstremnim i neophodno je izvršiti premeštanje. I na kraju metrikom FDP saznajemo
da metod koristi usluge drugih dveju klasa, što nam sužava izbor novog domadina
našeg metoda.
Kada smo analizirali nedostatke koji postoje u metodu odreditiKolicinu,
možemo predi na konkretne korake ka poboljšanju izvornog kôda. Prvo moramo
odlučiti u koju klasu demo prebaciti metod odreditiKolicinu. Ovo možemo
odrediti prostim brojanjem pojava atributa iz obe klase koje pružaju servise našem
metodu. Pošto je vedi broj pojava instanci klase CDKlub odlučujemo da metod
odreditiKolicinu premestimo u tu klasu. Pri tome demo mu i promeniti i ime,
tako da demo sada imati metod getKolicina.
Pogledajmo ovo u Izvornom Kôdu 11:

73
Dejan Stuparid, Softverska metrika

package testPaket;
public class CDKlub {

public double getKolicina() {
double result = 0;
switch (getCd().getCena()){
case JedanCD.FILM:
result += 1;
if (getDuzinaIznajmljivanja() > 2){
result += (getDuzinaIznajmljivanja() -
2)*1.5;
}
break;
case JedanCD.MUZIKA:
result += 2;
if (getCd().getKvalitetZvuka() > 3){
result *= getCd().getKvalitetZvuka()/3;
}
break;
case JedanCD.IGRA:
result += 3;
if (getCd().getZanr() == "Akcija"){
result *= 1.5;
}else if (getCd().getZanr() == "Strategija"){
result *= 1.4;
}else {
result *= 1;
}
break;
case JedanCD.PROGRAM:
result += 4;
if (getKoeficijentSadrzaja() > 3){
result *= getKoeficijentSadrzaja()/3;
}
break;
}
return result;
}
}
Izvorni Kôd 1 – Refaktorisanje metoda getKolicina

A u Izvornom Kôdu 12 imamo poziv metoda getKolicina u telu metoda


odreditiKolicinu.
package testPaket;
public class Musterija {

trenutnaKolicina = odretiKolicinu(porudzbina);

private double odretiKolicinu(CDKlub cdklub) {
return cdklub.getKolicina();
}

}
Izvorni Kôd 2 – Metod odrediKolicinu

74
Dejan Stuparid, Softverska metrika

Ovim premeštanjem smo smanjili broj pristupa servisima drugih klasa, a


analizu obavljenu po završetku refaktorisanja možemo videti u Tabeli 12.

Metod/Klasa Metrika Vrednost


LOC (Klase CDKlub) 63
LOC (Metoda getKolicina) 32
CYCLO (Metoda getKolicina) 10
CYCLO (Klase CDKlub) 2.125
ATFD 5
getKolicina/CDKlub
LAA Odnos pojava lokalnih i
stranih promenljivih je
8 : 5, u korist domadih
atributa
FDP 1
LOC (Klase Musterija) 56
LOC (Metoda odreditiKolicinu) 1
CYCLO (Metoda odreditiKolicinu) 1
odreditiKolicinu/JedanCD CYCLO (Klase Musterija) 1.222
ATFD --
LAA --
FDP --
Tabela 12 – Karakteristike metoda getKolicina i OdreditiKolicinu posle refaktorisanja

Kao što možemo zaključiti iz vrednosti navedenih metrika, nestali su znaci


disharmonije Ljubomorni Metod. Vidimo da klasa sada koristi vedi broj lokalnih
usluga, nego usluga drugih klasa (LAA). Takođe broj stranih servisa je sveden na
znatno manji broj, tačnije koristimo samo pet servisa drugih klasa (ATFD). Dok kao
jedini nedostatak ostaje činjenica da koristimo usluge samo iz klase JedanCD (FDP),
čime klasa CDKlub biva čvrsto sparena za klasu JedanCD. Ali popravkom ovog
defekta demo se baviti u narednoj sekciji.
Na kraju posmatrajmo mere kompleksnosti koje su takođe navedene u tabeli.
Linije izvornog kôda su sada ravnomernije raspoređene u klasama JedanCD i
Musterija, kao i kružna složenost (CYCLO) koja je takođe ravnomernije
raspoređena, iako metod getKolicina još uvek odskače.
Primetimo i da je metod odreditiKolicinu sveden na samo jednu liniju,
tj. njegova jedina funkcionalnost je poziv metoda getKolicina sa parametrom
tipa CDKlub.

Ovom prepravkom još smo malo poboljšali kvalitet našeg programa, ali je pred
nama još nekoliko bitnih defekata koje demo obraditi u narednim segmentima.

75
Dejan Stuparid, Softverska metrika

Moramo još jednom napomenuti da je naš primer izrazita trivijalizacija


situacija na koje bi moglo da se primeni refaktorsanje koje mi prikazujemo. Drugim
rečima naši defekti su samo mali podskup svih mogudih defekata kojima softver u
realnom radu može biti izložen.

3.2.3. Relacije između metrika Broj Redefinisanih Metoda,


Broj Naslednika, i Dubina Stabla nasleđivanja (NORM – NOC
– DIT), na primeru disharmonije Prekid Tradicije
Poslednju grupaciju promena u okviru ovog procesa refaktorisanja činide
promene vezane za nasleđivanje. Naime naš program prikazuje potpuno odsustvo
bilo kakvog nasleđivanja, što može dovesti do velikih problema sa aspekta ponovnog
iskorišdenja delova programa.
Analizom klasa našeg programa shvatamo da bismo mogli da ugradimo
hijerarhiju nasleđivanja u odnos tipova različitih CD-ova koje iznajmljujemo iz CD
Kluba. Drugim rečima ovo bismo mogli da uradimo ukoliko bi metod getKolicina
bio u klasi JedanCD. Stoga demo premestiti metod getKolicina u klasu
JedanCD, kako bismo mogli kasnije da uspostavimo hijererhiju nasleđivanja.
Pogledajmo kako ovo izgleda u Izvornom Kôdu 13:

package testPaket;
public class JedanCD {

public double getNaplata(int danIznajm, int koefSad){
double result = 0;
switch (getCena()){
case FILM:
result += 1;
if (danIznajm > 2){
result += (danIznajm - 2)*1.5;
}
break;
case MUZIKA:
result += 2;
if (getKvalitetZvuka() > 3){
result *= getKvalitetZvuka()/3;
}
break;
case IGRA:
result += 3;
if (getZanr() == "Akcija"){
result *= 1.5;
}else if (getZanr() == "Strategija"){
result *= 1.4;
}else {
result *= 1;
}
break;

76
Dejan Stuparid, Softverska metrika

case PROGRAM:
result += 4;
if (koefSad > 3){
result *= koefSad / 3;
}
break;
}
return result;
}
}
***
public class CDKlub {

public double getKolicina() {
return this.cd.getNaplata(getDuzinaIznajmljivanja(),
getKoeficijentSadrzaja());
}
}
Izvornom Kôd 3 – Premeštanje metoda getKolicina

Kao što se vidi iz primera napravili smo novi metod getNaplata u klasi
JedanCD, u koji je prekopirana sva funkcijonalnost metoda getKolicina, a on u
novoj verziji sadrži samo poziv metoda getNaplata sa parametrima
duzinaIznajmljivanja i koeficijentSadrzaja iz klase CDKlub.

Izanalizirajmo stanje u programu koristedi sledede metrike. Nažalost ne


možemo da predstavimo smislenije vrednosti za metrike koje mere karakteristike
nasleđivanja, iz prostog razloga jer nasleđivanje još uvek ne postoji u našem kôdu. Ali
zato demo posmatrati mere kompleksnosti kako bismo ispratili najsvežije promene.

Metod/Klasa Metrika Vrednost


LOC (Klase CDKlub) 32
LOC (Metoda getKolicina) 1
CYCLO (Metoda getKolicina) 1
getKolicina/CDKlub CYCLO (Klase CDKlub) 1
NORM (Klasa CDKlub) --
NOC (Klasa CDKlub) --
DIT (Klasa CDKlub) 1
LOC (Klase JedanCD) 75
LOC (Metoda getNaplata) 32
CYCLO (Metoda getNaplata) 10
getNaplata/JedanCD CYCLO (Klase JedanCD) 1.9
NORM (Klasa JedanCD) --
NOC (Klasa JedanCD) --
DIT (Klasa JedanCD) 1
Tabela 13 – Karakteristike klasa JedanCD i CDKlub, sa fokusom na metrike
nasleđivanja

77
Dejan Stuparid, Softverska metrika

Kao što smo očekivali kompleksnost klase JedanCD se povedala, dok se


istovremeno kompleksnost klase CDKlub smanjila. Nastavidemo sa refaktorisanjem
kako bismo inkorporirali hijerarhiju nasleđivanja.
U Izvornom Kôdu 14 vidimo promene koje smo napravili kako bismo ideju o
nasleđivanju sproveli u delo.

package testPaket;
public class JedanCD {

private Cena cenaCD;

public int getCenaCD() {
return cenaCD.getCena();
}

public void setCenaCD(int arg) {


switch(arg){
case FILM:
cenaCD = new CenaFilma();
break;
case MUZIKA:
cenaCD = new CenaMuzike();
break;
case IGRA:
cenaCD = new CenaIgre();
break;
case PROGRAM:
cenaCD = new CenaPrograma();
break;
default:
throw new IllegalArgumentException("Pogrešan
format cene!");
}
}

}
***

package testPaket;
public abstract class Cena {
abstract int getCena();
}
***

package testPaket;
public class CenaFilma extends Cena {

@Override
int getCena() {
return JedanCD.FILM;
}
}
***

78
Dejan Stuparid, Softverska metrika

package testPaket;
public class CenaIgre extends Cena{

@Override
int getCena() {
return JedanCD.IGRA;
}
}
***
package testPaket;
public class CenaMuzike extends Cena {

@Override
int getCena() {
return JedanCD.MUZIKA;
}
}
***
package testPaket;
public class CenaPrograma extends Cena{

@Override
int getCena() {
return JedanCD.PROGRAM;
}
}
Izvorni Kôd 4 – Formiranje hijerarhije nasleđivanja

Pošto pregledamo gornju sekciju izvornog kôda, vidimo da smo napravili čak
pet novih klasa. Napravili smo apstraktnu klasu Cena, koja sadrži apstraktan metod
getCena, koji de redefinisati sve klase koje nasleđuju klasu Cena. Takođe prepravili
smo metode getCenaCD i setCenaCD unutar klase JedanCD, kako bismo ispratili
promene nastale formiranjem hijerarhije nasleđivanja. Naime metod getCenaCD
poziva metod getCena apstraktne klase Cena koji je implementiran u klasama
naslednicama. Dok je metod setCenaCD promenjen tako da sadrži jednu switch
naredbu koja stvara nove instance klasa CenaFilm, CenaMuzika, CenaIgra ili
CenaProgram u zavisnosti od argumenta koji se prosleđuje.

Pre nego što predstavimo vrednosti metrika, napravidemo još jednu bitnu
izmenu. Premestidemo metod getNaplata iz klase JedanCD u klasu Cena. Na
ovaj način dajemo vedu odgovornost naslednicama klase Cena.
Pogledajmo ovu izmenu u Izvorni Kôd 15:

package testPaket;
public abstract class Cena {

public double getNaplata(JedanCD cd, int danIznajm, int
koefSad){
double result = 0;
switch (getCena()){

79
Dejan Stuparid, Softverska metrika

case JedanCD.FILM:
result += 1;
if (danIznajm > 2){
result += (danIznajm- 2)*1.5;
}
break;
case JedanCD.MUZIKA:
result += 2;
if (cd.getKvalitetZvuka() > 3){
result *= cd.getKvalitetZvuka()/3;
}
break;
case JedanCD.IGRA:
result += 3;
if (cd.getZanr() == "Akcija"){
result *= 1.5;
}else if (cd.getZanr() == "Strategija"){
result *= 1.4;
}else {
result *= 1;
}
break;
case JedanCD.PROGRAM:
result += 4;
if (koefSad > 3){
result *= koefSad / 3;
}
break;
}
return result;
}
}
***
package testPaket;
public class JedanCD {

public double getNaplata(JedanCD cd, int danIznajm, int
koefSad){
return cenaCD.getNaplata(cd, danIznajm, koefSad);
}
}
Izvorni Kôd 5 – Premeštanje metoda getNaplata

Kao što vidimo metod getNaplata je kompletno premešten u klasu Cena


kako bi bio kasnije redefinisan u naslednicama klase Cena. Primetidemo da metod
getNaplata klase Cena nije apstraktan, ovo je ostavljeno kako bi program mogao
da se kompajlira pre nego što metod redefinišemo u nasledničkim klasama. Metod
getNaplata klase JedanCD jedino poziva metod getNaplata klase Cena kako
bi dobio tražene informacije.

80
Dejan Stuparid, Softverska metrika

Pogledajmo vrednosti metrika u Tabeli 14:

Metod/Klasa Metrika Vrednost


LOC (Klase Cena) 38
LOC (Metoda getNaplata) 32
CYCLO (Metoda getNaplata) 10
getNaplata/Cena CYCLO (Klase Cena) 5.5
NORM (Klasa Cena) 0
NOC (Klasa Cena) 4
DIT (Klasa Cena) 1
LOC (Klase JedanCD) 28
LOC (Metoda getNaplata) 1
CYCLO (Metoda getNaplata) 1
getNaplata/JedanCD CYCLO (Klase JedanCD) 1.4
NORM (Klasa JedanCD) 0
NOC (Klasa JedanCD) 0
DIT (Klasa JedanCD) 1
LOC 7
CYCLO 1
CenaFilma NORM 1
NOC 0
DIT 2
LOC 7
CYCLO 1
CenaMuzike NORM 1
NOC 0
DIT 2
LOC 7
CYCLO 1
CenaIgre NORM 1
NOC 0
DIT 2
LOC 7
CYCLO 1
CenaPrograma NORM 1
NOC 0
DIT 2
Tabela 14 – Karakteristike klasa koje čine novoformiranu hijerarhiju nasleđivanja

Analizirajmo podatke iz Tabele 14. Mere kompleksnosti nam govore da je sada


najkompleksnija klasa Cena, jer smo u nju premestili funkcionalnost iz klase
JedanCD. Nastavimo ka metrikama koje nam mogu otkriti pojedinosti o hijerarhiji

81
Dejan Stuparid, Softverska metrika

nasleđivanja u našem programu. Vidimo da klasa Cena (koja je apstraktna) ima 4


nasledničke klase (NOC) koje redefinišu metod getNaplata. Takođe klasa Cena ne
redefiniše niti jedan metod (NORM), a ovo je posledica toga što se nalazi na vrhu
hijerarhije. I na kraju metrikom DIT potvrđujemo da se klasa nalazi na vrhu hijererhije,
jer je vrednost metrike 1.
Klasa JedanCD sada ima znatno manju kompleksnost, i nije opteredena
naredbama grananja. Takođe po metrikama (NORM, NOC, i DIT) saznajemo da klasa
JedanCD nije član hijererhije nasleđivanja.
I na kraju analizirajmo klase CenaFilma, CenaMuzike, CenaIgre,
CenaPrograma (referencirademo ove klase objedijeno kao Cenovne Klase, jer imaju
identičan semantički sadržaj). Naime Cenovne Klase su vrlo jednostavne sa strane
kompleksnosti (LOC = 7, CYCLO = 1), jer još uvek nisu redefinisale metod
getNaplata. Metrike nasleđivanja sa druge strane otkrivaju nam da su one članice
hijererhije, i da se nalaze na dnu te hijererhije (DIT = 2, NOC = 0). Metrika NORM nam
stavlja do znanja da Cenovne Klase redefinišu po jedan metod iz svoje superklase
(getCena).
Kroz ceo proces refaktorisanja ovog programa provlači se glomazan segment
oko switch naredbe, pokušademo da primenom polimorfizma eliminišemo ovaj
nedostatak.
U Izvornom Kôdu 16 pogledajmo kako ce izvorni kôd izgledati posle ove
promene.

package testPaket;
public abstract class Cena {
abstract int getCena();
abstract double getNaplata(int kvalZvuka, String znr, int
danIznajm, int koefSad);
}
***

package testPaket;
public class CenaFilma extends Cena {

@Override
double getNaplata(int kvalZvuka, String znr, int danIznajm,
int koefSad) {
int result = 1;
if (danIznajm > 2){
result += (danIznajm - 2) * 1.5;
}
return result;
}
}
***

package testPaket;
public class CenaMuzike extends Cena {

@Override

82
Dejan Stuparid, Softverska metrika

double getNaplata(int kvalZvuka, String znr, int danIznajm, int


koefSad) {
double result = 2;
if (kvalZvuka > 3){
result *= kvalZvuka / 3;
}
return result;
}
}
***

package testPaket;
public class CenaPrograma extends Cena{

@Override
double getNaplata(int kvalZvuka, String znr, int danIznajm, int
koefSad) {
double result = 4;
if (koefSad > 3){
result *= koefSad / 3;
}
return result;
}
}
***

package testPaket;
public class CenaIgre extends Cena{

@Override
double getNaplata(int kvalZvuka, String znr, int danIznajm, int
koefSad) {
double result = 3;
if (znr == "Akcija"){
result *= 1.5;
}else if (znr == "Strategija"){
result *= 1.4;
}else {
result *= 1;
}
return result;
}
}
Kôd 6 – Uvođenje polimorfizma

Konačno dolazimo do poslednje revizije. Klasa Cena je postala potpuno


apstraktna, tj. oba metoda su joj apstraktna i redefiniše ih svaka od klasa naslednica.
U Cenovne Klase smo prebacili segmente starog metoda getNaplata koji odgovara
tipu CD-a za koji je zadužena svaka pojedinačna Cenovna Klasa. Na primer, klasa
CenaIgre pored ved redefinisanog metoda getCena, sada redefiniše i metod
getNaplata. Metod getNaplata klase CenaIgre sadrži algoritam koji
određuje naplatu za tip CD-a Igra.

83
Dejan Stuparid, Softverska metrika

3.2.4. Analiza finalne verzije programa


Pošto smo završili celokupano refaktorisanje navedimo u Tabeli 15
karakteristike svih klasa programa. Na osnovu vrednosti metrika sprovešdemo krajnju
analizu programa kao celine.

Metod/Klasa Metrika Vrednost


LOC (Klase CDKlub) 32
CYCLO (Klase Cena) 1
CDKlub DIT (Klasa Cena) 1
NOM 8
WMC 8
LOC (Klase JedanCD) 59
LOC (Metoda setCenaCD) 16
CYCLO (Metoda setCenaCD) 5
setCenaCD/JedanCD CYCLO (Klase JedanCD) 1.4
DIT (Klasa JedanCD) 1
NOM (Klasa JedanCD) 10
WMC (Klasa JedanCD) 14
LOC 56
CYCLO 1.222
Musterija DIT 1
NOM 9
WMC 11
LOC 5
CYCLO 1
NORM 0
Cena NOC 4
DIT 1
NOM 2
WMC 2
LOC (Klasa CenaIgre) 19
LOC (Metod getNaplata) 9
CYCLO (Metod getNaplata) 9
CYCLO (Klasa CenaIgre) 2
getNaplata/CenaIgre NORM (Klasa CenaIgre) 2
NOC (Klasa CenaIgre) 0
DIT (Klasa CenaIgre) 2
NOM (Klasa CenaIgre) 2
WMC (Klasa CenaIgre) 4
LOC (Klasa CenaPrograma) 15
LOC (Metod getNaplata) 5

84
Dejan Stuparid, Softverska metrika

CYCLO (Metod getNaplata) 2


CYCLO (Klasa CenaPrograma) 1.5
NORM (Klasa CenaPrograma) 2
getNaplata/CenaPrograma NOC (Klasa CenaPrograma) 0
DIT (Klasa CenaPrograma) 1
NOM (Klasa CenaPrograma) 2
WMC (Klasa CenaPrograma) 3
LOC (Klasa CenaFilma) 15
LOC (Metod getNaplata) 5
CYCLO (Metod getNaplata) 2
CYCLO (Klasa CenaFilma) 1.5
getNaplata/CenaFilma NORM (Klasa CenaFilma) 2
NOC (Klasa CenaFilma) 0
DIT (Klasa CenaFilma) 2
NOM (Klasa CenaFilma) 2
WMC (Klasa CenaFilma) 3
LOC (Klasa CenaMuzike) 15
LOC (Metod getNaplata) 5
CYCLO (Metod getNaplata) 2
CYCLO (Klasa CenaMuzike) 1.5
getNaplata/CenaMuzike NORM (Klasa CenaMuzike) 2
NOC (Klasa CenaMuzike) 0
DIT (Klasa CenaMuzike) 2
NOM (Klasa CenaMuzike) 2
WMC (Klasa CenaMuzike) 3
LOC 221
CYCLO 1.289
CYCLO (Najkompleksnijeg metoda) 5
NOM 37
Ukupno
NOA 10
NOC 4
NOCL 9
WMC 49
Tabela 15 – Karakteristike svih klasa po završetku refaktorisanja

Kao što možete primetiti iz Tabele 15, naš program je pretrpeo značajne
izmene u implementaciji, dok je sama funkcionalnost ostala netaknuta. Ka izmenama
u implementaciji prevashodno smo posezali kako bismo program napravili
jednostavnijim za razumevanje i održavanje, kao i da bismo ispoštovali ustaljene
principe objektno-orjentisanog programiranja.
Analizirajmo ukratko finalno stanje našeg programa. Pošto smo promene za
svaku klasu analizirali u prethodnim primerima, ovde demo analizirati promene na
projektu kao celini.

85
Dejan Stuparid, Softverska metrika

Počnimo od metrike LOC, u originalnoj implementaciji imali smo 149 linija


izvornog kôda, dok u finalnoj verziji imamo 221. Zašto je broj LOC povedan?
Primetimo da je broj klasa povedan više od dva puta, što znači da imamo i dodatni
izvorni kôd za deklarisanje klasa, pozivanje metoda i uvoz potrebnih klasa. Takođe
manjali samo neke strukture kako bi postale jasnije, što zahteva nove linije.
Povedanje LOC samo po sebi ne znači da je program postao kompleksniji, ved je u
našem slučaju postao jasniji i ima vedi faktor ponovnog iskorišdenja programa.
Razmatrajmo metriku Kružne složenosti. U originalnoj verziji najkompleksniji
metod je imao CYCLO od čak 10, dok u završnoj verziji najkompleksniji metod ima
CYCLO vrednost od samo 5. Ova promena je posledica deljenja metoda na više
manjih, kao i uvođenje polimorfizma kojim smo znatno umanjili kompleksnost.
Broj klasa je povedan 2.5 puta u novoj nerziji programa (NOCL(početne verzije)
= 4, NOCL(finalne verzije) = 9). Ovakva radikalna promena nastala usled formiranje
klase Cena, i njenog deljenja na podkasle CenaFilma, CenaMuzike, CenaIgre,
CenaPrograma. Opravdanost ove hijerarhije objasnili smo u prethodnom poglavlju,
dok ovde smo navodimo da je ona uzrok povedanja broja klasa.
NOM metrika finalne verzije ima znatno vedu vrednost. U početnoj verziji imali
smo 23 metoda, dok u finalnoj imamo čak 37. Zašto je vrednost NOM metrike toliko
povedana? Još jednom kao glavni argument navodimo povedanje broja klasa, jer sa
više klasa imamo i više metoda. Takođe uspostavljanjem hijerarhije nasleđivanja naše
klase redefinišu metode svaka ponaosob, što povedava ukupan broj metoda.

Pošto smo razmotrili metrike pojedinačno vreme je da nešto kažemo o


projektu sa holističkog aspekta.
Naime, refaktorisanje na ovako malom projektu nema preterano smisla. Tako
da je on ovde vršen isključivo u edukativne svrhe, kako bi na konkretnim primerima
uvideli probleme i njihova rešenja. Takođe naš program sadrži neke nedostatke i
posle refaktorisanja. Na primer potpuno je nekomentarisan, uz to neka imena
promenljivih i klasa nisu baš najsrednije izabrani. Navedeni nedostaci nisu sanirani, jer
bi njihovo ispravljanje ovaj primer načinilo preglomaznim, a pritom ne bi doprinelo
jasnijoj slidi o samoj problematici. Sa druge strane nedostaci koji su ispravljeni
doprineli su da naš izvorni izvorni kôd postane čitkiji, efikasniji, i u duhu objektno-
orjentisanog programiranja.

Kada radimo na velikim korporativnim projektima, sa ogromnim brojem klasa


i metoda, obavljanje refaktorisanja je neophodno. Na takvim prijektima radi veliki
broj ljudi, pa je i jasnoda programa imperativ. Ne jasan program značajno može
redukovati produktivnost osoblja, tako da po svaku cenu treba izbegavati takav
scenario. Refaktorisanjem se mogu popraviti gotovo svi aspekti programa, što je
dovelo do pojave programera koji su specijalizovani za obavljnje ovog posla. Stoga
velike kompanije određuju sredstva potrebna za projekat uključujudi i cenu
refaktorisanja.

86
Dejan Stuparid, Softverska metrika

4. Zaključak
Zadatak ovog diplomskog rada bio je da pokaže kako softverske metrike mogu
biti korisne pri konstruisanju kvalitetnih softverskih sistema. Na samom početku
definisali smo koncepte kao što su: softverske metrike, reinženjerstvo, refaktorisanje,
kao i veliki broj defekata izvornog kôda. Pomodu ovih koncepata predstavili smo širu
primenu softverskih metrika u realnom radu.

U ovom radu posebnu pažnju treba obratiti na praktične primere koji su


predstavljeni u poglavlju 3, jer pomodu njih možemo početi da sagledavamo realnu
sliku u praksi. Još jednom treba napomenuti da je primer izvornog kôda koji je
korišden izrazita trivijalizacija realnih situaciju pri konstrukciji softvera. Realni softver
je uvek komplikovaniji i nepredvidljiviji, tako da su i rešenja raznih defekata
raznolikija.

Ovaj rad takođe može i da predstavlja svojevrstan uvod u polje Softverskih


Metrika, jer pokazuje veliki broj osnovnih koncepata, kao i neke naprednije i time
može da podstakne čitaoce na dalje istraživanje. Na ovaj način širom otvaramo vrata
za dalje istraživanje, čime podstičemo dalji razvoj ove još mlade discipline softverskog
inženjerstva.

87
Dejan Stuparid, Softverska metrika

5. Literatura
1. Object-Oriented Metrics in Practice; Michele Lanza, Switzerland and Radu
Marinescu, Romania; Springer-Verlag Berlin Heidelberg 2006.
2. Software Measurement and Estimation: A Practical Approach; Linda M. Laird
and M. Carol Brennan; Published by John Wiley & Sons, Inc., Hoboken, New
Jersey; 2006.
3. Software Metrics: A Rigorous and Practical Approach Second Edition; Norman
E. Fenton and Shari Lawrence Pfleeger; PWS Publishing Company, 20 Park
Plaza, Boston MA, USA; 1997.
4. Software Metrics; Rüdiger Lincke, M.Sc. School of Mathematics & Systems
Engineering; Växjö University; 2005.
5. Refactoring: Improving the Design of Existing Code; Martin Fowler, Kent Beck,
John Brant, William Opdyke, Don Roberts; Publisher: Addison Wesley; First
Edition June 11, 1999.
6. Object-Oriented Design Heuristics; Arthur J. Riel; Publisher: Addison Wesley;
April 30, 1996.
7. Bad code smells - A Taxonomy;
http://www.soberit.hut.fi/mmantyla/BadCodeSmellsTaxonomy.htm
8. Refactoring; http://sourcemaking.com/refactoring/
9. Code Deodorants for Code Smells; http://www.simple-talk.com/dotnet/.net-
framework/code-deodorants-for-code-smells/
10. SmellsToRefactorings;
http://wiki.java.net/bin/view/People/SmellsToRefactorings
11. Reengineering: Definition from Answers.com;
http://www.answers.com/topic/reengineering
12. Dubina stabla nasleđivanja (Depth of Inheritance Tree - DIT):
http://support.objecteering.com/objecteering6.1/help/us/metrics/metrics_in_
detail/depth_of_inheritance_tree.htm
13. Božija Klasa (God Class):
http://c2.com/cgi-bin/wiki?GodClass
14. Softverska Metrika – Wikipedia
http://en.wikipedia.org/wiki/Software_metric
15. Merenje – Wikipedia
http://en.wikipedia.org/wiki/Measurement
16. Softversko inženjerstvo – Wikipedia
http://en.wikipedia.org/wiki/Software_engineering
17. Zašto refaktorisati – Sourcemaking
http://sourcemaking.com/refactoring/why-should-you-refactor

88

You might also like