Professional Documents
Culture Documents
Softverska Metrika: Uvod I Primer
Softverska Metrika: Uvod I Primer
Softverska Metrika: Uvod I Primer
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 -
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.
2
Dejan Stuparid, Softverska 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
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
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.
7
Dejan Stuparid, Softverska metrika
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.
8
Dejan Stuparid, Softverska metrika
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
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
12
Dejan Stuparid, Softverska metrika
13
Dejan Stuparid, Softverska metrika
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.
14
Dejan Stuparid, Softverska metrika
15
Dejan Stuparid, Softverska metrika
16
Dejan Stuparid, Softverska metrika
Navedimo jedan primer pomodu koga demo lakše razumeti proces računanja
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
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
18
Dejan Stuparid, Softverska metrika
( )
Dok TCC računamo slededom formulom: , pri čemu NDC
( )
prikupljamo direktnim merenjem.
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.
C1
C2 C3
C4
C5
DIT(C1) = 1
DIT(C2) = 2
DIT(C3) = 2
DIT(C4) = 3
DIT(C5) = 4
20
Dejan Stuparid, Softverska metrika
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.
22
Dejan Stuparid, Softverska metrika
23
Dejan Stuparid, Softverska metrika
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.
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.
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.
26
Dejan Stuparid, Softverska metrika
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.
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
28
Dejan Stuparid, Softverska metrika
„One Class to rule them all, and in the darkness bind them.“
„Jedna klasa da vlada nad svima, i u tami ih ujedini“ (13)
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
30
Dejan Stuparid, Softverska metrika
Kako bismo rešili ovaj problem oslanjamo se na jednu od dve sledede strategije
predstavljene na Slici 6.
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.
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.
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
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.
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
import Class1.*;
import Class2.*;
34
Dejan Stuparid, Softverska metrika
35
Dejan Stuparid, Softverska metrika
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.
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.
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.
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.
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
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)
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.
40
Dejan Stuparid, Softverska metrika
41
Dejan Stuparid, Softverska metrika
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).
43
Dejan Stuparid, Softverska metrika
Navedimo pravilo saradnje koje de nam biti ideja vodilja u ovoj sekciji rada.
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.
45
Dejan Stuparid, Softverska metrika
46
Dejan Stuparid, Softverska metrika
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.
47
Dejan Stuparid, Softverska metrika
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
48
Dejan Stuparid, Softverska metrika
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.
49
Dejan Stuparid, Softverska metrika
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.
50
Dejan Stuparid, Softverska metrika
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.
a.getCountry().getGroupOrganization().getOrganizationId().getTeamId(
).getTeamMemberId().getTeamMemberAddress().setZipCode();
Izvorni Kôd 4 – Primer 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.
51
Dejan Stuparid, Softverska metrika
52
Dejan Stuparid, Softverska metrika
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.
53
Dejan Stuparid, Softverska metrika
54
Dejan Stuparid, Softverska metrika
55
Dejan Stuparid, Softverska metrika
56
Dejan Stuparid, Softverska metrika
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.
57
Dejan Stuparid, Softverska metrika
58
Dejan Stuparid, Softverska metrika
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.
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.
59
Dejan Stuparid, Softverska metrika
60
Dejan Stuparid, Softverska metrika
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
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
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)
63
Dejan Stuparid, Softverska metrika
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.
package testPaket;
public class JedanCD {
64
Dejan Stuparid, Softverska metrika
package testPaket;
public class CDKlub {
65
Dejan Stuparid, Softverska metrika
package testPaket;
public class Musterija {
double ukupno = 0;
66
Dejan Stuparid, Softverska metrika
int cestoIznajmljeni = 0;
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
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
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 += "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:
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
72
Dejan Stuparid, Softverska metrika
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
74
Dejan Stuparid, Softverska metrika
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
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.
77
Dejan Stuparid, Softverska metrika
package testPaket;
public class JedanCD {
…
private Cena cenaCD;
…
public int getCenaCD() {
return cenaCD.getCena();
}
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
80
Dejan Stuparid, Softverska metrika
81
Dejan Stuparid, Softverska metrika
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
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
83
Dejan Stuparid, Softverska metrika
84
Dejan Stuparid, Softverska metrika
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
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.
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