materiali plote ledjo allkoja
TRANSCRIPT
Analiza ,implementimi dhe optimizimi gabimeve në kod
1
Përmbajtje Abstrakt ......................................................................................................................................................... 4
1 Hyrje ...................................................................................................................................................... 5
1.1 Qëllimi ........................................................................................................................................... 6
1.2 Organizimi ..................................................................................................................................... 6
2 Testimi i software-it dhe gabimet në kod ............................................................................................. 7
2.1 Hyrje .............................................................................................................................................. 7
2.2 Defektet në software .................................................................................................................... 9
2.3 Nivelet e testimit ......................................................................................................................... 10
2.4 Metodat e testimit ...................................................................................................................... 12
2.5 Llojet e testimit ........................................................................................................................... 14
2.6 Metrikat e testimit ...................................................................................................................... 15
3 Parashikimi i gabimeve në kod ........................................................................................................... 17
3.1 Hyrje ............................................................................................................................................ 17
3.2 Cikli i jetës së një gabimi në kod ................................................................................................. 18
3.3 Klasifikimi .................................................................................................................................... 20
3.4 Gjetja e gabimeve në kod dhe mjetet e gjurmimit ..................................................................... 23
3.4.1 Sisteme efektive në gjurmimin e gabimeve në kod ............................................................ 24
3.5 Modelet e parashikimit të gabimeve në kod .............................................................................. 25
3.5.1 Metrikat e bazuar tek ndryshimet ...................................................................................... 26
3.5.2 Metrikat e kodit .................................................................................................................. 27
3.5.3 Metrikat e organizimit ........................................................................................................ 30
4 Mjetet e përdorura ............................................................................................................................. 32
4.1 SOTA ............................................................................................................................................ 32
4.1.1 Si punon SOTA ..................................................................................................................... 33
4.1.2 Tipet e përdorimit ............................................................................................................... 33
4.1.3 Puna me SOTA ..................................................................................................................... 34
4.2 CCCC ............................................................................................................................................ 36
4.2.1 Metrikat e shfaqura ............................................................................................................ 37
4.2.2 Metodat e numërimit ......................................................................................................... 38
Analiza ,implementimi dhe optimizimi gabimeve në kod
2
5 Analiza Dinamike ................................................................................................................................. 40
5.1 Objektivi dhe motivimi. ............................................................................................................... 40
5.2 Software-i nën testim. Rast studimor. ........................................................................................ 40
5.2.1 Implementimi i rastit studimor. .......................................................................................... 40
5.3 Përmbledhje ................................................................................................................................ 47
5.3.1 Klasa testuese në Java ......................................................................................................... 47
6 Analiza Statike ..................................................................................................................................... 48
6.1 Problemet ne kualitetin software-ik dhe matjet e tij. ............................................................... 48
6.1.1 Objektivi dhe motivimi. ....................................................................................................... 48
6.1.2 Software-i nën testim ......................................................................................................... 48
6.1.3 Komentet mbi vlerat e metrikave MVG dhe LOC ............................................................... 48
6.2 Klasa Error.java ........................................................................................................................... 49
6.2.1 Rezultatet e CCCC ................................................................................................................ 49
6.2.2 Rezultatet e SOTA ............................................................................................................... 50
6.3 Scaner.java .................................................................................................................................. 51
6.3.1 Rezultatet e CCCC ................................................................................................................ 53
6.3.2 Rezultatet e SOTA ............................................................................................................... 54
6.4 Avantazhet dhe disavantazhet e kompleksitetit çiklomatik ....................................................... 55
6.4.1 Vlerat e këqija për kompleksitetin çiklomatik .................................................................... 57
6.4.2 Matje shtesë........................................................................................................................ 58
7 Optimizimi dhe sfidat në të ardhmen ................................................................................................. 60
7.1 Optimizimi i gabimeve në kod .................................................................................................... 60
7.2 Nivelet e optimizimit ................................................................................................................... 60
7.3 Platforma e varur dhe optimizimi i pavarur ................................................................................ 62
7.4 Pikat bllokuese ............................................................................................................................ 62
7.5 Kostoja e optimizimi.................................................................................................................... 62
7.6 Sfidat e optimizimit ..................................................................................................................... 63
8 Përfundimet ........................................................................................................................................ 64
Lista e figurave ............................................................................................................................................ 65
Lista e tabelave ........................................................................................................................................... 66
Shtojca 1 ...................................................................................................................................................... 67
Analiza ,implementimi dhe optimizimi gabimeve në kod
3
Shtojca 2 ...................................................................................................................................................... 69
Shtojca 3 ...................................................................................................................................................... 82
Referencat ................................................................................................................................................... 87
Analiza ,implementimi dhe optimizimi gabimeve në kod
4
Abstrakt Defektet në software janë gjendje, që nuk i përgjigjen kërkesave të software-it ose
pritshmërive të përdoruesit përfundimtar. Me fjalë të tjera, janë gabime në kod ose gabime
logjike, të cilat çojnë në keqfunksinimin e programit ose në rezultate të gabuara.
Kjo paper prezanton analizën e kodeve burim të porgrameve te zhvilluara në java ,për te
ilustruar identifikimin e bugeve dhe realizimin e një testimi të mirfilltë software-ik.
Testimi software është një aktivitet thelbësor për të kontrolluar dhe provuar korrektësinë e
sjelljes e software-it sipas specifikimit të tij. Testimi përballet me problemin për të gjetur setin
e të gjitha rasteve të mundshme të testit e cila ka një probabilitet të lartë për të zbuluar gabimet.
Një mënyrë për të adresuar këtë problem është të përdoret testimi i strukturuar (p.sh duke
përdorur Sota).
Analizohet zgjedhja e testcase-ve specifike për te qëne në numrin minimal të tyre dhe arsyet pse
në nje kod burim nuk mbulohen plotësisht gjithë nyjet apo deget e tij lidhur me problemet ne
kod. Në aspektin e metrikave nëpëmjet CCCC dhe SOTA realizohet për cdo njësi ,modul ,klase
rishikimi i parametrave si kualitetin software-ik, kompleksitetin cikolmatik, gjatësine, përmasën,
numrin e variablave, parametrave etj. Do të diskutohet se fundmi optimizime të mundshme ne
aspektin software-ik në kodet përkatëse.
Terminologji – Me termin “Gabime ne kod” në këtë material do t‟i referohemi termit “software
bug” në anglisht, i cili në këtë material ka kuptimin e një sjellje difektoze në program që
rregullohet nëpërmjet ndryshimeve semantike në kodin burim.
Analiza ,implementimi dhe optimizimi gabimeve në kod
5
1 Hyrje Lidhur me fenomenin e rritjeve në internet është e rëndësishme të testohet dhe të rishikohet
kodi software për të shmangur ndodhjen e buge-ve dhe shmangjen e pjeseve te kodit të pa
nevojshme të cilët thjesht rritin kohën e kompilimit.Lidhur me këte kompanitë shtetet janë të
prirura për të investuar sasi të mëdha parash pë të rritur kualitetin software-ik. Kështu testimi
software është vlerësuar për të marrë rreth 50% të kohës dhe kostove të procesit të zhvillimit të
software-it .
Inxhinierët e testimit janë përballur me problemin për të gjetur një setin e të gjitha rasteve të
mundshme të testit e cila ka një probabilitet të lartë për zbuluar gabimet .
Në këtë temë ne fokusohemi në testimin e kodeve te programeve në java duke realizuar një
analizë statike. Analiza statike nënkupton ekzaminimin e një pjese të kodit pa e ekzekutuar atë.
Kjo i referohet analizës së kompleksitetit të kodit në lidhje me rritjen e numrit të rrjeshtave të
kodit, kohës së zhvillimit dhe kohës gjatë ekzekutimit të kodit. Shumë tool-se të automatizuara
janë zhvilluar për të realizuar këtë analizë.
Në këtë tezë prezatoj një tools shumë efektiv sic është CCCC dhe SOTA (e përdorur për të dyja
analizat) të ekzekutuara në platform të ndryshme si psh Windows, Mac, Linux. Metrikat
software-ike përcaktohet si një objektiv si një mates matematik që është i ndjeshëm në
diferencën në karakteristikat software-ike. Qëllimi i tij ështe njohja e procesit software-ik duke
kontrolluar aspekte të ndryshme. Thuhet që këto metrika përdoren për të rritur mundësinë e
identifikimit, kontrollit dhe matjen e parametrave esenciale.
Informacioni i mbledhur nga metrikat software-ike mund të pëdoren për të menaxhuar dhe për
parashikuar procesin e zhvillimit. Disa nga cilësite ideale të metrikave software janë:
1. Duhet të jetë i thjeshtë, lehtësisht i pëcaktuar dhe i qartë
2. Duhet të jetë i vlefshëm
3. Duhet të jetë i „fortë‟ në natyrë
Në varësi me metrikat software që veprojnë janë klasifikuar në dy tipe:
Metrikat e tipit të testimit
Mat produktet e software. (Psh kodi burim dhe dokumentet e dizenjimit)
Metrikat e tipit të procesit
Psh tipi i metodologjisë, numrin e ndryshimeve të bëra në dokument dhe numrin e
bugeve të rikuperuara gjatë testimit
Kjo tezë diskuton kualitetin e dhënë nga një standard si ISO, rëndësinë e kualitetit gjatë procesit
të zhvillimit,dhe së fundmi zgjedhjen e metrikave software si metrikat e pëmasës (size-metrics),
metrika e kompleksitetit metrikat e defekteve për të vlerësuar kodet në java .
Analiza ,implementimi dhe optimizimi gabimeve në kod
6
Ndërsa teknika e vlerësimit software-ik gjatë kompilimit njihet si analiza dinamike. Kështu që
analiza dinamike është më thelbësore pasi përdoret për të testuar gabimet logjike dhe stresin e
testimit gjatë ekzekutimit në një mjedis me burime të kufizuara.
Lidhur me analizën dinamike nëpërmjet SOTA e cila ka nëntë parametra që do të prezantohen në
rastet studimore të mëposhtme anlaizohet në mënyrë të hollësishme pse jo të gjithë mbulimet
(coverage) nuk realizohen 100% duke shpjeguar arsyet. Shikohet se për gjashtë parametrat e parë
mbulimi është realizuar i plotë kurse për 3 të fundit ka një rënie dhe maximum që u arrit 43.6%.
Kjo tezë bën një kontribut në fushën e Software Engineering e mbështetur në aspektein empirik
dhe analitik të kodeve reale (me numër të vogël LOC) dhe në fund realizimin e përgjithësimeve
për kode shumë të mëdha (Referuar LOC).
1.1 Qëllimi Qëllimi i kësaj teme është të studiojë gabimet që ndodhin në kodet e ndërtuara në
programet në java dhe nëpërmjet tyre te realizoj përgjithësime për super programe. Këto gabime
do të analizohen në aspektin e kompleksitetit ku shpjegohet dhe ndikimi i kompleksitetit në
mundësinë për gabime, rritja e pëmasave te kodit (LOC). Përveç kësaj shikohet mbulimi i kodit
ne 9 parametrat e specifikuara nga programi .
Për të realizuar këtë gje përdoren dy programe SOTA dhe CCCC. Këto rezultate janë
interpretuar dhe në bazë të tyre nxirren përfundime në forme raportesh. Këto raporte do të
shprehin dhe ndikimin e tyre ne gabimet në kod, që është dhe thelbi i studimit të kësaj teme
diplome.
1.2 Organizimi Materiali është organizuar në shtatë kapituj. Në kapitullin e dytë trajtohet testimi i
software-it kryesisht testimi i gabimeve në kod. Ky kapitull jep një pasqyrë të defekteve në
software, niveleve të testimit, metodave , llojeve si dhe metrikat e testimit. Kapitulli i tretë
fokusohet tek parashikimi i gabimeve në kod, cikli i jetës së një gabimi, klasifikimi dhe gjetja e
tyre, mjetet e gjurmimit dhe modelet për parashikimin e gabimeve. Toolset e përdoruara për
realizimin e implementimit, ku shpjegohet manuali i përdorimit dhe mënyrën se si funksionon,
janë pjesë e kapitullit të katërt. Kapitulli i pestë paraqet implementimin e një rasti studimor, një
analize e detajuar statike të realizuar me anën e CCCC tool-s i shpjeguar në kapitullin e
mëparshëm. Analiza dinamike dhe analiza e hollësishme e parametrave të mbulimit të kodit
është pjesë e kapitullit të gjashtë. Kapitulli shtatë paraqet mundësi optimizimi të kodit e cila
mund të shihet si punë në të ardhmen, pse jo futjen e inteligjencës artificiale për kode
vetëkorrigjuese.
Për ilustrim të studimit në shtojcat e pas kapitujve do të paraqiten tabelat, gafikët për sejcilin nga
rastet ilustrues dhe kodet burim të shkruara në java, të përdoruar për këtë studim të bëre. Së
fundmi paraqiten konkluzionet e nxjerra nga kjo punë si dhe referencat e përdorura.
Analiza ,implementimi dhe optimizimi gabimeve në kod
7
2 Testimi i software-it dhe gabimet në kod
2.1 Hyrje Software-ët po bëhen gjithmonë e më shumë kompleks dhe të shumëllojshëm. Si rrjedhojë
e kësaj edhe kërkesat ndaj tyre janë rritur. Kërkohet që software-ët të kenë kosto më të ulët, të
kenë më shumë funksionalitete, të jenë më të shpejtë dhe me një cilësi më të mirë se më parë.
Krijimi dhe zhvillimi i një software-i kalon në disa faza, ku secila fazë përdor rezultatet e fazës
së mëparshme. Më poshtë po japim një përshkrim të shkurtër të tyre:
Specifikimi i kërkesave dhe analiza – kjo fazë kërkon të specifikohen kërkesat e
përdoruesit, por edhe kërkesat e vetë software-it.
Projektimi – kërkesat e marra nga faza e parë ndahen në module të pavarura duke krijuar
nivele më të vogla
Kodimi – programuesit shkruajnë kodin e projektit sipas gjuhës së përzgjedhur të
programimit
Testimi – në këtë fazë krijohet një plan testimi, vihet në zbatim dhe dokumentohen
rezultatet e marra
Implementimi – është faza e instalimit të produkteve të nevojshme në mjediset përkatëse
Mirëmbajtja – pasi është krijuar software-i dhe ka filluar përdorimi nga përdoruesit,
mirëmbajtja është faza e rradhës
Në varësi se si shfrytëzohen këto faza, janë krijuar modelet e ciklit të jetës së një software-i. Disa
prej këtyre modeleve janë: modeli waterfall, “V”, spiral, iterativ dhe inkremental.
Figura 1 Fazat e zhvillimit të një software
Analiza ,implementimi dhe optimizimi gabimeve në kod
8
Figura 2 Modeli Waterfall
Sic shihet, testimi është një nga fazat e zhvillimit të një software. Kjo fazë fokusohet në një
hetim empirik, ku rezultatet përshkruajnë cilësinë e sistemit. Testimi nuk mund të konfirmojë që
sistemi funksionon siç duhet në të gjitha kushtet, por mund të provojë se ai dështon për kushte të
caktuara. Sa me shpejt që të gjendet defekti gjatë procesit të zhvillimit, aq më e vogël është
kostoja e rregullimit. Testimi i hershëm redukton rreziqet si vonesat ose tejkalimi i kostos. Në
fazën e testimit, ai provon nëse janë plotësuar të gjitha kërkesat, përfshirë edhe kërkesat e
performancës dhe sigurisë. Si përfundim, testimi konfirmon që sistemi plotëson kërkesat e
përdoruesit dhe përmbush nevojat e biznesit.
Qëllimi i fazës së testimit është të garantojë se sistemi ka ndërtuar dhe testuar me sukses të gjitha
kërkesat dhe parametrat e projektimit në fazat e mëparshme. Pasi kjo fazë kalohet me sukses
shkohet në fazën e implementimit.
Testimi është një proces që realizohet nga grupe dhe persona të ndryshëm. Së pari është
menaxheri i testimit që menaxhon dhe kontrollon projektet e testimit, përcakton planin e testimit
dhe mbikqyr inxhinierët. Këta të fundit hartojnë rastet e studimit (test cases), përcaktojnë
specifikimet dhe ekzekutojnë testet. Me testimin merren edhe grupe të pavaruara testimi. Vetë
përdoruesi pëfundimtar është një testues, i cili kontrollon nëse software i plotëson apo jo
kërkesat. Ndarja në këtë mënyrë e ndihmon procesin sepse testuesit nuk kanë të njëjtat njohuri
për kodin dhe brendësinë e aplikacionit. Është e rëndësishme që kur krijohet dhe ndërtohet një
software të testohet hap pas hapi. Testimi në fund të projektit ka kosto më të mëdha sepse është
më e vështirë të rikthehesh në fillim për të gjetur se ku ka ndodhur problemi dhe për ta rregulluar
atë.
Problemet më të shpeshta të software-it janë[1]:
Gabimet në llogaritje
Analiza ,implementimi dhe optimizimi gabimeve në kod
9
Redaktimet e të dhënave jo të sakta dhe redaktimet e të dhënave jo efektive
Bashkimi dhe përputhja jo korrekte e të dhënave Kërkimet e të dhënave që japin rezultate jo korrekte Përpunimi i pasaktë i të dhënave Kod i pasaktë Performanca e pamjaftueshme e software-it Të dhënat jo të qarta Përdorimi i software-it nga përdoruesit përfundimtar dhe software-ët e vjetëruar Përpunimi jo konsistent Rezultatet jo të besueshme
Ndërfaqe të pamjaftueshme ose të pasakta me sistemet e tjera
2.2 Defektet në software Defektet në sofware janë gjendje, që nuk i përgjigjen kërkesave të software-it ose
pritshmërive të përdoruesit përfundimtar. Me fjalë të tjera, janë gabime në kod ose gabime
logjike, te cilat cojnë në keqfunksionimin e programit ose në rezultate të gabuara.
Shkalla e rëndësisë së defekteve ndryshon në varësi të problemit që ato shkaktojnë. Jo të gjithë
defektet janë seriozë për software-in. Përpara se defektet të parandalohen dhe të hiqen, është e
nevojshme të dihet origjina e defektit dhe çfarë e shkakton atë. Janë tre kategori që shkaktojnë
defektet dhe shtatë origjina të tyre. Shkaqet e defekteve përfshijnë[2]:
Gabimet e komisionit (është bërë diçka e gabuar)
Gabimet e mosveprimit (diçka është lënë pa bërë aksidentalisht)
Gabimet e qartësisë dhe dykuptimësisë (dy persona kanë interpretime të ndryshme)
Gabimet e komisionit i referohen problemeve të shkaktuara nga një veprim jo korrekt, si
përfshirja e gjendjeve të caktuara në një specifikim me të cilin janë reciprokisht kontradiktore.
40-65% e problemeve të numëruara në një software i përkasin gabimeve të komisionit, duke e
bërë këtë kategori si shkaktaren kryesore të defekteve.
Gabimet e mosveprimit i referohen problemeve të shkaktuara nga një dështim për të përfshirë
informacion jetik. 15-30% e problemeve të numëruara në një software i përkasin gabimeve të
mosveprimit. Probabiliteti dhe frekuenca e këtyre defekteve është në përpjestim të drejtë me
madhësinë e sistemit.
Gabimet e qartësisë dhe dykuptimësisë i referohen problemeve të shkaktuara nga dy ose më
shumë interpretime të të njëjtit informacion. Shembull i një gabimi të tillë është shprehja “kohë
përgjigje e shpejtë”, ku “e shpejtë” nuk ka një përcaktim fiks. Përafërsisht 5-10% e problemeve
të numëruara në një software i përkasin këtij grupi të gabimeve.
Për sa i përket origjinës së defekteve, më poshtë paraqitet një listë e tyre:
Defektet në kërkesat e software-it
Defektet në projekt
Defektet në kod
Analiza ,implementimi dhe optimizimi gabimeve në kod
10
Defektet në dokumentacion
Defektet “Bad Fixes”
Defektet në të dhëna dhe tabela
Defektet në rastet e studimit (test cases)
Shkaktarët e defekteve në kërkesat e software-it janë të treja kategoritë e mësipërme, por më të
shpeshta janë gabimet e mosveprimit dhe gabimet e qartësisë dhe dykuptimësisë. Këto lloj
defektesh, që lindin që në fillim të projektit, nëse nuk parandalohen dhe nuk hiqen depërtojnë
dhe në hapat e mëposhtëm (projektimi, kodi dhe dokumentacioni). Janë defektet që kërkojnë
koston më të lartë dhe që kanë më shumë vështirësi në eleminimin e tyre. Për të reduktuar këto
defekte, parandalimi është më efikas se heqja e tyre. Vështirësia më e madhe vjen nga kërkesat
që bazohen në gjuhën natyrale. Për ta shmagur këtë, janë zhvilluar disa metoda për t‟i përcaktuar
kërkesat në gjuhë formale, por nuk janë ende gjerësisht të përdorura. Shkaktarët e defekteve në
projekt janë të treja kategoritë, por më të shpeshta janë gabimet e mosveprimit, ku lihen gjëra pa
bërë, si dhe gabimet e komisionit, ku diçka është deklaruar, por rezulton e gabuar më vonë. Edhe
gabimet e qartësisë dhe dykuptimësisë janë të shpeshta dhe shumë probleme që lidhen me
performancën lindin pikërisht nga ky shkak. Edhe këto defekte kanë kosto të lartë dhe vështirësi
në trajtimin e tyre.
Shkaktarët e defekteve në kod janë të treja kategoritë, ku gabimet e komisionit janë dominante
gjatë kohës së krijimit të kodit. E vecanta e defekteve në kod është se 50% e gabimeve serioze të
gjetura në kodin burim nuk e kanë origjinën nga kodi. Pjesa më e madhe gabimeve ndodhin në
rastet kur programuesi nuk e kupton qartë projektin, ose kur projekti nuk i interpreton kërkesat
ashtu si duhet.
Dokumentacioni për përdoruesin si në formën e manualit, ashtu edhe në formën e informacionit
online, mbart gabime të mosveprimit dhe të komisionit. Në fakt, defektet më të shpeshta i
përkasin gabimeve të qartësisë dhe dykuptimësisë. Fraza “Bad Fixes” i referohet tentativës për të
riparuar një gabim që edhe pse gabimi origjinal mund të jetë rregulluar, paraqet ende një gabim
në kod për aplikacionin. Zakonisht “Bad Fixes” janë gabime të komisionit. Ato janë defekte të
shpeshta dhe mund të jenë edhe serioze për aplikacionin. 5-20% e tentativave për të riparuar
gabime në kod mund të shkaktojnë një gabim të dytë në kod. “Bad Fixes” lidhen fort me nivelet
e larta të kompleksitetit.
Defektet e të dhënave mund të jenë shumë serioze dhe mund të ndërveprojnë me gabimet e
software-it për të krijuar probleme edhe më të mëdha dhe me kosto më të lartë. Shumë nga
problemet në aplikacione njerëzit i vënë re tek defektet e të dhënave. Gabime të tilla si gabimet
në faturat e shërbimeve, pasqyrat financiare, gabime të taksave, regjistrimin e automjeteve
motorike janë shpesh gabime të të dhënave.
Rastet e studimit kanë për qëllim të sigurojnë që çdo karakteristikë e aplikacionit punon siç duhet
dhe se materialet e reja nuk kanë shkaktuar gabime në pjesë ekzistuese të aplikacionit. Gabimet
në rastet e studimit ndodhin kur këto raste të krijuara për testim nuk janë të përshtatshme për
kërkesat e software-it. Në rastet kur bëhen ndryshime në aplikacion, përdoret testimi i regresit, që
nënkupton një set me raste studimi. Regresi i referohet një gabimi të ndodhur gjatë përpjekjes për
të shtuar karakteristika të reja në aplikacion.
2.3 Nivelet e testimit Përpara se një aplikacion të publikohet, ai i nënshtrohet një procesi të plotë të testimit për
tu siguruar se aplikacioni punon në mënyrën në të cilën është kërkuar. Janë katër nivele testimi,
Analiza ,implementimi dhe optimizimi gabimeve në kod
11
të cilat duhet të përmbushen para se programi të jetë gati për përdorim: testimi njësi, testimi i
integruar, testimi i sistemit, dhe testimi i pranimit.
Tetsimi njësi është një nivel i procesit të testimit të software-it ku tetsohen njësi ose komponente
individuale të software-it. Qëllimi është të vlerësojë se çdo njësi e software-it performon ashtu
siç është projektuar. Ky lloj testimi kërkon njohuri të kodit dhe projektit të brendshëm të
programit dhe realizohet nga programuesit. Një njësi i referohet një funksioni, programi
individual ose një procedure. Një nga benefitet kryesore të këtij niveli testimi është se mund të
ekzekutohet sa herë që ndryshon një pjesë kodi, duke bërë të mundur që çështjet të zgjidhen sa
më shpejt të jetë e mundur. Zhvilluesit e software-it realizojnë testimin njësi përpara se ta
dërgojnë për testimin formal[3]. Testimi i integrimit është një nivel i procesit të testimit të
software-it ku njësi individuale kombinohen dhe testohen në grup. Qëllimi është të vëjë në dukje
gabimet në ndërveprimin midis njësive të integruara. Ky nivel testimi është projektuar për të
gjetur defektet e ndërfaqes ndërmjet moduleve. Njësitë e integruara apo grupet që testohen mund
të jenë module kodi, aplikacione individuale ose aplikacione klient-server. Ky testim është
veçanërisht i dobishëm sepse përcakton se sa efikasitet kanë njësitë të ekzekutuara së bashku.
Është me rëndësi fakti se pavarësisht se një njësi funksionon si duhet më vete, ndikon në
funksionalitetin e software-it nëse nuk është e integruar siç duhet. Janë dy metoda që përdoren
për të realizuar testimin e integrimit: testimi nga Poshtë-Lart (Bottom-up) dhe testimi nga Lart-
Poshtë (Top-Down).
Tetsimi nga Poshtë-Lart fillon me testimin njësi dhe ndiqet nga testimet progresive të
kombinimeve të njësive (moduleve) të niveleve më të larta.
Testimi nga Lart-Poshtë teston fillimisht modulet e niveleve të larta dhe më pas teston në
mënyrë progresive modulet e niveleve më të ulta.
Në një mjedis të plotë të zhvillimit të software-it realizohet fillimisht testimi Poshtë-Lart dhe më
pas tetstimi Lart-Poshtë. Testimi i sistemit është një nivel i procesit të testimit ku testohet një
sistem ose software i plotë dhe i integruar. Është niveli i parë në të cilin i gjithë aplikacioni
testohet si i tërë. Qëllimi është të vlerësojë përputhshmërinë e sistemit me kërkesat specifike dhe
nëse përmbush standartet e kualitetit. Ky testim kryet nga testues të pavarur, që nuk kanë pasur
rol në zhvillimin e programit. Është i rëndësishëm sepse vëren që aplikacioni plotëson kërkesat
teknike, funksonale dhe të biznesit ashtu siç kërkohen nga përdoruesi.
Testimi i pranimit është një nivel i procesit të testimit ku sistemi testohet për pranueshmërinë.
Qëllimi është të vlerësojë përputhshmërinë e sistemit me kërkesat e biznesit dhe nëse është i
pranueshëm për tu shpërndarë. Gjate ciklit të jetës së zhvillimit të software-it, ndryshimet e
kërkesave mund të keqinterpretohen në një mënyrë që nuk përputhen me nevojat e përdoruesit.
Pikërisht në këtë fazë, përdoruesi teston nëse sistemi i plotëson nevojat e tij të biznesit. Pasi është
plotësuar ky proces, atëherë programi është gati për përdorim. Ky testim vërteton dhe njëherë
faktin që sa më herët të bëhen testimet aq më shumë defekte zbulohen. Duke realizuar testimin e
pranimit në një aplikacion, grupi i testimit nxjerr në përfundim se si do të punojë aplikacioni në
prodhim. Dallojmë dy faza të testimit të pranimit: testimin Alpha dhe testimin Beta.
Testimi Alpha është faza e parë dhe duhet të performohet nga zhvilluesit dhe grupi i
kualitetit. Kombinimi i testimit njësi, testimit të integrimit dhe testimit të sistemit njihet si
testimi Alpha. Në këtë fazë testohen gabimet drejtshkrimore, linqet e këputura, koha e
ngarkimit dhe problemet e vonesës.
Analiza ,implementimi dhe optimizimi gabimeve në kod
12
Testimi Beta performohet pasi është realizuar me sukses testimi Alpha. Vetëm një pjesë
e vogël e audiencës së parashikuar teston aplikacionin. Njihet ndryshe si testimi i para
lirimit. Në këtë fazë përdoruesi do të instalojë, ekzekutojë aplikacionin dhe do dërgojë
një analizë tek ekipi i projektit. Do të testohen gabimet tipografike, sjelljet konfuze të
aplikacionit dhe rastet e përplasjeve. Pasi merr analizën, ekipi i projektit mund të
rregullojë problemet përpara se ta dorëzojë aplikacionin tek përdoruesit. Sa më shumë
probleme të zgjidhura të jenë, aq më e lartë është dhe cilësia e aplikacionit dhe sa më e
lartë cilësia, aq më e lartë dhe kënaqësia e marrë nga klienti.
Disa tentojnë që të përfshijnë në nivelet e testimit dhe testimin e regresit, por ai nuk është i
nevojshëm. Testimi i regresit është thjesht një lloj testimi që mund të kryhet tek secili nga katër
nivelet e mësipërme.
Figura 3 Nivelet e testimit
2.4 Metodat e testimit Rastet e studimit janë zhvilluar duke përdorur teknika të ndryshme testimi për të arritur
nivele efektive testimi. Ka metoda të ndryshme që mund të përdoren për testimin software-it.
Përmendim testimin Black Box, White Box dhe Gray Box[2].
Testimi Black Box është një teknikë testimi, e cila nuk ka njohuri për brendësinë e aplikacionit
dhe se si ai punon. Testuesi është i pavëmendshëm për akitekturën e sistemit dhe nuk ka akses në
kodin burim. Gjatë këtij testimi, testuesi ndërvepron me ndërfaqen e përdoruesit duke ofruar të
dhëna hyrëse dhe duke gjeneruar rezultate, pa ditur se ku kanë vepruar të dhënat.
Avantazhet e këtij testimi janë:
Të përshtatshme dhe efikase për segmente të mëdha të kodit
Nuk kërkohet akses në kod
Analiza ,implementimi dhe optimizimi gabimeve në kod
13
Në mënyrë të qartë ndan perspektivën e përdoruesit nga perspektiva e zhvilluesit
nëpërmjet përcaktimit të roleve
Shumë testues mund ta testojnë aplikacionin pa patur njohuri për implementimin, gjuhën
e programimit apo sistemin operativ të përdorur
Disavantazhet:
Mbulim i kufizuar sepse vetëm një pjesë e përzgjedhur e rasteve të studimit performohet
Testim jo efikas për shkak se testuesi ka njohuri të kufizuara në lidhje me aplikacionin
Mbulim “i verbër” sepse testuesi nuk mund të synojë segmente kodi specifike apo zona të
caktuara të gabimeve
Rastet e testimit janë të vështira për tu projektuar
Testimi White Box është hetim i detajuar i logjikës dhe strukturës së brendshme të kodit. Quhet
ndryshe testimi i kutisë së hapur. Për të realizuar këtë testim në një aplikacion, testuesi duhet të
ketë njohuri se si punon kodi në brendësi. Gjithashtu duhet të zbulojë se cila njësi e kodit nuk
punon ashtu siç duhet.
Avantazhet janë:
Ndihmon në optimizimin e kodit
Rrjeshtat e tepërt të kodit mund të hiqen
Nisur nga fakti se testuesi ka njohuri për kodin, mbulimi maksimal arrihet gjatë shkrimit
të skenarit të testimit
Disavantazhet:
Ka kosto të lartë
Ndonjëherë është e pamundur për të parë në çdo cep dhe kënd për të gjetur gabime të
fshehura që mund të krijojnë probleme duke qenë së shumë rrugë mbeten pa testuar.
Është e veshtirë për të ruajtur testimin White Box duke qenë se kërkohet përdorimi i
mjeteve të specializuara si analizuesit e kodit apo mjetet për debug.
Testimi Grey Box është një teknikë testimi që kërkon njohuri të limituara të punës së brendshme
të aplikacionit. Ndryshe nga testimi Black Box ku testuesi teston vetëm ndërfaqen e përdoruesit,
në testimin Grey Box testuesi ka akses në bazën e të dhënave dhe në dokumentat e projektit. Me
këto njohuri testuesi është i aftë të përgatisë skenare testimi dhe raste testimi më të mira gjatë
hartimit të planit të testimit. Avantazhet që ofron ky testim janë:
Ofron benefite të kombinuara të testimit Black Box dhe atij White Box
Testuesit nuk mbështeten në kodin burim, por mbështeten tek kërkesat funksionale dhe
përkufizimi i ndërfaqes
Testuesit mund të projektojnë skenare të shkëlqyera testimi rreth protokolleve të
komunikimit dhe trajtimit të llojeve të të dhënave
Testimi realizohet nga pikëpamja e përdoruesit dhe jo nga pikëpamja e projektuesit
Disavantazhet:
Duke qenë se aksesi në kodin burim nuk është i mundur, edhe mbulimi (test coverage)
është i limituar
Analiza ,implementimi dhe optimizimi gabimeve në kod
14
Testet mund të jenë të tepërt nëse projektuesi i software-it ka ekzekutuar një rast testimi
(test case)
Testimi i çdo të dhëne hyrëse të mundshme është i paarsyeshëm sepse merr shumë kohë
dhe rrjedhimisht shumë rrugë mbeten pa testuar
Në tabelën më poshtë paraqitet një krahasim midis të tre metodave të testimit:
Tabela 1 Krahasimi i metodave të testimit
2.5 Llojet e testimit Llojet e testimit fokusohen në objektiva të veçanta testimi. Dallohen dy grupime të llojeve
të testmit, testmi funksional dhe testimi jo funksional. Testimi funksional i referohet aktiviteteve
që testojnë një veprim specifik ose një funksion të kodit. Ky testim tenton t‟i përgjigjet pyetjeve
“A mundet përdoruesi ta bëj këtë?” ose “A punon kjo karakteristik e veçantë”. Testimi jo
funksional i referohet aspekteve të software-it, që nuk lidhen me një funksion specifik ose me një
veprim të përdoruesit si shkallëzueshmëria apo performanca ose siguria.
Analiza ,implementimi dhe optimizimi gabimeve në kod
15
Sipas këtyre dy grupimeve ekzistojnë një numër i madh llojesh testimi. Më poshtë do të
paraqiten vetëm një pjesë e tyre.
Ndër testimet funksionale përmendim[7]:
Testimi i instalimit – fokusohet në çfarë duhet të bëjë klienti për instalimin dhe
funksionimin e saktë të software-it të ri
Testimi i zhvillimit – përfshin aplikacione të sinkronizuara lidhur me strategjitë e
dedektimit të defekteve në mënyrë që të reduktojë risqet, kohën dhe koston. Përfshin
analizat e kodit, analizat e të dhënave, testimin njësi dhe praktika të tjera verifikimi
Testimi i “shëndosh” (sanity testing) – ofron testim të shpejtë dhe të plotë dhe përcakton
nëse është e mundur dhe e arsyeshme për të vazhduar testimin e mëtejshëm. Ky testim
është një mënyrë për të kursyer kohë.
Testimi i rivendosjes – është testimi që tregon se sa i aftë është një aplikacion të rikthehet
në gjendjen fillestare pas përplasjeve, dështimeve në hardware dhe problemeve të tjera të
ngjashme.
Testimi i pranimit nga përdoruesi – konsiston në verifikimin e software-it nëse punon për
përdoruesin.
Lidhur me testimet jo funksionale ndër më të shpeshtat janë:
Testimi i performancës - ka të bëjë me aspektet e shpejtësisë, kapacitetit, stabilitetit dhe
shkallëzueshmërisë së sistemit
Testimi i përdorshmërisë - lidhet me testimin e kërkesave të tilla si; e lehtë për tu mësuar,
e lehtë për tu përdorur, efiçent në përdorim, i kënqshëm në përdorim dhe i lehtë për tu
kuptuar
Testimi i sigurisë - duhet të sigurojë konfidencialitetin, integritetin, autentikimin,
disponueshmërinë, sigurinë e të dhënave etj.
Testimi i portabilitetit - teston nëse software-i mund të ripërdoret dhe të mund të
transferohet në një tjetër kompjuter
2.6 Metrikat e testimit Metrikat e software-it janë teknika ose formula që përdoren për të matur disa karakteristika
të veçanta të software-it. Ato lidhen drejtpërdrejt me matjet dhe matjet kanë rol domethënës në
menaxhimin e software-it.
Metrikat e software-it janë një guidë sasiore e performancës së software-it në raport me
ndërveprimet e njëriut të nevojshme që software-i të punojë. Metrikat janë zhvilluar sipas idesë
se përpara se diçka të matet, duhet të përkthehet në numra. Ato kanë përdorim të gjerë në shumë
fusha.
Metrikat gjejnë zbatim gjatë gjithë ciklit të jetës së zhvillimit të një software-i. Në fillim të
projektit ato përdoren për të përcaktar koston dhe kërkesat e burimeve. Gjatë fazës së projektimit
përdoren për të numëruar pikat e funksionit. Matjet për përmasat e software-it janë një tjetër
aspekt sasior. Për këto matje shërbejnë metrikat e kodit burim si për shembull numri i rreshtave
të kodit. Në mënyrë të ngjashme edhe metrikat e detajuara të projektimit ose të strukturës së
kontrollit çojnë në procesin e testimit. Gjithashtu analiza e kodit ndihmon në përmirësimin e
kostos së mirëmbajtjes së software-it.
Analiza ,implementimi dhe optimizimi gabimeve në kod
16
Matjet efektive japin objektiva të rëndësishme të menaxhimit si kostoja dhe vlerësimi i
burimeve. Nga sa më sipër metrikat zhvillohen për:
Përmasat e software-it
Vlerësimin e kostos
Vlerësimin e përpjekjes
Cilësinë e software-it
Mirëmbajtjen
Modelet e besueshmërisë
Analizat e kompleksitetit
Analizat e defekteve
Testimin e software-it
Metrikat e software-it mund të grupohen si më poshtë:
1. Metrikat e procesit
2. Metrikat e produktit
3. Metrikat e burimeve
Metrikat e software-it qe lidhen me matjet e atributeve të procesit të software-it grupohen si
metrika të procesit. Këto matje përfshijnë vlerësimin e kohëzgjatjes, vlerësimin e kostos,
përpjekjen e kërkuar, cilësinë e procesit dhe efektivitetin e zhvillimit të procesit. Këto metrika
mund të llogariten në çdo hap të zhvillimit të software-it.
Shembull i metrikave të procesit është SLOC(Source Line of Code). Numri i rreshtave të kodit
llogaritet thjesht duke i numëruar ato. Ky numërim jep një të dhënë mbi përpjekjen e bërë për të
zhvilluar kodin.
Matjet mbi produktin nuk përfshijnë vetëm dorëzimin e produktit tek klienti, por gjithashtu edhe
gjithë aktivitetin gjatë procesit të zhvillimit si për shembull dokumentacionin. Ekzistojnë shumë
metrika për matjen e produktit. Ato shërbejnë si për matje të atributeve të jashtme ashtu edhe për
ato të brendshme. Atributet e jashtme kanë të bëjnë me matjet e performancës së produktit në
mjedisin aktual ku duhet të ekzekutohet software. Këto matje përfshijnë përdorimin dhe
ripërdorimin, portabilitetin dhe efiçencën. Atributet e brendshme përfshijnë përmasat e software-
it, saktësinë, kompleksitetin, gabimet në kod dhe testimin.
Metrikat e burimeve janë më shumë të lidhura me menaxherët për vlerësimin e burimeve të
nevojshme për projektin. Këto burime janë fuqia njerëzore (zhvilluesit), burimet fizike
(kompjuterat, materialet, metodat). Janë metrika të cilat mund të klasifikohen edhe në klasën e
metrikave të procesit.
Analiza ,implementimi dhe optimizimi gabimeve në kod
17
3 Parashikimi i gabimeve në kod
3.1 Hyrje
Parashikimi i të ardhmes është shumë tërheqës për njerëzit. Të parashikosh saktë ose në
mënyrë të përafërt të ndihmon të planifikosh punën me më shumë efikasitet. Software-ët
ndërtohen dhe tregtohen dhe shumë defekte apo gabime në kod gjenden në to. Ndonjëherë
konsumatorët duhet të presin për një kohë të gjatë për rregullimin e tyre. Parashikimi i gabimeve
në kod është i dobishëm për dedektimin e tyre në një software. Ai është gjerësisht i studiuar dhe
është një nga temat më të nxehta të kërkimeve shkencore.
Defektet në software janë gabime, të meta ose dështime të programit që e pengojnë atë që të
punojë ashtu siç duhet ose që prodhojnë rezultate të gabuara. Gabimet në kod janë gabime që
kërkojnë ndryshime semantike në kod. Nëse një gabim që në hapat fillestar të programit nuk
shndërrohet në defekt, atëherë jemi me fat, por nëse ai kthehet në defekt, atëherë mund të
shkaktojë dështime dhe duhet të rregullohet.
Ka shumë lloje gabimesh në kod që mund të gjenden në një software. Gjerësisht janë dy tipe
gabimesh: gabimet funksionale dhe gabimet e regresit. Gabimet funksionale në kod lidhen me
funksionalitetin e aplikacionit. Ne duhet të verifikojmë rrjedhën e veprimeve dhe nëse ajo është
jo korrekte ose jo konsistente, atëherë raportohet si gabim që prodhon një sjellje të papritur/jo
logjike të aplikacionit, ku rezultati final ndryshon nga rezultati i pritur. Gabimet e regresit lidhen
me ndryshimet në kodin ekzistues që ndryshojnë sjelljen e aplikacionit. Pra, ai nuk sillet njësoj si
më parë pas ndryshimeve në kod.
Gabimet në kod të një software kanë pasoja të shumta duke filluar nga gliçet e vogla deri tek
humbje jetësh njerëzish dhe të mira materiale. Për shembull, më 1962 një gabim kodi në
kontrollin e fluturimit shaktoi devijimin e raketës nga rruga e përcaktuar. Kjo shkaktoi dështimin
e misionit. Më 1988 më shumë se 2000 kompjutera u infektuan nga “krimbi” i parë kompjuterik,
i cili u bë i mundur nga një gabim në kod në një program Unix. Përgjithësisht përdoren proceset
e rregullimit (debugging) për të gjetur dhe për të eleminuar gabimet nga një program. Procesi
tradicional i rregullimit kërkon rishikim e kodit, përdorimin e mjeteve të përshtatshme, testimet e
llojeve të ndryshme (të regresit apo të njësisë) dhe sërish rishikimin e kodit. Pra, është një punë e
lodhshme dhe që kërkon shumë kohë. Pas gjithë këtyre problemeve mund të themi se
parashikimi i gabimeve në kod është mënyra më e mirë për të gjetur gabimet dhe për të
përmirësuar cilësinë e software-it[8].
Për të identifikuar gabimet në kod janë dy teknika. E para dedektimi i gabimeve në kod dhe e
dyta parashikimi i gabimeve në kod. Në dedektimin e gabimeve në kod, kur programi dështon
kemi mjaftueshëm probleme. Ndoshta me të rrezikshëm mund të jenë gabimet e padedektuara, të
cilat veprojnë në heshtje. Kur një gabim në kod dedektohet në një software, procesi i rregullimit
fillon të gjejë vendodhjen korrekte të këtij gabimi. Dedektimi është një proces që konsumon
kohë dhe fillon në momentin kur gjendet një gabim në software. Identifikimi i moduleve të
prirura për të qenë difektoz është detyrë e rëndësishme për menaxhimin. Parashikimi i gabimeve
Analiza ,implementimi dhe optimizimi gabimeve në kod
18
në kod luan rol të rëndësishëm në zhvillimin software-it. Ai depërton në mirëmbajtjen e
software-it në mënyrë që menaxhimi dhe skuadra e testimit mund të analizojë informacionin për
të përmirësuar cilësinë e software-it.
Parashikimi mund të realizohet me dy mënyra: me intuitë dhe bazuar tek të dhenat. Parashikimi
me intuitë nuk prodhon rezultat të saktë, madje shpesh çon drejt vendimeve të gabuara. Mënyra
më e mirë është parashikimi bazuar tek të dhënat. Shume parashikime në kod janë propozuar të
trajtojnë problemet e software-it duke u mbeshtetur tek infrormacioni i ndryshëm si metrikat e
kodit, metrikat e procesit ose në defektet e mëparshme.
Disa çështje që lidhen me parashikim e gabimeve në kod janë:
Parashikimi i bazuar tek ndryshimet
Parashikimi i bazuar tek problemet
Parashikimi i bazuar tek metrikat
Parashikimi i bazuar tek klasifikimi
Parashikimi i bazuar tek ndryshimet ndihmon zhvilluesit nëpërmjet rekomandimeve të entiteteve
të programit që duhet të ndryshohen së bashku me entitetet që tashmë janë ndryshuar.
Ndryshimet janë studiuar në disa nivele; në nivel klase, në nivel metode dhe në nivel skedari.
Në parashikimin e bazuar tek problemet përfshihen ngjarjet si prodhimi i adresave dhe vlerave
jashtë kufirit, ekzekutimi i rrugëve të pazakonta të kontrollit, shkaktimi i dështimeve, llogaritjet e
tepërta, gjenerimi i alarmeve false dhe shumë të tjera.
Parashikimi bazuar tek metrikat përdor metrikat e marra nga të dhënat historike të projektit
përpara se produkti të prodhohet. Premton mbështetje më të mirë për menaxherët duke ofruar
parshikimin e defekteve.
Parashikimi i bazuar tek klasifikimi parashikon ndryshimet nëse kemi të bëjmë me gabim ose jo.
Sipas këtij parashikimi përcaktohet se sa saktë është parshikuar gabimi dhe sa % duhet t‟i
nënshtrohen një kontrolli të dytë.
Parashikimi i gabimeve në kod vazhdon të jetë ende një fushë e re. Ai nuk mund të qëndrojë
vetëm në kornizat e çështjeve të përmendura më lart. Është një fushë premtuese, e cila ndihmon
në identifikimin e gabimve që në faza të hershme për të përmirësuar cilësinë e software-it dhe
për të përmbushur kërkesat e përdoruesve.
3.2 Cikli i jetës së një gabimi në kod Cikli i jetës së një gabimi në kod është cikli që përshkon një defekt gjatë gjithë ekzistencës
së tij. Ai fillon në momentin që defekti gjendet dhe përfundon në momentin që defekti mbyllet
në mënyrë që të mos përsëritet më. Gabimet në kod kalojnë në gjendje të ndryshme gjatë gjithë
ciklit të jetës së tij. Në figurë paraqitet diagrama e gjendjeve në të cilat kalon gabimi në kod[13]:
Analiza ,implementimi dhe optimizimi gabimeve në kod
19
Figura 4 Cikli i jetës së një gabimi në kod
E re – është gjendja ku defekti regjistrohet dhe njoftohet për ekzistencen e tij për herë të parë.
Caktuar – pasi testuesi ka njoftuar për praninë e gabimit në kod, provohet që gabimi në kod është
i vërtetë dhe i caktohet ekipit përkatës të zhvilluesve.
Hapur – në këtë gjendje zhvilluesi ka filluar analizën dhe punën për të rregulluar defektin.
Rregulluar – pasi zhvilluesi ka bërë ndryshimet e nevojshme në kod dhe i ka verifikuar këto
ndryshime, gjendja e gabimit në kod kalon në gjendjen e rregulluar dhe gabimi në kod i kalon
grupit të testimit.
Në pritje të ritestimit – pasi është rregulluar defekti, zhvilluesi ia jep kodin specifik testuesve për
ritestim. Në këtë gjendje testimi është në pritje të përfundimit të punës së testuesve.
Ritestimi – në këtë gjendje testuesi riteston ndryshimet e bëra në kod në fazën e mëparshme për
të kontrolluar nëse defekti është rregulluar apo jo.
Analiza ,implementimi dhe optimizimi gabimeve në kod
20
Verifikuar – tetsuesi teston sërish gabimin në kod pasi është rregulluar. Nëse ai nuk është më
prezent në software, ai konfirmon se gabimi në kod është rregulluar dhe statusi tashmë kalon në i
verifikuar.
Rihapur – nëse gabimi në kod është ende i pranishëm edhe pasi është rregulluar nga zhvilluesi
kalohet në gjendjen “reopen”, ku gabimi në kod duhet t‟i nënshtrohet dhe njëherë të gjithë
hapava nga fillimi.
Mbyllur – pasi gabimi në kod është rregulluar, testohet nga testuesit. Nëse ai përfundimisht nuk
është i pranishëm në software, kalohet në gjendjen i mbbyllur. Kjo gjendje do të thotë se gabimi
në kod është rregulluar, testuar dhe miratuar.
Dublikuar - është gjendja ku gabimi në kod përsëritet dy herë ose dy gabime të ndryshme në kod
kanë të njëjtin koncept.
Refuzuar – nëse zhvilluesi kupton që gabimi në kod nuk është i vërtetë, ai e refuzon atë.
Shtyr për më vonë – gabimi në kod i vendosur në këtë gjendje do të thotë që pritet të rregullohet
më vonë. Arsyet pse gabimet në kod vendosen në këtë gjendje varen nga shumë faktorë. Disa
faktorë mund të jenë: prioritet i ulët i gabimit në kod, mungesa e kohës për ta rregulluar atë ose
gabimi në kod mund të mos ketë efekt të madh në software.
Jo një gabim në kod - kjo gjendje vendoset në rastet kur nuk ka ndryshime në funksionalitetin e
aplikacionit. Për shembull: nëse klienti kërkon disa ndryshime në pamjen e aplikacionit apo në
fusha të tilla si ndryshimi i ngjyrës ose tekstit, ky nuk është një gabim në kod. Është thjesht një
ndryshim në dukjen e aplikacionit.
3.3 Klasifikimi Shumica e gabimeve në kod ndodhin nga gabimet e bëra nga njerëzit në kodin burim ose
në dizajn dhe pak shkaktohen nga kompilimi që prodhon kod të pasaktë. Një program që ka një
numër të madh gabimesh në kod që ndikojnë seriozisht funksionalitetin e tij thuhet të jetë një
program me problem (buggy). Ekzistojnë raporte që raportojnë në mënyrë të detajuar gabimet në
kod që ka një program. Ato njihen si raportet e gabimeve në kod, raportet e defekteve, raportet e
problemeve etj.
Gabimet në kod shkaktojnë problem që mund të kenë një shumëllojshmëri efektesh me nivele të
ndryshme të shqetesimit për përdoruesin e programit. Disa gabime në kod mund të kenë një efekt
jo shumë të dukshëm në funksionalitetin e programit dhe në këtë mënyrë mund të mos
dedektohen për një kohë të gjatë. Gabimet në kod më serioze mund të shkaktojnë ngrirje të
programit ose shkatërrim. Të tjerë gabime të kualifikuar si gabime në kod të sigurisë mund të
lejojnë përdorues me qëllim të keq të anashkalojnë kontrollet e aksesit me qëllim që të marrin
privilegje të paautorizuara.
Analiza ,implementimi dhe optimizimi gabimeve në kod
21
Në projektet e zhvillimit të software-it, një gabim mund të ndodh në secilën nga fazat e
zhvillimit. Gabimet në kod janë pasojë e faktorit njeri në programim. Ato lindin nga
anashkalimet apo keqkuptimet e bëra nga grupi i software-it gjatë specifikimit, projektimit,
kodimit, futjes së të dhënave apo dokumentimit. Gabimet më komplekse në kod mund të lindin
nga ndërveprime ndërmjet pjesëve të ndryshme të një programi. Kjo shpesh ndodh sepse
programet mund të jenë komplekse, të programuara nga shumë njerëz për një kohë të gjatë.
Një gabim që në momentin e shfaqjes së tij deri në fazën finale pëson transformime.
Metamorfoza e një gabimi paraqitet në hapat e mëposhtëm:
Gabim
Anomali
Dështim
Pasaktësi
Përjashtim
Shkatërrim
Gabime në kod
Defekt
Incident
Efekt anësor
Është e natyrshme që software-ët të kenë gabime në kod që nuk konsiderohen kritik dhe që nuk
ndikojnë tek përdoruesi. Duke qenë se software-ët kanë një numër të panjohur gabimesh në kod,
matjet gjatë testimit mund të ofrojnë një vlerësim të gabimeve në kod duke e bërë më të
besueshëm produktin. Pjesa më e madhe e projekteve të software-it përmban dy lloje të
gabimeve në kod – ato që njihen nga ekipi i software-it dhe ato që duhet t‟i bëhen të ditura
përdoruesit. Lloji i dytë informon përdoruesit për gabimet në kod që nuk janë rregulluar.
Ka shumë arsye pse një gabim në kod nuk mund të rregullohet. Zhvilluesit shpesh nuk kanë
kohën e mjaftueshme apo mundësi ekonomike për të rregulluar të gjithë gabimet jo serioze. Një
tjetër arsye është se gabimet në kod kërkojnë të rregullohen në ndonjë version të ri që ende nuk
është i njohur. Nga ana tjetër ndryshimet në kod mund të jenë të mëdha, të shtrenjta ose mund të
vonojnë përfundimin e projektit. Edhe gabimet në kod që në dukje janë të thjeshtë mund të çojnë
në krijimn e gabimeve të reja në kod të panjohura në sistem.
Gabimet në kod kategorizohen nga pesha që kanë dhe disa kompani tolerojnë gabimet jo kritike
në kod më peshë të ulët sepse ato nuk ndikojnë në funksionimin siç duhet të sistemit.
Pesha e një gabimi në kod nuk është njësoj si rëndësia e rregullimit të tij. Secila prej tyre mund të
matet dhe menaxhohet në mënyrë të veçantë. Ky balanc varet nga shumë faktorë dhe për të patur
një ekuilibër sa më të mirë disa zhvillues software-i përdorin një proces të formalizuar të
përzgjedhjes së gabimit në kod. Në këtë proces secilit gabim në kod i caktohet një prioritet
bazuar në peshën e tij, frekuencën, rrezikun dhe faktorë të tjerë.
Disa nga llojet më të shpeshta të gabimeve në kod janë[10]:
Analiza ,implementimi dhe optimizimi gabimeve në kod
22
Gabimet konceptuale, të cilat janë korrekte nga ana e sintaksës së kodit, por sillen në një
mënyrë tjetër nga ajo që është parashikuar nga projektuesi.
Gabime arithmetike në kod janë gabime që vijnë nga logjika matematike. Të tilla mund të jenë
pjesëtimi me zero, mbiderdhja ose nënderdhja dhe humbja e preçizionit matematik për shkak të
rrumbullakimit.
Gabime logjike në kod përfshijnë problemet që vijnë nga ciklet e pafundëm apo rekursioni i
pafundëm.
Gabime sintaksore në kod janë problemet që lindin nga sintaksa e gjuhës si përdorimi i
operatorëve të gabuar. Shembull është ngatërrimi i barazimit me vlerëdhënien (== dhe =).
Gabime në kod multi-threading sjellin problemet e njohura si deadlock, kushtet e garës ku një
kompjuter nuk performon detyrat sipas rradhës që ka menduar programuesi dhe problemet e
konkurrencës.
Gabimet e ndërfaqes në kod lidhen me përdorimin e gabuar të ndërfaqes. Probleme të tjera janë
dhe implementimi i pasaktë i protokolleve, menaxhim jo i mirë i hardware-it dhe hipoteza të
pasakta lidhur me një platform të caktuar.
Gabimet e performancës në kod kanë të bëjnë me kompleksitetin e lartë llogaritës së
algoritmave apo me akseset në memorje.
Përveç tipit, një tjetër klasifikim i gabimeve në kod bëhet nga pesha që ata kanë në një
aplikacion. Kategoritë kryesore janë:
Bllokues – janë gabimet në kod me prioritetin më të lartë.
Kritike – janë gabime kritike në kod për funksionalitetin bazë të aplikacionit dhe për të
cilat nuk ka rrugëzgjidhje. Këto gabime në kod duhet të rregullohen përpara se
aplikacioni të dalë për publikun. Gabime kiritike në kod janë shumë të rrallë dhe
klasifikohen si të tillë vetëm në rastet kur vonohet nisja e produktit për shkak të tij.
Shembuj të gabimeve në kod kritike mund të jenë: të mos hyjmë dot në një faqe të
caktuar, të mos bësh dot pagesën me kart, të mos marrësh dhe dërgosh dot email etj.
E lartë – gabime në kod që lidhen me funksionalitetin bazë të aplikacionit, por që nuk
duhet të rregullohen me patjetër para se produkti të lançohet. Gjithsesi këto gabime në
kod duhet të rregullohen sa më shpejt të jetë e mundur.
Mesatare – gabime në kod që nuk prekin pjesë kritike të funksionalitetit të aplikacionit.
Gabimet në kod me një peshë mesatare kanë rrugëzgjidhje që i lejojnë përdoruesit të
kryejnë detyrën e duhur.
I ulët – gabime në kod që nuk ndikojnë në funksionalitetin e aplikacionit dhe që mund të
mbeten pa rregulluar.
Analiza ,implementimi dhe optimizimi gabimeve në kod
23
3.4 Gjetja e gabimeve në kod dhe mjetet e gjurmimit Gjetja e gabimeve në kod është një sistem që është i domosdoshëm për çdo sistem që do të
performojë mirë. Është një mjet që lehtëson rregullimin e shpejtë të gabimeve në kod dhe
siguron cilësinë e software-it. Këto sisteme janë të përdorura gjerësisht dhe trajtohen si
thelbësore në gjetjen e statusit të gabimeve në kod dhe në zgjidhjen e shpejtë të tyre duke
garantuar ecurinë e projektit. Potenciali dhe qëndrueshmëria e një sistemi të mirë gjurmimi të
gabimeve në kod ndihmon sistemin për të rritur cilësinë për të përmbushur pritshmëritë e
klientëve. Inxhinierët shpesh përdorin raportet e gabimeve në kod dhe përpiqen t‟i rregullojnë
nëse kërkohet informacion i mjaftueshëm. Raportet e pamjaftueshme ose të papërshtatshme
shkaktojnë vonesa në rregullimin e gabimeve në kod dhe si pasojë shkaktojnë shkeljen e afateve.
Disa nga informasionet që përfshihen në raport janë fotot, rastet e testimit, sjellja që pritet dhe
sjellja e vëzhguar. Në përgjithësi ky është informacioni që nevojitet për rregullimin e një gabimi
në kod. Megjithatë është zbuluar se raportuesit i lënë jashtë këto fusha thelbësore në raportet e
tyre duke i bërë këto raporte të vakët dhe të projektuar dobët. Kur zhvilluesit kanë nevojë për
informacion të detajuar dhe raportet i paraqesin mungesa, kjo çon në zvarritjen e projektit ose në
vonesa në përfundimin e tij. Problem kryesor në sistemet e gjurmimit të gabimeve në kod është
se ata thjesht ruajnë disa fusha të informacionit në bazën e të dhënave, por nuk kanë natyrë
përshkruese. Një raport duhet të jetë specifik, jo i dykuptimtë apo i dyshimtë dhe i detajuar.
Gjithashtu duhet të jetë raport minimal dhe unik.
Sistemet e gjurmimit të gabimeve në kod ndryshojnë shumë nga madhësia, qëllimi dhe metodat.
Nga njëra anë janë sisteme të thjeshta me një qëllim, kurse nga ana tjetër janë sisteme të plota
menaxhimi që kontrollojnë çdo aspekt të procesit të zhvillimit të software-it. Megjithatë qëllimet
kryesore të këtyre sistemeve mbeten konstante. Ato janë:
Para së gjithash, sigurojnë që nuk kemi harruar asnjë gabim në kod
Duke ofruar një standard për raportet e gabimeve në kod, rrisin shanset që të përfshihet i
gjithë informacioni i nevojshëm
Si një gjurmë auditimi, sigurojnë që për çdo lançim të dimë cilat gabime në kod janë të
pazgjidhura, cilat të rregulluara, kush i ka zgjidhur dhe si i ka zgjidhur.
Japin mundësinë për të përcaktuar prioritetet e gabimeve në kod dhe të përcaktojmë se
cili duhet të zgjidhet i pari.
Duke ofruar një mënyrë komunikimi midis aktorëve të ndryshëm, sigurojnë që të gjithë
të kuptojnë gjendjen aktuale të gabimeve në kod dhe që i gjithë informacioni i
rëndësishëm lëviz midis individëve ose ekipeve.
Si mjete të menaxhimit, ofrojnë një pasqyrë të gjendjes aktuale të projektit.
Në raste të rralla që zgjidhet të mos rregullohen gabimet në kod, mund të ruajmë arsyet e
këtij vendimi në mënyrë që të mos përsërisim procesin në të ardhmen.
Megjithatë sistemet e gjurmimit të gabimeve në kod janë të mira nëse është i mirë dhe
informacioni që ata mbartin.
Pothuajse çdo sistem i gjurmimit të gabimeve në kod ka një mjedis të caktur në të cilin vepron.
Nëse punojmë me software desktop, ky mund të përdoret për të regjistruar gabime në kod që
ndodhin në sistemin operativ. Për aplikacionet web, mjedisi është browser-i. Megjithatë kjo nuk
Analiza ,implementimi dhe optimizimi gabimeve në kod
24
është e mjaftueshme. Së pari sepse përdoruesit që nuk e njohin pjesën teknike nuk kanë asnjë ide
për mjedisin e tyre dhe së dyti mjediset kompjuterike janë bërë me të komplikuara dhe më të
ndërlidhura.
3.4.1 Sisteme efektive në gjurmimin e gabimeve në kod
Inxhinierët e software-it shpesh përfshihen në rregullimin e gabimeve në kod gjatë fazës
së zhvillimit. Koha që shpenzohet për këtë mund të reduktohet dhe cilësia e software-it mund të
rritet duke përdorur një sistem efektiv të gjurmimit të gabimeve në kod. Informacioni fillestar
mund të ndihmojë në zgjidhjen e shpejt të gabimeve në kod duke kursyer kohë dhe kosto. Gjatë
një periudhë kohë, zhvilluesit mund të reduktojnë shumë harxhimin e kohës me një sistem të
sofistikuar të gjurmimit të gabimeve në kod. Në figurën më poshtë paraqitet një strukturë
konceptuale, që ofron drejtime që mund të përmirësojnë këto sisteme[35].
Figura 5 Drejtimet për të përmirësuar sistemet e gjurmimit të gabimeve në kod
Orientuar nga mjetet – rekomandohet që sistemet e gjurmimit të gabimeve në kod të jenë të
orientuara nga mjetet. Kjo nuk do të thotë që këto sisteme do të konfigurohen për të mbledhur
gjurmë që do të vendosen në raportet që përmbajnë detajet e gabimeve në kod. Duke vepruar
kështu mund të përmirësojë aftësitë e mbledhjes së informacionit. Orientimi nga mjetet mund të
përmirësojë aftësinë e sistemeve të gjurmimit të gabimeve në kod në mbledhjen e informacionit
që është shumë e rëndësishme dhe mund të përdoret lehtësisht në rregullimin e gabimeve në kod
në sistem. Kjo do të çojë në gjurmimin efektiv dhe rezultatet në cilësinë e software-it përveç
faktit të të qenit produktiv.
Orientuar nga informacioni – ky është një drejtim që ndihmon zhvilluesit e software-it të
përmirësojnë mbledhjen e informacionit që do të shkruhet te raportet. Për këtë qëllim disa lloje
mjetesh duhet të përfshihen në sistemet e gjurmimit. Këto mjete verifikojnë informacionin e
ofruar në raportet e gabimeve në kod dhe ofrojnë reagimet që ndihmon në përmirësimin e
cilësisë së informacionit. Kjo ndihmon edhe inxhinierët të jenë të motivuar dhe më të
përqëndruar në zgjidhjen e gabimeve në kod. Orientimi nga informacioni me mbështetjen e
mjeteve të caktuara rrit mundësitë për të kontrolluar nëse raportet e gjurmëve janë të plota dhe
konsistente.
Analiza ,implementimi dhe optimizimi gabimeve në kod
25
Orientuar nga procesi – procesi në një sistem gjurmimi mund të përmirësohet në këtë drejtim.
Kjo do të thotë që të gjitha aktivitetet administrative lidhur me gjurmimin dhe rregullimin e
gabimeve në kod vendosen nën funksionin e orientuar nga procesi. Këto sisteme fokusohen
gjithashtu edhe tek zhvilluesi që është përgjegjës për rregullimin e gabimeve në kod. Avantazh i
këtyre sistemeve është se zhvilluesit kanë vetëdije më të plotë lidhur me raportet e gabimeve në
kod. Në këtë mënyrë ata janë më të vetëdijshëm për veprimet që do të ndërmeren. Gjithashtu i
ndihmon ata të vlerësojne kohën e shpenzuar në një gabim kodi specifik dhe të planifikojnë
kohën në përputhje me rrethanat.
Orientuar nga përdoruesi – përdorues do të thotë zhvilluesit dhe raportuesit e gabimeve në kod.
Ky drejtim fokusohet në edukimin e raportuesve në mënyrë që t‟ju mundësojë atyre të mbledhin
informacionin në mënyrë korrekte dhe se si ta mbledhin atë. Ndihmon si raportuesit, ashtu edhe
zhvilluesit. Informacioni i duhur në një raport e bën zhvilluesin ta kuptojë më shpejtë dhe të
veprojë më shpejt për rregullimin e gabimeve në kod. Ky drejtim ndikon në përshtatjen e mjeteve
të reja në proces, duke e bërë atë më të fuqishëm dhe produktiv.
3.5 Modelet e parashikimit të gabimeve në kod Modelet e parashikimit të gabimeve në kod janë modele që krijohen paraprakisht për të
identifikuar pjesët e prirura për të pasur gabime. Si fillim duhet të identifikohen komponentet e
sistemit që janë më kritike në lidhje me defektet. Modelet kombinojnë metodat dhe teknikat e të
dhënave, të statistikave dhe algoritmave të makinave. Në figurën e mëposhtme paraqiten në
mënyrë skematike disa modele të parashikimit të gabimeve në kod bazuar tek metrikat.
Figura 6 Parashikimi i gabimeve në kod
Analiza ,implementimi dhe optimizimi gabimeve në kod
26
3.5.1 Metrikat e bazuar tek ndryshimet
Janë matës të procesit. Ato reflektojnë aktivitetet e zhvillimit. Modulet me shumë defekte në të
kaluarën kanë shumë mundësi të jenë difektoz në të ardhmen. Gjithashtu modulet të cilët
ndryshojnë shpesh kanë shanse më të larta për të qenë të ndikuar nga defektet. Metrikat e
bazuara tek ndryshimet e bëra në kod bazohen në tre teknika:
1. Gabimet e mëparshme në kod
Angazhohet në sistemet e kontrollit. Është matje në nivel skedari. Pra, janë skedarët ato që
ndryshojnë. Quhet ndryshe strukturë e ashpër.
2. Code churn
Code churn mat ndryshimet e bëra në kodin bazë për një periudhë kohe dhe është një mënyrë për
të përcaktuar sasinë e këtyre ndryshimeve. Ai është i rëndësishëm për skuadrën e zhvilluesve të
software-it sepse mund të përdoret për të parashikuar densitetin e defekteve. Problemi me
metrikat është se ato mund të shkaktohen nga shumë gjëra. Ka dy lloje matjesh: matjet absolute
dhe matjet relative. Në tabelën e mëposhtme jepet një përshkrim i shkurtër i tyre[18]. Tabela 2 Matjet absolute dhe relative duke përdorur Code Churn
3. Strukturë delikate e ndryshimit të kodit (SCC)
Code Churn e shpjeguar më lartë është një matje që nuk mund të kap dot ndryshimet semantike
të bëra në kod, por vetëm rrjeshtat e modifikuar. Për të rregulluar këtë mangësi përdoret SCC, e
cila mat ndryshimet semantike.
Parashikimi i gabimeve në kod në nivel metode
Analiza ,implementimi dhe optimizimi gabimeve në kod
27
Parashikimi në një strukturë delikate, i cili përfaqëson nivelin e metodës kërkohet sepse mund të
paraqesë rezultate interesante krahasuar me parashikimin me strukturën e ashpër (nivel skederi
dhe pakete). Këto rezultate përfshijnë perfomancën dhe gjetje të reja midis korrelacionit të
gabimeve në kod me historikun.
3.5.2 Metrikat e kodit
Metrikat e kodit janë një set matjesh në software që i ofrojnë zhvilluesve informacione
më të mira lidhur me kodin që ata po zhvillojnë. Duke përfituar nga avantazhet e metrikave të
kodit, ata mund të kuptojnë se cilat lloje ose metoda duhet të ripunohen ose testohen më në
thellësi. Mund të identifikojnë rreziqet e mundshme, të kuptojnë gjendjen aktuale të projektit dhe
të ndjekin procesin gjatë zhvillimit të software-it.
Këto metrika llogariten direkt në kod dhe variojnë nga përmasat dhe kompleksiteti. Sa më të
mëdhenj dhe kompleks të jenë modulet, aq më e vështirë është t‟i kuptosh dhe t‟i ndryshosh. Ato
vlerësojnë numrin e gabimeve të ndodhura në kod duke bërë dy lloje analizash: analiza statike
dhe analiza dinamike. Gjithashtu llogarit dështimet në të ardhmen.
Analiza statike:
Halstead’s software physics
n1 = nr. i operatorëve të dukshëm në program
n2 = nr. i operandeve të dukshëm në program
N1 = nr. total i operatorëve
N2 = nr. total i operandëve
Gjatësia e programit: N = N1 + N2
Vëllimi i programit: V = N log2 (n1 + n2), përfaqëson volumin e informacionit (në bit).
Niveli i abstraksionit: L = (2 * n2) / (n1 * N2)
Përpjekja e programit: E = (n1 +N2 * (N1 + N2) * log2 (n1 + n2)) / (2 * n2)
McCabe’s Cyclomatic Complexity
Vështirësia e të kuptuarit një program përcaktohet nga kompleksiteti i grafit (Control Flow
Graph). Numri cyclomatic V i një grafi të lidhur G është numri i rrugëve të pavarura lineare në
graf ose numri i rajoneve në një graf të sheshtë. McCabe rekomandon që maksimimumi i V(G) të
jetë 10[17].
Analiza statike ka disa probleme:
Nuk ndryshon me ndryshimin e programit
Analiza ,implementimi dhe optimizimi gabimeve në kod
28
Korrelacion të lartë me përmasat e programit
Nuk ka arsye intuitive për shumë metrika
Injoron shumë faktorë: p.sh. mjedisin e llogaritjeve, zonën e aplikacionit, algoritmat e
implementuar, karakteristikat e përdoruesve, aftësinë e prgramuesve.
Prgramuesit mund të prezantojnë më shumë kompleksitet të panjohur në mënyrë që të
minimizojnë karakteristikat e matura nga metrika te veçanta.
Analiza dinamike:
Vlerëson numrin e gabimeve të kodit që kanë mbetur me ato të gjetura. Janë dy modele: modeli i
numërimit të dështimeve dhe modeli i numërimit të gabimeve. Të vlerësosh gabimet e mbetura
në kod ka kuptimin e performancës së programit, jo të numrit të gabimeve në kod që përmban.
Normat e dështimit:
Janë modele input-domain. Vlerëson besueshmërinë e programit nëpërmjet rasteve të testimit.
Ndahet domaini i të dhënave në klasa ekuivalente. Secila klasë shoqërohet me një rrugë të
programit. Llogarisin probabilitetin e kushtëzuar për të gjitha hyrjet e mundshme duke patur
parasysh që është i saktë për një set specifik të të dhënave.
Besueshmëria e software-it: ka të bëjë me portabilitetin e një programi, i cili mund të performojë
funksionet e tij specifik për një gjendje të caktuar në kushte të caktuara. Ekzekutimi i
programeve derisa të ndodh një dështim, gjetja e gabimit, heqja e tij dhe vazhdimi i ekzekutimit.
Përdor një funksion probabilitar të shpërndarë për të parashikuar dështimet në të ardhmen.
Problemet me modelet e besueshmërisë së software-it:
Nuk ka një realitet fizik ku të bazohen hipotezat
Hipotezat nuk janë gjithmonë të vlefshme për të gjithë dhe për çdo lloj programi
Kërkesat e mbledhjes së të dhënave mund të jenë jo praktike
Metrikat e kërkesave të software-it:
Fuqi e kufizuar parashikuese
Pikat e funksionit
1. Numërimi i hyrjeve dhe daljeve, skedarët e përdorur, ndërfaqet e jashtme.
2. Vlerësimi i secilit për kompleksitetin dhe shumimin nëpërmjet një faktori
ponderimi
3. Përdoret për të parashikuar përmasat ose koston dhe për të vlerësuar
produktivitetin e projektit.
Numrin e gabimeve të gjetura (vlerësimi i cilësisë)
Ndryshimi i frekuencës së kërkuar
1. Vlerëson qëndrueshmërinë e kërkesave
2. Frekuenca duhet të zvogëlohet me kohën
Dallojmë dy grupime të mëdha të metrikave të kodit:
Analiza ,implementimi dhe optimizimi gabimeve në kod
29
1) Metrikat e orientuara nga objekti
Qëllimi i përdorimit të metrikave të orientuara nga objekti është të vlerësojë sistemin në mënyrë
që të prodhojë rezultate të cilësisë së lartë. Vlefshmëria e këtyre metrikave kërkon bindshëm të
demostrojë që metrikat janë matur ashtu siç duhet dhe se ato janë të lidhura me një metrik të
jashtme si besueshmëria, mirëmbajtja dhe ekzpozimi ndaj dështimeve.
Metrikat bazë që llogariten janë:
Çiftimi
Kohezioni
Enkapsulimi
Trashëgimnia
Kompleksiteti
Përveç këtyre ka dhe matje shtesë:
Numri i klasave
Numri i rreshtave të kodit
2) Metrikat në nivel funksioni
Llogariten tre tipe të metrikave të nivelit të funksioneve: metrikat përjashtuese, metrikat
përfshirëse dhe metrikat e atributeve. Metrikat përjashtuese llogariten nga ngjarjet që ndodhin në
brendësi të funksionit. Ato përjashtojnë metrikat që vijnë nga thirrjet e funksioneve të tjera.
Metrikat përfshirëse llogariten nga ngjarjet që ndodhin brenda funksionit dhe çdo funksioni që ai
thërret. Ato përfshijnë metrikat që vijnë nga thirrjet e funksioneve të tjera. Metrikat e atributeve
tregojnë se sa metrika përfshirëse vijnë nga thirrjet e funksioneve të tjera ose nga funksionet e
tjera.
Për një funksion që paraqitet në fund të stivës, metrikat përjashtuese dhe përfshirëse janë njësoj.
Këto metrika përdoren edhe për objektet e ngarkesës. Metrikat përjshtuese llogariten si shumë e
metrikave në nivel funksioni, kurse metrikat përfshirëse llogariten njësoj si për funksionet.
Metrikat përjashtuese dhe përfshirëse për një funksion japin informacion për të gjitha rrugët e
regjistruara gjatë funksionit. Metrikat e atributeve japin informacione për rrugë të veçanta. Ato
tregojnë se sa metrika vijnë nga një funksion i veçantë. Dy funksionet e përfshira në një thirrje
janë thirrësi dhe i thirruri.
Lidhja midis këtyre metrikave shprehet me ekuacionin e mëposhtëm:
Analiza ,implementimi dhe optimizimi gabimeve në kod
30
3.5.3 Metrikat e organizimit
Struktura e organizimit dhe rregullat ndikojnë në kualitetin e software-it. Janë metrika që
kanë të bëjnë me performancën. Edhe këto metrika ndahen në dy grupime kryesore:
Struktura e skuadrës
Struktura e skuadrës është një strukturë e re organizative, më pak hierarkike, ku individët
grupohen në skuadra. Skuadra formohet nga njerëz me aftësi plotësuese dhe përpjekje
bashkëpunuese që punojnë për një qëllim të përbashkët. Në një organizim të gjerë mund të jenë
shumë skuadra. Skuadrat ndryshojnë me kohën dhe mund të përfshijnë anëtarë me funksione të
ndryshme. Edhe pse konsiderohen si jo shumë hierarkike, ato përsëri kanë një strukturë
menaxhimi. Avantazhet e kësaj strukture janë:
Kërkon më pak menaxhim
Përmirëson marrëdhëniet
Rrit produktivitetin
Balancimi
Figura 7 Struktura e skuadrës
Struktura e kontributit
Është një strukturë që tregon se si ndikon ndryshimi i një skedari dhe se si ky ndryshim
shpërndahet tek zhvilluesit. Bazuar në koeficientin e Ginit ajo llogarit pabarazinë. Kurba e
Lorenz është një metod grafike që shpreh pabarazinë. Në figurën e mëposhtme tregohet grafiku i
kurbës së Lorenz në kushtet e parashikimit të gabimeve në kod, ku në boshtin e x-eve vendosen
zhvilluesit dhe në boshtin e y-eve burimet. Vija diagonale në grafik shpreh barazinë ideale, ku të
gjjithë kanë të njëjtin akses tek burimet. Devijimi nga diagonalja tregon pa barazinë, ku një
individ zotëron gjithçka[23].
Analiza ,implementimi dhe optimizimi gabimeve në kod
31
Figura 8 Grafiku i kurbës së Lorenz
Analiza ,implementimi dhe optimizimi gabimeve në kod
32
4 Mjetet e përdorura
4.1 SOTA SOTA është shpikur nga Ronney Treybe si pjesë e tezës së diplomës së tij. Është një mjet
për analizën e programeve statike dhe testimin e programeve të orientuar nga struktura (Structure
Oriented Test and Analysis).
Analiza statike e komponenteve të programit siguron disa metrika software-ike si kompleksiteti
thelbësor apo çiklomatik si graf për kontrollin e rrjedhës së çdo metode (për analizën grafike të
testcase-ve të ekzekutuara. Për më shumë ofron disa matës të mbulimit të kodit si C0, C1, C2,
C3, MMCC and MCDC. Kodi vizualizohet në termat e CFG (Control Flow Graph). CFG
gjenerohet pa nevojën e kompilimit dhe ekzekutimin e software-it nën testim .
Për më shumë për analizën e kodeve statike SOTA, siguron metrikat e kompleksitetin
ciklomatik, rrjeshtat e kodit, kompleksitetin esencial, degët.
Figura 9 Paraqitja grafike e SOTA
Detyrat e SOTA-ës:
Bën llogaritjen e metrikave të ndryshme statike
Kontrollon mbulimin të kodit burim në testim për një set të dhënë test case-esh
Përgatit informacionin vizualisht
Informacion i fituar lejon një vlerësim të cilësisë së testimit të programit. Programi kontrollon
seksionet e kodit të mbuluar ose jo (d.m.th nuk jane testuar sa duhet kushtet ), për një set të
dhënë testcase-esh. Pra, SOTA nuk është drejtpërdrejt përgjegjës për testim, ajo është një ndihmë
për të vlerësuar zhvillimin e testcase-eve shtese. [7].
Analiza ,implementimi dhe optimizimi gabimeve në kod
33
4.1.1 Si punon SOTA
SOTA përcakton mbulimin nga instrumentimi i kodit burim. Instrumentimi është
pasurimi i kodit original npm shtimit të shprehjevë, thyerjene e kushteve, transformimin e
cikleve.
SOTA suporton :
Analizen statike të programeve
Analizen dinamike të programeve
Në analizën statike kodi burim i programit është analizuar dhe rezultatet përcaktohen përmes
dhjetë mateseve sic paraqiten në figurë.
Figura 10 Matësit e analizës statike
Analiza dinamike varet nga një testcase-et specifice. Për të realizuar këtë gjë SOTA ka
përcaktuar nëntë kritere mbulimi gjatë ekzekutimit të programi të paraqitur më poshtë.
4.1.2 Tipet e përdorimit
Ka tre tipe versionesh se si SOTA mund të përdoret për testim:
Testimi manual
Figura 11 Matësit e analizës dinamike
Analiza ,implementimi dhe optimizimi gabimeve në kod
34
Së bashku me një sistem testimi të jashtëm
E integruar në një system testimi automatik
Testimi manual
Realizohet me një IDE sic është eklipsi, e përdorur shtesë për SOTA-ën, me të dhëna
testuese të future nëpërmjet cmd
Me testcaset të vendosura në një program JAVA dhe të testuara me eklipsin si JUnit test
Me SOTA-ën nën përdorimin të një Ant build files dhe një skripti startues
Testimi external
Punon më një system testimi të jashtëm që është i ngjashëm me testimin manual
I vetmi ndryshim është metoda e testimit
SOTA bën të njëjtën gjë si tek testimi manual, por për testimin e programit në vetvete
përdoret një sistem testimi i ndarë (psh ATOSj)
Testimi automatik
Me një system testimi automatik, SOTA mund të bashkohet si library (SOTA ATM) në
sistem
Në këtë rast asnjë funksionalitet GUI nuk është përdorur nga SOTA
Funksionet kernel të SOTA-ës thirren ose mbi parmetrat e cmd, ose si një instance e
ATM së SOTA-ës , klasa e së cilës thirret nga libraria.
4.1.3 Puna me SOTA
Të punosh me SOTA-ën konsiton në tre hapa:
Përgatitja
Ka te bëjë me leximin e kodit dhe përcaktimit të llojit të instrumentimit për të. Në
testimin manual kjo realizohet nëpërmjet SOTAGUI
Testimi
Në fazën e testimit, kompilimit ndodh testimi i programit. Kompilimi nuk është
përgjegjësi e SOTA-ës. Shpesh kompilimi iniciohet nga SOTA nëpërmjet integrimit të
ANT build script. Nëse një batch file është prezent programi gjithashtu mund të filloj
nga SOTA.
Vlerësimi i fazave
Në fazën e vlerësimit kodi burim ngarkohet, logfile-at janë lexuar dhe matje të ndryshme
janë llogaritur. Rezultatet janë më pas të disponueshme për vlerësim, ose më mirë të
eksportuara në një raport HTML.
Instalimi i SOTA-s.
Ështe njëaplikacion standalone Eclipse RPC. Pranon instalime Java (nga 1.6). Instalohet
nga ç‟paketimi një file zip-i.
Analiza ,implementimi dhe optimizimi gabimeve në kod
35
Më poshtë paraqitet nje pamje vizuale e SOTA-ës pas instalimit . Në pjesën e sipërmë majtas lart
ka një pamje të projektit, kurse majtas poshtë testcase-et e programit që janë realizuar.
Figura 13 Ndërfaqja e SOTA-ës
Figura 12 Zip file-i i SOTA
Analiza ,implementimi dhe optimizimi gabimeve në kod
36
4.2 CCCC Mjet C dhe C ++ Code Counter ( CCC ) siguron funksionalitet për të llogaritur disa
metrika Software për C , C ++ dhe fila-a të Java-ës .
Ai mbështet metrikat si rreshta të kodit,kompleksiteti McCabe dhe metrika të orientuara nga
objekt të propozuara nga Chidamper dhe Kemerer. Për më tepër ajo krijon një raport në formën
e një faqe interneti HTML cila është e vendosur gjithmonë në nëndirektorine .cccc, me
directorinë e ekzekutimit të cccc .
Matjet e kodit burim të këtij lloji janë përgjithësisht të referuara si " metrika software " , ose më
saktë ' produkte metrikash software ' (termi' software metrics` mbulon edhe matjet e procesit të
programeve, të cilat janë quajtur „proces software metrics‟) . Ekziston një konsensus i arsyeshëm
në mesin e liderëve të opinionit modern në fushën e inxhinierisë software, që matja e disa lloj
është ndoshta një gjë e mirë, edhe pse ka më pak konsensus në atë që është me vlerë në matje
dhe çfarë matjet thotë .
CCCC është zhvilluar si program opensource, dhe është lëshuar në formë të kodit burim.
Përdoruesit janë të inkurajuar që të kompilojnë programin në vetvete, dhe për të modifikuar
burimin për të pasqyruar preferencat dhe interesat e tyre .
Mënyra më e thjeshtë e përdorimit cccc është vetëm për të ekzekutuar atë me emrat e një
përzgjedhje të file-ave në cmd si kjo :
cccc my_types.h big.h small.h *.cc
Nga ana tjetër,për një hierarki komplekse, përdoruesi mund të hyjë në një komandë si kjo:
dir /b/s | cccc - (në platformat e DOS/Windows)
Pika fillestare e raportit është skedari cccc.html.Cccc është një mjet i lirë që mund të përdoren
për të matur kompleksitetin cyclomatic të një kodin bazë.
1) Pasi të kemi shkarkuar atë nga sourceforge dhe e instalojmë atë shfaqet menuja e
zhvillimit.
Figura 14 Menuaja pas instalimit të CCCC
Analiza ,implementimi dhe optimizimi gabimeve në kod
37
2) Ne klikojmë tek command line dhe shfaqet dritarja e mëposhtme.
Figura 15 Dritarja e instalimit të CCCC nëpermjet cmd
3) Në dritaren cccc, shkruajmë cccc C: \ Source1.cpp
Figura 16 Treguesi që dritarja është e gatshme për përdorim
4.2.1 Metrikat e shfaqura
Tabela 3 Metrikat e CCCC më të pëdorura
Tag-u Emri i metrikës Përshkrimi
LOC
Rrjeshta kodi
Kjo metrikë numëron numrin e rrjeshtave jo bosh
,sorce kodet pa koment në një funksion(LOCf).
LOC ishte një nga metrikat më të hershme që do të
vijnë në përdorim ( kryesisht për shkak se ajo është e
drejtpërdrejtë për tu matur ) .
Ajo ka një lidhje të qartë me madhësinë apo
kompleksitetit të një pjesë të kodit dhe
produktivitetit mund të kalibrohet për përdorim në
parashikimin e përpjekjeve të mirëmbajtjes,
Analiza ,implementimi dhe optimizimi gabimeve në kod
38
megjithëse shqetësim është shprehur se përdorimi i
kësaj metrike si një masë e programues mund të
priren për të inkurajuar praktikat e programimit
fjalëshumë dhe dekurajojnë thjeshtësimin e
dëshirueshme.
MVG
McCabe's Cyclomatic
Complexity
Një masë e një trupi të kodit në bazë të analizave të
kompleksitetit cyclomatic të grafikut aciklik drejtuar
cili përfaqëson rrjedhën e kontrollit brenda secilit
funksion . Propozuar së pari si një masë e numrit
minimal të rasteve të testit të siguruar të gjitha pjesët
e secilit funksion ushtrohen .Ajo tani është e pranuar
gjerësisht si një masë për zbulimin e kodit e cila ka të
ngjarë të jenë e prirur për gabime / ose e vështirë për
të mbajtur .
COM
Rreshta
Komenti(coment
lines)
Një masë e papërpunuar e krahasueshme me LOC të
shtrirjes së komentimit brenda një rajoni të kodit . Jo
shumë kuptimplotë në izolim, por nganjëherë
përdoren në raport me LOC ose MVG për të siguruar
se komentet janë të shpërndarë në mënyrë
proporcionale në sasi të mëdha ose kompleksitetit të
një rajoni të kodit .
4.2.2 Metodat e numërimit
Cccc zbaton algoritme të thjeshta për të llogaritur secilën nga masat e paraqitura.
Algoritme janë të destinuara për të paraqitur një përafrim të dobishme të sasive themelore, në
vend të numërimit të saktë , në marrëveshje të përgjithshme me akuza të bazuara tek manuali në
të njëjtat përkufizime duhet të bien dakord me cccc për brenda 2-3 %. Nëse mospërputhje të
mëdha janë zbuluar, ose në qoftë se ky nivel i marrëveshjes nuk është konsideruar i
përshtatshëm, përdoruesit janë të mirëpritur për të modifikuar kodin burim për të zbatuar
marrëveshjen më të ngushtë,apo për të ndryshuar sjelljen e numërimit për të pasqyruar një bazë
të dëshiruar të llogaritjes. Përkufizimet themelore të çdo akuzë janë si më poshtë :
Numri i Moduleve ( NOM )
Cccc përcakton module në drejtim të një grupim të funksioneve anëtare : klasa dhe
hapësira C ++ , klasa Java dhe ndërfaqe, paketa Ada të gjitha të përcaktuara si module.
Përveç kësaj, funksionet të cilat nuk janë anëtarë të një prej këtyre strukturave janë
trajtuar si pjesëtarë të një moduli anonim që konsiderohet nëse ajo ka funksione anëtare
Rreshtat e Kodit ( LOC )
Kjo numërim ndjek standarti i numërimit jo- bosh ,rreshtat e jo komente të kodit burim .
Ndarjet midis rreshtave trajtohen si bosh . Deklarimet e klasave dhe funksioneve janë të
numëruara, por deklarata e të dhënave globale injorohen. Nuk mund të ketë disa
numërimi i dyfishtë i rreshtave në përkufizimet klasës sic algoritmi trajton totalin mbi
një modul, si shuma e rreshtave që i përkasin modulit vetë dhe linjat që i përkasin
funksioneve të tij anëtare ( deklaratat dhe përkufizimet e funksioneve anëtare në trupin e
përkufizimit të klasës do të kontribuojë në të dy numërimet ) .
Analiza ,implementimi dhe optimizimi gabimeve në kod
39
Komentet e rreshtave( COM )
Çdo rresht i cili përmban çdo pjesë të një komenti për gjuhën në fjalë është trajtuar si një
komenti nga cccc , dhe është i alokuar tek moduli. Kjo siguron që komentet kryesore
janë trajtuar si pjesë e funksionit apo klasës, përkufizimin që i ndjek ata .Eshtë një
përjashtim nga ky rregull :Rational Rose mjet dizajn është i njohur për të futur direktivat
në file-at burim të maskuara si komentet e C ++ me prefiksin ' // ## ' . Këto nuk
numërohen si komentet, megjithatë të gjitha strukturat e tjera komente janë, edhe nëse
nuk ka përmbajtje brenda komenteve përndarëse , apo përmbajtja është komentuar nga
kodi burim .
Kompleksiteti Ciklomatik McCabe ( MVG )
Përkufizimi formal i kompleksitetit ciklomatik është se ai është numri i shtigjeve
linearisht të pavarur përmes një rrjedhë të grafikut të kontrollit që rrjedhin nga një nën-
program . Një përafrim pragmatik për këtë mund të gjendet duke numëruar fjalë kyçe të
gjuhës dhe operatorët që do të vendoste rezultatet dhe vendimet shtesë. Kjo mund të
tregohet të jetë mjaft i saktë në shumicën e rasteve . Në rastin e C ++ , numërimi është
rritet për secilin nga argumentet e mëposhtme: 'if','while','for','switch','break','&&','||'
Analiza ,implementimi dhe optimizimi gabimeve në kod
40
5 Analiza Dinamike
5.1 Objektivi dhe motivimi. Testimi Software është një aktivitet thelbësor për të kontrolluar dhe provuar
korrektësinë e sjelljes e softuerit sipas specifikimit të tij. Megjithatë, testimi i çdo gjëndje të
mundshme të sistemit software mund të jetë shumë e shtrenjtë, ose edhe e pamundur .
Kështu testimi Software është vlerësuar për të marrë rreth 50 % të kohës dhe kostove të procesit
të zhvillimit të software-it.
Inxhinierët e testimit janë përballur me problemin për të gjetur një setin e të gjitha rasteve të
mundshme të testit e cila ka një probabilitet të lartë për zbuluar gabimet [20]. Një mënyrë për të
adresuar këtë problem është të përdoret testimi i strukturuar (p.sh duke përdorur Sota).
5.2 Software-i nën testim. Rast studimor. Software-i që kam zgjedhur për të testuar është i vogël rreth 60 LOC(rrjeshta kodi), i cili
është përgjegjës për marrjen e datës nga një string i dhënë dhe krijimin e objektit të duhur të
datës. Për 6 nga kriteret e para do të mundohem të gjej setin më të vogël të testcase-ve që e rrit
mbulimin e kodit deri ne 100%.Në këtë mënyrë për kodin e marrë në shqyrtim kam ndërtuar
klasën specifike në java qe implementon setin e duhur të testcase-ve, e cila thërret metodën
kryesore të klasës main të programit në Java. Kurse për tre parametrat e fundit duke plotësuar
kështu nëntë kriteret e specifikuara tregoj arsyen pse mbulimi për të tre nuk arrihet 100% .
5.2.1 Implementimi i rastit studimor.
Kjo matje mbulimi arrin 100% kur të gjitha inputet e mundshme të funksioneve dhe
vlerat e kthimit janë testuar (p.sh të gjithe parametrat e funksioneve janë kaluar, dhe të gjitha
vlerat e mundshme të kthimit janë thirrur të paktën njëherë të vetme).
Kështuqë, për të testuar metodën Date.toString() na nevojitet vetëm një rast testimi për të
mbuluar 100% testin e FEEC: pra një datë e vlefshme për tu bërë print.
System.out.println(DateParser.parseDate("2014.11.15"));
Po në të njëjtën mënyrë ne mund të testojmë metodën DateParser.parseDate(), sapo inputi i
vlefshëm (për të bërë return new Date()) dhe njëherë me input të vlefshëm (për të bërë return
null;). Rasti i parë testues është aktualisht i mbuluar nga testi i parë i përmendur mësipër, ndërsa
për rastin tjetër testues mëposhtë jepet forma e vlefshme:
System.out.println(DateParser.parseDate("1ab"));
Kështu që si përfundim, ne mund të mbulojmë testin FEEC me metodën e mëposhtme e cila
përmban vetëm dy raste testuese:
private static void functionIOCoverage_feec(){
System.out.println(DateParser.parseDate("2014.11.15
System.out.println(DateParser.parseDate("1ab"));}
Analiza ,implementimi dhe optimizimi gabimeve në kod
41
Emri i file-it të logeve SOTA: functionIOCoverage_feec.log
Rezultati i analizës SOTA:
5.2.1.1 Testi mbulimit deklarativ – Testi C0
Duke parë mbulimin e kodit të kryer nga testi FEEC mund të shohim se ekzistojnë vetëm
pak rreshta të cilët nuk janë mbuluar, kështuqë metoda e mëposhtme përcakton 5 raste të tjera
testuese të cilat duke zgjeruar 2 testet e mëparshme mund të mbulojnë testin C0 në nivel 100%:
private static void statementCoverageTest_C0(){
System.out.println(DateParser.parseDate("199.11.15"));
System.out.println(DateParser.parseDate("20.11.15"));
System.out.println(DateParser.parseDate("2.5.1"));
System.out.println(DateParser.parseDate("2013.00.11"));
System.out.println(DateParser.parseDate(".01.11"));
}
Kështuqë 3 rastet e para testuese në këtë metodë shërbejnë për të mbuluar rrjeshtat deklarativ në
metodën Date.toString(), të cilët nuk ishin mbuluar nga rasti i rregullt testues i mëparshëm që
konsistonte në dhënien si input të datës (testi FEEC mësipër).
else if (year < 1000) {
result += "0" + year; } // eshte mbuluar nga ("199.11.15") input
else if (year < 100) {
result += "00" + year;
} // eshte mbuluar nga ("20.11.15") input
if (year < 10) {
result += "000" + year;
} And
if (month < 10) {
result += ".0" + month;
}
Figura 17 Paraqitja grafike pas ekzekurimit të testit FECC
Analiza ,implementimi dhe optimizimi gabimeve në kod
42
And
if (day < 10) {
result += ".0" + day;
} // jane mbuluar nga ("2.5.1") input
Rastet e tjera testuese sherbejne per te mbuluar rrjeshtat ne vijim:
if(month < 1 | month > 12) {
errorFree = false;
} // is covered by ("2013.00.11")
if(year < 0 | index == 1) {
errorFree = false;
} // eshte mbuluar nga (".01.11") sepse index==1 me ate input
Pra, ne kemi zgjeruar rastet testuese të FEEC me këtë set testesh shtesë (5 teste) dhe më në fund
kemi arritur që ta çojmë testin C0 në nivelin e mbulimit 100%, gjë që dëshmon se të gjitha
deklaratat janë ekzekutuar të paktën njëherë.
Emri i skedarit te logeve SOTA: statementCoverageTest_C0.log
Rezultati i analizes SOTA:
5.2.1.2 Testi mbulimit të degëve – Testi C1
Ashtu siç kemi parë nga figura e mësipërme (statementCoverageTest) testi C1 është
mbuluar 100%. Kjo ndodh ngaqë struktura e programit testues është e thjeshtë dhe në mënyrë që
të arrihet çdo deklaratë (testi C0) ne kemi për të pasuar të paktën njëherë përmes të gjitha
degëve.
5.2.1.3 Testi i mbulimit të kushtëzimit të thjeshtë – Testi C2
Duke parë diagramen CFG, ne mund te nxjerrim ne pah kushtezimet atomike te cilat nuk
kane mbulim 100%:
-dita>31 –ishte përherë e vërtetë, kështuqë duhet ta vlerësojme si të pasaktë : “2013.05.32”
-muaji>12 –ska qenë asnjëherë e vërtetë, pra duhet ta vlerësojmë testin e saktë: “2013.14.11”
-Si përfundim , neve na duhet një test që të vlerësojmë viti<0 si të saktë, gjë që duket e
pamundur, duke qenë se viti fillon viti=0 dhe programi nuk e njeh “-” si shenjë.
Por pastaj e kuptojmë që kur testojmë vitin me një vlerë të madhe, në mënyrë që shumëzimi i
vit = vit * 10 + Integer.parseInt(chr); do të gjeneronte mbiderdhje dhe viti mund të merrte disa
vlera negative. Kështuqë si përfundim, si zgjerim i rasteve testuese të mëparshme, kemi shtuar
metodën e mëposhtme me 3 raste testuese:
private static void simpleConditionCoverage_c2(){
System.out.println(DateParser.parseDate("2013.05.32"));
System.out.println(DateParser.parseDate("9999999999999999999999.10.32"));
System.out.println(DateParser.parseDate("2013.14.11")); // month>12
Analiza ,implementimi dhe optimizimi gabimeve në kod
43
}
Emri i skedarit te logeve SOTA: simpleConditionCoverage_c2.log
Rezultati i analizës SOTA:
5.2.1.4 Testi i mbulimit të kushteve minimale të shumëfishta – Testi MMDC
Siç e shohim nga figura e mësipërme (simpleConditionCoverage_c2) testi MMDC është
mbuluar tashmë 100%. Kjo ndodh ngaqë në testin C2 ne mbuluam kushte atomike, në mënyrë që
kushtet komplekse të cilat duhet të mbulohen në MMCC të cilat janë vlerësuar aktualisht të
paktën njëherë si të sakta ose të pasakta.
5.2.1.5 Testi i kushteve të modifikuara/Mbulimit të vendimeve – Testi MCDC
Testi MCDC pretendon të jetë më preçiz sesa testi MMCC, sepse na duhet të testojmë
nëse ndryshimi i një kushti atomik ka impakt mbi vlerësimin kompleks të kushtit apo jo. Duke
parë në skemën e CFG në këtë faze, ne kemi mbulim të ulët të MCDC në këto kushte:
- (!errorFree | day < 1 | day > 31)
- (chr.equals(".") & whereAmI.equals("month"))
Kështuqë kemi zgjeruar rastet tona testuese me metodat e mëposhtme te cilat
përmbajne 3 teste te tjera:
private static void modifiedConditionDecisionCoverage_MCDC(){
System.out.println(DateParser.parseDate("2013.05.0"));
System.out.println(DateParser.parseDate("2013.14_11"));
System.out.println(DateParser.parseDate("2013.05.11."));
}
Testi i parë vlerëson day<1 si të saktë, vlerën e dytë e vlerësojmë chr.equals(“.”)
si të pasaktë dhe rasti i tretë vlerëson whereAmI.equals(“month”) si të pasaktë. Me këto tre
raste të tjera ne mund të përmbushim mbulimin e MCDC në nivel 100%.
Emri i skedarit te logeve SOTA: modifiedConditionDecisionCoverage_MCDC.log
Figura 18 Paraqitja grafike pas ekzekutimit të test case-ve të 5 parametrave të para
Analiza ,implementimi dhe optimizimi gabimeve në kod
44
Analiza e rezultateve të SOTA:
5.2.1.6 Testi i mbulimit të kushteve të shumëfishta – Testi C3
Për këtë matje, në mënyrë që të arrijmë mbulim 100%, duhet të përfshijmë rastet testuese
të cilat vlerësojnë çdo kombinim të mundshëm të kushteve atomike në një kushtëzim kompleks.
Përderisa ekzistojnë disa kombinime të paarritshme, testi C3 nuk mund të mbulohet asnjëherë në
nivel 100% për arsyet e mëposhtme:
1.(month<1 | month>12)
Nuk ka mundësi të jetë asnjëherë true|true sepse një numër nuk mund të jetë
asnjëherë në të njëjtën kohë edhe më i vogël se 1 dhe më i madh se 12. Ne kemi
testuar 3 nga 4 kombinimet e mundshme (1 është i pamundur).
2.(year<0 | index==1)
Nuk mund të vlerësohet asnjëherë si true|true sepse në mënyrë që viti të ketë disa
vlera duhet që të inkrementohet index.
Ky kusht ka një total prej 8 kombinimesh të mundshme, por 2 nga këto kombinime janë të
paarritshme. Kombinimet në vazhdim janë të pamundura që të ndodhin:
errorFree Day<1 Day>31
True True True
False True True
Dita nuk mund të jetë më e vogël se 1 dhe më e madhe se 31 në të njejtën kohë, kështuqë ne
kemi mbuluar 5/8. Ekziston vetëm një kombinim që nuk është mbuluar, i cili mund të testohet
nga metoda në vijim:
public static void multipleConditionCoverage_c3(){
System.out.println(DateParser.parseDate("2013.9.999."));
}
Figura 19 Paraqitja grafike pas ekzekutimit të testit e MCDC
Analiza ,implementimi dhe optimizimi gabimeve në kod
45
Emri i skedarit te logeve SOTA: multipleConditionCoverage_c3.log
Rezultati i analizës SOTA:
5.2.1.7 Testi i kufirit te brendshem – Testi BI
Në rastin e klasës Date testi BI është i thjeshtë, sepse kemi 4 mundësi pikash hyrje në
bllokun e parë (që është year<10, year<100, year<1000, etj). Për secilen nga këto 4 mundësi, ne
mund t‟i kombinojmë ato me (month<10, muaj të tjerë) dhe pastaj t‟i kombinojmë sërish me
(day<10, ditë të tjera). Kështuqë, në total kemi 4*2*2=16 raste të mundshme testuese, përderisa
nuk kemi asnjë cikël të mbyllur. Duke përjashtuar rastet studimore të cilat janë përdorur mëparë,
marrim:
System.out.println(DateParser.parseDate("2013.5.11"));
System.out.println(DateParser.parseDate("2013.5.2"));
System.out.println(DateParser.parseDate("2013.11.2"));
System.out.println(DateParser.parseDate("222.5.11"));
System.out.println(DateParser.parseDate("222.5.2"));
System.out.println(DateParser.parseDate("222.11.2"));
System.out.println(DateParser.parseDate("22.5.11"));
System.out.println(DateParser.parseDate("22.5.2"));
System.out.println(DateParser.parseDate("22.11.2"));
System.out.println(DateParser.parseDate("2.5.11"));
System.out.println(DateParser.parseDate("2.11.11"));
System.out.println(DateParser.parseDate("2.11.2"));
Veç kësaj, ne mund të gjykojmë në të njëjtën mënyrë siç bëmë me funksionin
DateParser.parseDate(). Është paksa e komplikuar përderisa kemi një cikël të mbyllur:
1. Cikli nuk ekzekutohet,
2. Cikli ekzekutohet vetëm njëherë të vetme,
3. Cikli përsëritet vetëm njëherë të vetme
Figura 20 Paraqitja grafike e pas ekzekutimit të testit C3
Analiza ,implementimi dhe optimizimi gabimeve në kod
46
Trupi i ciklit të mbyllur është një element i strukturuar (if, else if, else if, else) dhe çdo bllok
është gjithashtu një element i strukturuar, kështuqë numri total i rasteve testuese është me të
vërtetë shumë i madh. Sipas SOTA-s (dhe Matematikës gjithashtu) ne mund të gjejmë se numri
më i mundshëm i testit BI është 147 për funksionin parseDate(). Kjo në fakt nuk është shumë e
vërtetë sepse disa pathe janë të paarritshme, si pasojë e strukturës logjike:
Për shembull, trupi i një cikli të mbyllur nuk mund të fillojë asnjëherë tek blloku:
“else if(chr.equals(“.”) & whereAmI.equals(“month”))”
Kjo gjë vjen ngaqë karakteri i parë është “.”, atëherë variabli whereAmI ka vlerën “year”. Pra,
testi i mbulimit BI është me të vërtetë i ngushtë. Ne do mund të përdornim testime të rastësishme
për të rritur përqindjen, por duke qenë se testimet kushtojnë, ne pranojmë një mbulim më të
vogël me minimumin e rasteve të mundshme testuese. SOTA ka vlerësuar një numër maksimal
të degëzimeve në vlerën 163.
Ne ndoqëm një rregull bazë për të derivuar rastet në vijim: Nisim me një vlerë të saktë të mundur
ose të pamundur dhe përpiqemi që të parashikojmë të gjitha karakteret vijuese në hyrje të cilat
programi mund t‟i lexojë pa u mbyllur.
Përderisa metoda përmban 120 raste testuese, ajo është e përfshirë në një skedar zip të
emërtuar boundaryInteriorPath_BI() brenda klasës testuese.
Emri i skedarit te logeve SOTA: boundaryInteriorPath_BI.log
Figura 21.Paraqitja grafike pas anlizes se testit MBI dhe BI
5.2.1.8 Testi i pathit të brendshëm të modifikuar - Testi MBI
Çuditërisht, mbulimi për këtë test është shumë i ulët, 43,96%. Edhe pse testi BI ka një
mbulim shumë të mirë me 85,59% që do të thotë se shumë nga pathet e mundshme janë vizituar
tashmë, testi MBI është shumë i ulët prapë se prapë. Për më tepër, numri i rasteve testuese
aktualisht është rritur pak, kështuqë po të shtonim raste të tjera testuese shtesë rrit koston dhe
kohën për të aplikuar këto teste. Kështuqë përfundimisht ne po pranojmë vlerën 43,96% si një
mbulim të mirë për këtë test.
Analiza ,implementimi dhe optimizimi gabimeve në kod
47
5.3 Përmbledhje
5.3.1 Klasa testuese në Java
Ne kemi krijuar një klasë në Java të emërtuar DateParserTest , e cila ka një metodë për
secilin set të rasteve testues. Metodat thirren një nga një në metodën kryesore (duke komentuar
rreshtat e tjerë ndërkohë), kështuqë secili set testues ka një skedar të ndarë ASCILogger.
Përderisa rastet testuese janë të trashëguar/zgjeruar në setet pasuese testuese, ne mund t‟i
bashkangjisim ekzekutimin e metodave pasuese brenda main() ose të bashkojmë rezultatet e
testeve (interpretimet e logeve) në SOTA. Në rastin tonë menduam se është më i arsyeshëm
bashkimi i rezultateve të testeve në SOTA.
Vini re:
Metodat në klasën DateParserTest mbajnë thirrjen System.out.println(); e cila nuk është
e nevojshme (përveç testit FEEC dhe BI).
Tabela 4 Tabela e rezultateve
Testi Mbulimi Nr.
Testimeve
Emri metodës Emërtimi skedarit të logeve
FEEC 100% 2 functionIOCoverage_feec functionIOCoverage_feec.log
C0 100% 5 statementCoverageTest_C0 statementCoverageTest_C0.log
C1 100% 0 - -
C2 100% 3 simpleConditionCoverage_c2 simpleConditionCoverage_c2.l
og
MMCC 100% 0 - -
MCDC 100% 3 modifiedConditionDecisionCov
erage_MCDC
modifiedConditionDecisionCo
verage_MCDC.log
C3 90.91% 1 multipleConditionCoverage_c3 multipleConditionCoverage_c
3.log
MBI 43.96% 0 - -
BI 85.89% 121 boundaryInteriorPath_BI boundaryInteriorPath_BI.log
Analiza ,implementimi dhe optimizimi gabimeve në kod
48
6 Analiza Statike
6.1 Problemet ne kualitetin software-ik dhe matjet e tij.
6.1.1 Objektivi dhe motivimi.
Sistemet software-ike që janë përmendur sot janë bërë shumë të komplikura. Lidhur me
këtë ato janë ndarë në module/klasa/njësi apo cdo formë që një gjuhë programimi suporton. Për
sejcilën prej këtyre njësive, dhe për cdo gjuhë programimi ka sygjerime lidhur me kualitetin
software-ik, lidhur me kompleksitetin, gjatësinë, përmasën, numrin e variablave, parametrave etj.
Matja e kualitetit software-ik është vërtetuar që është gjë e mirë për procesin e zhvillimit[17].
6.1.2 Software-i nën testim
Për këtë rast studimor kam zgjedhur dy klasa të një komplilatori që përkthen
njëprogram në paskal në një kod makine virtuale P-Code. Klasa Error është përgjegjëse për
printimin e mesazhin gabues për stream-in në pëputhje me nje kod të dhënë ku klasa Scanner
implementon komponentët leksik të kompilatorit. Përdor CCCC për të krijuar një raport të
metrikave për një softuer të caktuar në bazë të testit dhe analizuar vlerat e metrikave, rreshtat e
kodit ( LOC ) dhe kompleksiteti ciklomatik( MVG ) për metodat e klasave ( moduls ) Error dhe
Scanner . Veçanërisht vëmendje marrin metodat kritike ( hyrjet me ngjyrë ). Përveç kësaj të
ekzaminoj sipas kodi burim të këtyre metodave duke përdorur mjetet Sota për të llogaritur
metrikat për software në provë dhe krahasoj metrikat , vlerat me ato nga raporti cccc .
6.1.3 Komentet mbi vlerat e metrikave MVG dhe LOC
Klasat Error dhe Scanner janë klasa të një kompilatori që përkthejnë programet e
shkruara në nga Pas-0 në kod të makinës virtuale P-Code. Së pari është përdorur mjeti CCCC
për të llogaritur vlerat e metrikave LOC (rreshtat e kodit) dhe MVG (cyclomatic complexity) për
metodat e këtyre klasave. Është përdorur dhe mjeti SOTA për të njëjtën arsye.
Në këtë seksion do të analizohen vlerat që janë marrë nga CCCC për secilën nga metrikat për
metodat e klasave të mësipërme. Pas kësaj do të analizohen rezultatet e marra nga SOTA për të
njëjtat metrika. Rezultatet e marra nga dy mjete të ndryshme do të krahasohen.
Për të analizuar vlerat, do të marrim në konsideratë vlerën maksimale të MVG, që është 10
(bazuar tek rekomandimet e McCabe).
Më pas do të analizojmë metodat për një kompleksitet më të lartë, e cila mund të çojë në më
shumë gabime dhe në një mungesë të qartësisë. Metodat komplekse kërkojnë më shumë kohë për
t‟u zhvilluar dhe për t‟u testuar. Nga rezultatet që u morën nga CCCC, u vu re se disa vlera të
metrikave ishin me ngjyra (të kuqe dhe të verdha). Kjo ndodh për shkak të kompleksitetit të
tepruar që duhet të shmanget. Zgjidhje për të thjeshtuar kompleksitetin është të rishkruhen dhe
të ndahen metodat në disa metoda.
Analiza ,implementimi dhe optimizimi gabimeve në kod
49
Nga ana tjetër kompleksiteti lidhet pozitivisht me përmasat e kodit. Një program apo funksion i
madh ka gjasa të jetë kompleks. Gjithsesi një procedure me relativisht pak rreshta kodi mund të
jetë edhe më komplekse se sa një procedure e gjatë.
6.2 Klasa Error.java Kjo klasë është përgjegjëse për të printuar mesazhet jo korrekte në rradhën e gabimeve
bazuar në një gabim kodi të dhënë. Në figurën 22 je pen vlerat e metrikave për tre metoda (error,
ioError, symbolError) llogaritur nga CCCC dhe në figurën 2 jepen vlerat e llogaritura nga
SOTA.
Figura 22 Vlerat e metrikave të llogaritura nga CCCC
Figura 23 Vlerat e metrikave të llogaritura nga SOTA
6.2.1 Rezultatet e CCCC
a. Metoda: error(int,int,int)
Metoda LOC MVG error(int,int,int) 34 57
MVG
Ne e dimë se kompleksiteti çiklomatik përdoret për të treguar kompleksitetin e një programi. Ai
mat direkt numrin e rrugëve lineare të pavarura në një kod burim të një programi. Nga tabela
shohim se MVG është 57, që tregon një vlerë të lartë. Por duke marrë në konsideratë
Analiza ,implementimi dhe optimizimi gabimeve në kod
50
implementimin e kësaj metode (switch me shumë case) mund të themi se ka një përpjestim
ndërmjet kompleksitetit dhe përmasave të kodit.
LOC
Nga tabela e mësipërme shohim se rezultati për LOC të llogaritura nga CCCC është 34, e cila
nuk është një vlerë e lartë. Mund të themi se metoda është e qartë dhe e thjeshtë për t‟u kuptuar.
b. Metoda: symboError(int,int,int)
Metoda LOC MVG
symbolError(int,int,int) 4 0
MVG
Nga tabela mund të shohim se rezultatet e lloagritura nga CCCC tregojnë se MVG është 0 sepse
kjo është një metodë e thjeshtë dhe nuk ka fjalë kyçe ose operator që të rrisin kompleksitetin.
LOC
Rezultati i marrë nga CCCC është 4. Është një vlerë e vogël dhe nuk shkakton kompleksitet,
kështu që është një metodë e qartë dhe e thjeshtë për t‟u kuptuar.
6.2.2 Rezultatet e SOTA
a. Metoda: error(int,int,int)
Metoda LOC MVG
error(int,int,int) 39 29
MVG
Bazuar tek përkufizimi i MVG dhe tek formula: v(G) = e – n + 2 (e – numri i degëve, n - numri i
nyjeve), ne mund ta llogarisim vlerën e mësipërme: v(G) = 89 -62 + 2 = 29.
Vlera e llogaritur nga CCCC është më e madhe se v(G). Kjo ndodh sepse switch-i me 28 case rrit
kompleksiteti e kësaj metode.
LOC
Rezultati i llogaritur nga SOTA është 39, kurse rezultati i marrë nga CCCC është më i vogël. Kjo
ndodh për arsye se CCCC nuk llogarit hapësirat midis rreshtave dhe komentet. Pavarësisht kësaj
të dyja vlerat nuk janë të larta dhe nuk tregojnë kompleksitet në rreshtat e kodit.
Si përfundim mund të themi se kjo metodë është e thjesht për t‟u kuptuar dhe lexuar. Gjithashtu
është e lehtë për t‟u zhvilluar, testuar dhe riimplementuar.
b. Metoda: symbolError(int,int,int)
Analiza ,implementimi dhe optimizimi gabimeve në kod
51
Metoda LOC MVG
symbolError(int,int,int) 3 1
MVG
Bazuar në metodën e CFG, kjo metodë ka 1 degë dhe 2 nyje, kështu vlera MVG është v(G) = 1 –
2 + 2 = 1.
Kjo vlerë është më e vogël se 10, e cila është vlera e rekomanduar, prandaj mund të themi se
metoda nuk ka kompleksitet. Vlera nga CCCC është më e vogël sepse kjo metodë nuk përmban
cikle apo kushte.
LOC
Rezultati i llogaritur nga SOTA është 3 dhe ky është një rezultat i pritshëm. Rezultati i marrë nga
CCCC është më i madh, por në të dyja rastet metoda është e qartë, e thjeshtë për t‟u kuptuar, e
thjeshtë për t‟u zhvilluar dhe riimplementuar.
c. Metoda: ioError()
Metoda LOC MVG
ioError() 3 1
MVG
Njësoj si metoda symbolError, kjo metodë ka 1 degë dhe 2 nyje, me një vlerë të MVG prej: v(G)
= 1 – 2 + 2 = 1. Kjo vlerë është një njësi më e madhe se vlera e llogaritur nga CCCC dhe është
më e vogël se vlera e rekomanduar 10. Si përfundim mund të themi se është një metodë pa
komleksitet.
LOC
Rezultati i SOTA është 2 dhe ky është rezultati që ne prisnim sepse ka vetë 2 rreshta kod.
Rezultati i CCCC është më i madh se sa rezultati i SOTA, por të dyja vlerat janë të vogla dhe
nuk tregojnë kompleksitet. Metoda është e qartë dhe e thjeshtë për t‟u kuptuar. Gjithashtu e lehtë
për t‟u zhvilluar dhe testuar.
6.3 Scaner.java Kjo klasë implementon komponenten leksikore të kompilatorit. Në figurën 24 jepen vlerat
e metrikave të llogaritura nga CCCC për metodat (Scanner, charIsAlpha, charIsDigit, comment,
getLine, getPos, getSymbol, handleIdentifier, main, number, readNextChar). Në figurën 25 jepen
vlerat e llogaritura nga SOTA.
Analiza ,implementimi dhe optimizimi gabimeve në kod
52
Figura 24 Vlerat e metrikave të llogaritura nga CCCC
Nga figura shohim se disa nga metodat janë të ngjyrosura (të kuqe dhe të verdha), që do të thotë
se se ato kanë kompleksitet të tepërt. Vlerat e tjera që nuk janë të ngjyrosura tregojnë se MVG
dhe LOC janë larg vlerës maksimale të rekomanduar dhe metodat përkatëse nuk janë komplekse.
Ato janë të thjeshta për t‟u kuptuar, lexuar, zhvilluar dhe testuar. Interesi ynë është analiza dhe
krahasimi i vlerave për metodat e ngjyrosura.
Analiza ,implementimi dhe optimizimi gabimeve në kod
53
Figura 25 Vlerat e metrikave të llogaritura nga SOTA
6.3.1 Rezultatet e CCCC
a. Metoda: getSymbol()
Metoda LOC MVG
getSymbol 78 45
MVG
Rezultati i llogaritur nga CCCC është më i lartë se sa kufiri i rekomanduar. Me këtë mund të
themi se metoda është komplekse dhe jo shumë e sigurt.
LOC
Janë 78 rreshta, e cila është një vlerë e lartë. Kjo vlerë tregon për një kompleksitet të lartë të
rreshtave të kodit.
b. Metoda: handleIdentifier()
Metoda LOC MVG
handleIdentifier() 22 19
MVG
Vlera e MVG është 19 dhe është një vlerë më e madhe se sa kufiri i lejuar. Kjo do të thotë se
kemi të bëjmë me një metodë komplekse.
Analiza ,implementimi dhe optimizimi gabimeve në kod
54
LOC
Rezultati i CCCC është 66. Kjo vlerë është më e madhe se limiti maksimal dhe nuk merr në
konsidertë hapësirat midis rreshtave dhe komentet.
6.3.2 Rezultatet e SOTA
a. Metoda: getSymbol()
Metoda LOC MVG
getSymbol() 78 27
MVG
Kjo metodë ka 99 degë dhe 74 nyje, kështu vlera e MVG është: v(G) = 99 – 74 + 2 = 27. Kjo
është vlera e llogaritur nga SOTA dhe është më e madhe se vlera maksimale. Prandaj metoda
është komplekse dhe jo e sigurt.
Shohim se ka shumë diferencë midis vlerave të llogaritura nga SOTA dhe CCCC. Bazuar tek
implementimi shohim se arsyeja e këtij kompleksiteti të lartë dhe ndryshimit midis dy vlerave
është switch-i me shumë case dhe disa if-else brenda switch-it. Për më tepër switch-i është i
vendosur brenda një cikli.
LOC
Vlera e llogaritur nga SOTA është 78 dhe është e njëjtë me vlerën e llogaritur nga
CCCC. Kjo është një vlerë e lartë që tregon edhe një kompleksitet të lartë të kodit. Kjo do të
thotë se metoda ka probleme me qartësinë, është e vështirë për t‟u kuptuar dhe me gabime.
Gjithashtu nuk është e lehtë për t‟u zhvilluar si metodë.
b. Metoda: handleIdentifier()
Metoda LOC MVG
handleIdentifier() 21 20
MVG
Kjo metodë ka 97 degë dhe 79 nyje. Vlera e MVG është: v(G) = 97 – 79 + 2 = 20. Ky rezultat
është më i lartë se vlera maksimale e përcaktuar që do të thotë se metoda është komplekse.
Shohim se vlera e llogarir nga SOTA është një njësi më e madhe se sa ajo e llogaritur nga
CCCC. Kjo ndodh sepse janë 19 kushte të llogaritura nga CCCC. Duke marrë parasysh
implementimin e kësaj metode, vëme re se janë 20 rrugë të mundshme sipas if-else, e cila e
Analiza ,implementimi dhe optimizimi gabimeve në kod
55
dyfishon kompleksitetin. Pavarësisht se nga vlera e MVG rezulton se metoda është komplekse.
Në fakt nga implementimi i saj kuptohet se nuk është shumë.
LOC
Vlera e LOC është një njësi më e vogël se vlera e llogaritur nga CCCC. Në fakt kjo është vlera
që ne presim sepse janë 21 rreshta kodi. Të dyja vlerat nuk janë shumë të larta dhe nuk tregojnë
kompleksitet në kod. Si përfundim mudn të themi se metoda është e qartë dhe lehtësisht e
kuptueshme.
c. Metoda: number()
Metoda LOC MVG
number() 70 12
MVG
Kjo metodë ka 47 degë dhe 37 nyje. Vlera e MVG është: v(G) = 47 – 37 + 2 = 12. Kjo vlerë nuk
është shumë larg nga vlera kufi e përcaktuar. Prandaj mund të themi se kjo metodë nuk është
shumë komplekse. Krahasuar me CCCC është një vlerë 2 njësi më e vogël.
Për më tepër, bazuar tek implementimi kjo metodë ka shumë cikle dhe kushte if-else. Kjo na
shtyn që të presim një kompleksitet më të madh se sa ai i rekomanduar.
LOC
Rezultati i SOTA është 4 herë më i madh se sa ai i marrë nga CCCC sepse CCCC nuk merr në
konsideratë hapësirat midis rreshtave dhe komentet. Të dyja vlerat janë të larta dhe tregojnë për
kompleksitet në kod. Gjithashtu bazuar tek implementimi vëmë re se kjo metodë ka shumë
rreshta kod dhe asnjë koment. Kjo do të thotë se kodi nuk është i qartë, është i vështirë për t‟u
kuptuar, zhvilluar dhe riimplementuar.
6.4 Avantazhet dhe disavantazhet e kompleksitetit çiklomatik Më poshtë do të jepet një listë e avantazheve dhe disavantazheve të MVG. Bazuar në
punën e bërë do të komentojmë disa prej tyre.
Avantazhet:
1. Është i lehtë për t’u llogaritur nga programi dhe CFG
Llogaritja e MVG u bë me dy mjetet CCCC dhe SOTA. Në të dyja rastet ishte e thjeshtë
llogaritja. Për CCCC duke numëruar fjalët kyçe si „if‟, „while‟, „for‟, „switch‟, „break‟, „&&‟,
Analiza ,implementimi dhe optimizimi gabimeve në kod
56
„||‟ose për SOTA nëpërmjet formulës v(G) + e – n + 2 duke numëruar degët dhe nyjet nga
metoda CFG.
2. Ajo mbështet një proces zhvillimi nga lart-poshtë për të kontrolluar kompleksitetin në
fazën e projektimit.
3. Përcakton setin maksimal të rrugëve të pavarura.
4. Përdoret për të kontrolluar kompleksitetin e moduleve të programit duke përcaktuar
vlerën kufi 10.
Është përdorur vlera e rekomanduar për të përcaktuar nëse programi ishte kompleks ose jo. Nëse
MVG ishte më e madhe se 10, atëherë programi ishte kompleks, në të kundërt nuk ishte.
5. Përdoret për të vlerësuar dezajnin e programit për të gjetur strukturën më të thjeshtë të
mundshme të programit.
Një vlerë e lartë e MVG do të thotë se programi ka një strukturë të keqe, prandaj na duhet ta
rishkruajmë programin duke e ndarë në disa procedura në mënyrë që të kemi një program më të
thjeshtë dhe të mirë strukturuar.
6. Shërben për të ndarë strukturën e programit në mundësi të larta ose të ulta për gabime
sipas vlerës.
Një vlerë e lartë e MVG do të thotë se edhe mundësia e gabimeve është e lartë, që përkthehet
ndryshe si paqartësi dhe vështirësi për leximin dhe riimplementimin e programit. E kundërta
ndodh për vlera të vogla të MVG.
7. Shërben për të ndarë strukturën e programit në gjetje dhe heqje të gabimeve shpejt ose
ngadalë në varësi të vlerës.
8. Mund të shërbejë si guidë për vendosjen e burimeve të testimit.
Disavantazhet:
1. Mat vetëm kompleksitetin psikologjik. Nuk mat kompleksitetin llogaritës.
MVG mat direkt numrin e rrugëve lineare të pavarura në një kod programi dhe nuk mat
kompleksitetin llogaritës që është i rëndësishëm sepse ndikon tek overhead-i.
2. Tregon të gjitha predikatat, alternimet dhe përsëritje sikur ndikojnë njësoj tek
kompleksiteti.
Tek MVG çdo përsëritje ose alternim e rrit kompleksitetin me 1. Kjo nuk është korrekte sepse
disa përsëritje ose alternime janë më komplekse se sa të tjerat dhe ndikimi në kompleksitet nuk
duhet të jetë i njëjtë.
3. Është e pandjeshme në nivelin e :
Analiza ,implementimi dhe optimizimi gabimeve në kod
57
a. Ngastra me shumëllojshmëri ndërtimesh
Për llogaritjen e MVG nuk merren në konsideratë niveli i ndërthurjeve. Në vend të kësaj bazohet
tek numri i degëve. Kjo situatë u pa tek metoda getSymbol(), e cila ka shumë ndërthurje, po këto
nuk ndikuan kompleksitetin.
b. Frekuenca dhe tipi i hyrjeve dhe daljeve
c. Përmasa e programeve sekuenciale
d. Numri i variablave në program
Klasa Scanner.java ka më shumë varibla se sa klasa Error.java, por kjo nuk e ndikoi
kompleksitetin e klasës.
e. Numri i veprimeve me të dhënat në program
f. Varësia e rrjedhjes së kontrollit në veprimet me të dhënat
g. Situatat kur një kusht është i maskuar apo i bllokuar nga një tjetër
Kjo situatë u pa tek metoda number() e klasës Scanner,java. Fakti se kjo nuk ndikon
kompleksitetin nuk është shumë e saktë sepse kjo situatë mund të çojë në rrugë të pamundshme
brenda moduli.
h. Stili i programit dhe përdorimi i GOTO
MVG është indiferente ndaj GOTO, por rrugët e modulit kanë varësi. Prandaj GOTO duhet të
merret në konsideratë sepse kjo situatë mund të çojë në rrugë të pamundshme brenda modulit.
4. Ai nuk llogarit as llojet dhe nivelet e modulit të përsëritur, as nivelet e modulit thirës.
5. Ajo nuk pasqyron me saktësi përmirësim e rezultatit nga rishikimi i programit.
6.4.1 Vlerat e këqija për kompleksitetin çiklomatik
MVG është një vlerë që përdoret për të shprehur kompleksitetin e kodit burim. Një vlerë
e ulët është një faktor për të përmirësuar lexueshmërinë, mirëmbajtjen dhe testimin për kodin.
Nëse moduli ka një vlerë të lartë do të thotë se ky program ka vështirësi për t‟u kuptuar,
ndryshuar, zgjeruar dhe zhvendosur.
Mirëmbajtja është një faktor që ndikon në cilësinë e software-it. Një produkt duhet të jetë i mirë
dokumentuar në mënyrë që të jetë e lehtë për t‟u mirëmbajtur. Në këtë mënyrë MVG ka një
ndikim të madh në mirëmbajtjen e moduleve të programit.
Më lart janë analizuar dhe krahasuar vlerat që janë marrë nga CCCC dhe SOTA për MVG dhe
LOC. Në këtë seksion do të analizojmë vlerat kritike (>10) që tregojnë kompleksitet të lartë të
metodave dhe që mund të ndikojë tek mirëmbajtja. Metodat me vlera të larta të MVG janë:
Klasa: Error.java
Analiza ,implementimi dhe optimizimi gabimeve në kod
58
1. Në metodën error(int,int,int), vlerat e MVG të llogaritura nga CCCC dhe SOTA
janë më të mëdha se kufiri i lejuar. Kjo tregon se kjo metodë është komplekse dhe
ka stil të keq programimi. Për këtë arsye na duhet ta rishkruajmë programin duke
e ndarë në metoda më të thjeshta që mund të jenë më të kuptueshme dhe lehtësisht
të zgjerueshme.
Klasa: Scanner.java
1. Në metodën getSymbol(), vlerat e MVG të llogaritura nga CCCC dhe SOTA janë
shumë më të larta se kufiri i përcaktuar. Kjo do të thotë se metoda ka një stil të
keq programimi. Kjo ndodh për shkak të një switch me shumë case të përfshirë
brenda një cikli. Gjithashtu ka shumë cikle while dhe kushte if-else të ndërfutura.
Kjo metodë duhet të riimplementohet në mënyrë të tillë që të shmangen
instruksionet e ndërfutura dhe ta bëjmë metodën më të lehtë për t‟u kuptuar,
lexuar dhe mirëmbajtur.
2. Në metodën handleIdentifier(), vlerat e llogaritura nga CCCC dhe SOTA
tregojnë se metoda ka një vlerë dyfish më të lartë të MVG se sa kufiri i
përcaktuar. Kjo do të thotë se metoda është komplekse, por ne presim që këto
vlera të jenë më të mëdha se 10 për shkak të kushteve if-else që krijojnë 20 rrugë
lineare të mundshme. Kjo metodë nuk ka stil të keq programimi dhe është e
thjeshtë për t‟u kuptuar dhe mirëmbajtur.
3. Në metodën number(), vlerat e llogaritur nga CCCC e SOTA janë afërsisht sa
vlera kufi, kështu metoda nuk ka stil të keq programimi dhe nuk mund të
sugjerojmë ndonjë përmirësim.
6.4.2 Matje shtesë
Nga llogaritjet e bëra u vu re se ka disa vlera të tjera interesante të matura nga CCCC.
Janë dy metoda error(int,int,int) nga klasa Error.java dhe number() nga klasa Scanner.java që
kanë rezultate të ngjyrosura për dy metrikat L_C dhe M_C.
L_C = rreshta kodi për rreshta komenti. Tregon densitetin e komenteve në respekt të përmasës së
tekstit në program.
M_C = MVG për rreshta komenti. Tregon densitetin e komenteve në respekt të kompleksitetit
logjik në program.
Metodat L_C M_C
error(int,int,int) 11,333 19,000
number() 7,333 1,556
Metoda: error(int,int,int) e klasës Error,java
L_C = 34 / 3 = 11,333
Analiza ,implementimi dhe optimizimi gabimeve në kod
59
Kjo do të thotë se 8,8% e metodës është koment. Kjo është një vlerë e ulët sipas limitit minimal
të rekomanduar ku 30% - 75% e kodit duhet të jetë koment. Kjo është arsyeja pse janë të
ngjyrosura me të verdhë.
M_C = 57 / 3 = 19
Sipas vlerave të larta të MVG, mund të themi se M_C ka një vlerë të lartë gjithashtu. Kjo është
arsyeja pse ka një ngjyrë të kuqe.
Metoda: number() e klasës Scanner.java
Në këtë metodë vetëm L_C ka një vlerë kritike:
L_C = 66 / 9 = 7,333
Kjo do të thotë se 13,6% e metodës është koment. Për të njëjtën arsye si në metodën
error(int,int,int) themi se metoda është varfërisht e shpjeguar.
Analiza ,implementimi dhe optimizimi gabimeve në kod
60
7 Optimizimi dhe sfidat në të ardhmen
7.1 Optimizimi i gabimeve në kod
Në shkencat kompjuterike optimizimi i programeve është proçesi i modifikimit të një
sistemi kompjuterik për të bërë disa aspekt të saj të punojnë në mënyrë më efikase ose të për të
përdorur më pak burime. Në përgjithësi, një program kompjuterik mund të jetë i optimizuar në
mënyrë që ai të ekzekutoj më shpejt, ose është i aftë të veprojnë më pak kujtesës ose burime të
tjera, ose të humbë më pak energji.
Edhe pse fjala "optimizim " ndan të njëjtin rrënjë si "optimal", ajo është e rrallë për procesin e
optimizimit për të prodhuar një sistem të vërtet optimale. Sistemi i optimizuar në mënyrë tipike
do vetëm të jetë optimal në një aplikim ose për një audiencë. Një system i tillë mund të
zvogëlojë sasinë e kohës që një program merr për të kryer disa detyra, duke e bërë të
konsumojnë më shumë memorie . Në një aplikim ku hapësira e memories është primare ,
dikush mund të zgjidhni qëllimisht një algoritëm më të ngadalshme në mënyrë që të përdorin më
pak memorie . Shpesh nuk ka " një madhësi që iu përshtatet të gjithë-ve " ,por dizajn-i që punon
mirë në të gjitha rastet , kështu që inxhinierët të bëjnë kompromise të zgjedhin atributet me
interesit më të madh .
Përveç kësaj ,përpjekje të nevojshme për të bërë një pjesë e software plotësisht optimale – të
paaftë për ndonjë përmirësim të mëtejshëm - është pothuajse gjithmonë e më shumë e arsyeshme
për të mirat që do të grumbullohen ; në mënyrë që procesi i optimization mund të ndalet para se
një zgjidhje krejtësisht optimale të jetë arritur. Për fat të mirë , është shpesh rasti që
përmirësimet më të mëdha vijnë në fillim të procesit.
7.2 Nivelet e optimizimit Optimization mund të ndodhë në një numër nivelesh . Në mënyrë tipike nivelet më të
larta të kenë ndikim më të madh , dhe janë të vështirë për të ndryshuar më vonë në një projekt që
kërkon ndryshime të rëndësishme ose një rishkrim të plotë në qoftë se ato duhet të ndryshohen.
Kështu optimization në mënyrë tipike mund të vazhdojë nëpërmjet rafininmit nganiveli më i
lartë në atë më të ulët , me fitimet fillestare për të qenë më të mëdha dhe të arrihet me më pak
punë , dhe fitimet pasuese duke qenë më të vogla dhe që kërkojnë më shumë punë.
Megjithatë, në disa raste performanca e përgjithshme varet nga performanca e shumë pjesëve të
nivelit të ulët të një programi , dhe ndryshime të vogla në një fazë të vonëshme mund të ketë
ndikim shumë të madh .
Disa prej niveleve të optimizimit janë:
Algoritmet dhe strukturat e të dhënave
Në një dizajn të përgjithshëm duhet pasur parasysh që të kemi një zgjedhje të mirë ë
algoritmeve efikase dhe strukturave të të dhënave, si dhe zbatim efikas të tyre.Pas
projektimit, zgjedhja e algoritmeve dhe strukturave të të dhënave ndikon në efikasitet më
shumë se çdo aspekt tjetër i programit. Në përgjithësi strukturat e të dhënave janë më të
vështira për të ndryshuar se algoritmet. Supozimet për strukturën e të dhënave dhe për
performancën janë përdorur në program,edhe pse kjo mund të minimizohet nga përdorimi
i llojeve abstrakte të të dhënave në përkufizimet e funksionit, dhe duke e mbajtur
përkufizimet konkrete për strukturën e të dhënave të kufizuara në disa vende.
Analiza ,implementimi dhe optimizimi gabimeve në kod
61
Për algoritmeve, kjo kryesisht konsiston për të siguruar që algoritmet janë me
kompleksitet konstant O(1), logaritmik O(log n), O linear (n), ose në disa raste logaritem
-linear (n log n) në të dhëna (si në hapësirë dhe kohë). Algoritmet me kompleksitet O(N2)
katror nuk arrijnë të shkallëzohen dhe madje edhe algoritme lineare të shkaktojnë
probleme nëse në mënyrë të përsëritur rithirren dhe janë zëvendësuar në mënyrë tipike
me konstante ose logaritmike nëse është e mundur.
Një teknikë e përgjithshme për të përmirësuar performancën është shmangia e punës. Një
shembull i mirë është përdorimi i një rrugë të shpejtë për raste të zakonshme,
përmirësimin e performancës duke shmangur punën e panevojshme. Një tjetër teknikë e
rëndësishme është caching, veçanërisht memorizimi, e cila shmang llogaritje të tepërta.
Për shkak të rëndësisë së caching, shpesh ka shumë nivele të caching në një sistem, i cili
mund të shkaktojë probleme nga përdorimi kujtesës, dhe çështje të korrektësisë nga arka
bajate.
Niveli i kodit burim
Përtej algoritme të përgjithshme dhe zbatimin e tyre në një makinë abstrakte , zgjedhja
konkrete e nivelit të kodit burim mund të bëjë një ndryshim të rëndësishëm .Për
shembull , mbi hartuesit e hershme të C , while ( 1 ) ishte më e ngadalshme se sa for ( ;; )
për një cikël të pakushtëzuar , sepse while ( 1 ) është vlerësuar 1 dhe pastaj kishte një
kërcim me kusht që testuar nëse kjo ishte e vërtetë , ndërsa për ( ;; ) kishte një kërcim të
pakushtëzuar . Disa optimizations (si ky ), në ditët e sotme mund të kryhet nga
optimizimi i kompilatorit . Kjo varet nga gjuha burim, në gjuhën e makinës objektiv ,
dhe përpiluesit , dhe mund të jetë edhe i vështirë për t'u kuptuar ose të parashikuar dhe
ndryshimet me kalimin e kohës. Ky është një vend kyç ku kuptimi i kompilatorit dhe
kodit të makinës mund të përmirësojë performancën . Kodi ciklik i pandryshuar dhe
vlerat e kthyera janë shembuj të optimizimit që zvogëlojnë nevojën për variabla ndihmëse
dhe mund të rezultojë në performance më të mire duke shmangur optimizimet vajtje
ardhje.
Niveli i ndërtimit
Midis burimit dhe nivelit të kompilimit direktivat dhe flamujt mund të përdoren për të
mbajtur performancën në kodin burim dhe kompilatorin respektivisht.
Gjatë ekzekutimit
Kompilatorët e sotëm (Just-in-Time) mund të prodhojë kode në makina të bazuara në të
dhënat e drejtuara me kohë, në koston e kompilimit të sipërm. Kjo teknikë e përdoru në
motorët e shprehjeve të rregullta është përhapur me Java HotSpot dhe V8 për
JavaScript. Në disa raste përshtatja e optimizimit mund të jetë aftë për të kryer në kohë
optimizime duke tejkaluar aftësinë e hartuesve statike me rregullimi dinamik të
parametrave sipas kontributit aktual apo faktorëve të tjerë.
Kodi Vetë-modifikimin mund të ndryshojë veten në ekzekutim kushtet kohore në
mënyrë që të optimizojë kodin; kjo ishte më shumë e zakonshëm në asembler.
Disa dizajne CPU mund të kryejë disa optimizime gjatë ekzekutimit. Disa shembuj
përfshijnë ekzekutimit Out-of-order(Jashtë rendit) , ekzekutimi spekulative,
Kompilatorët mund të ndihmojnë programin për të marrë parasysh këto cilësi të CPU-s
CPU-së ,për shembull perms instruksioneve të skedulimit.
Analiza ,implementimi dhe optimizimi gabimeve në kod
62
7.3 Platforma e varur dhe optimizimi i pavarur Optimizimi i kodit mund të kategorizohet gjërësisht si i varuar nga platform me
teknika të pavarura. Ndërsa këta të fundit janë efektive në shumicën apo të gjitha platformat ,
teknikat platformave të varura përdorin vetitë e veçanta të një platformë , ose mbështeten në
parametrat në varësi të një platforme të vetme apo edhe në procesor të vetëmShkrimi ose
prodhimi i versioneve të ndryshme për të njëjtin kod për procesor të ndryshëm mund të jete e
nevojshme.Për shembull në rastin e optimizimit të kompilimit teknika të pavarura janë teknika
gjenerike si psh loop unrolling ,reduktim në thirrjet e funksionit ,reduktimi i kushteve , që kanë
inpakt në CPU në mënyre të ngjashme.Përgjithësisht këto ndihmojnë për të reduktuar rrugën
totale për të përfunduar programin dhe për të përdorimin e përgjithshëm të kujtesës gjatë
procesit.Në anën tjetër teknikat e varura nga platform përfshijnë skedulimin e
instruksioneve,nivelin e paralelizmit të tyre,të të dhënave optimizimin e nivelit të cachesë dhe
instruksionet optimale të skedulimit mund të jenë të ndryshme për procesorë të ndryshëm të së
njëjtës arkitekturë.
7.4 Pikat bllokuese Optimizimi pëfshin gjetjen e pikave pikave bllokuese të një sistemi, një factor që limiton
performancën.Në termat e kodit kjo është një zone e nxehtë,një pjesë kritike që është
konsumuese dhe që ka nevojë për burime.Algoritme komplekse dhe struktura të dhënash
performojnë mire me shumë gjëra ndërsa algoritme të thjeshta për sasi shuem të vogël të
dhënash-setup-in kohën e inicializimit, dhe faktorë konstant për shumë algoritma kompleksëpsh
algoritmat hibridë apo adaptive , të cilët mund të jenë më të shpejtë se cdo algoritëm i vetëm.
7.5 Kostoja e optimizimi Sot nuk është e pazakontë për programuesit software për të rekomanduar që asnjë
funksion apo metodë nuk duhet të jetë më e gjatë se disa rreshta . Disa dekada më parë
,rekomandimi ishte e kundërta: mos vendos diçka në një subroutinë të veçantë nëse ajo është
thirrur vetëm një herë. Arsyet për këtë ndryshim në shkrim software janë që projektet software
janë bërë më të mëdha dhe më komplekse , që ka më shumë fokus në kostot e zhvillimit të
softwerit , dhe se kompjuterët janë bërë më i fuqishëm.
Prioritet i lartë i zhvillimit të softwerit të strukturuar dhe me prioritet të ulët të efikasitetit të
programit është reflektuar , para së gjithash , në zgjedhjen e gjuhës së programimit dhe të
ndërfaqes së framework-ut. Kjo është shpesh një disavantazh për përdoruesit fundorë që ka për të
investuar ndonjëherë në kompjuterat më të fuqishëm për të mbajtur me paketat më të mëdha
software dhe që dështon ende nga kohët e papranueshme të gjata dhe përgjigje , madje edhe për
detyra të thjeshta .
Ndonjëherë është e nevojshme të bëhet kompromis mbi parimet e avancuara të zhvillimit
software- it në mënyrë që ti bëjë paketat software më të shpejtë dhe më të vogla . Ky manual
diskuton se si të bëjnë një bilanc të ndjeshme në mes të këtyre konsideratave . Ajo është
diskutuar se si për të identifikuar dhe izoluar pjesën më kritike të një programi dhe të
përqëndrohen përpjekjet optimizimin në atë pjesë të veçantë. Ajo është diskutuar se si për të
kapërcyer rreziqet e një stili programimi relativisht primitive që nuk kontrollon automatikisht
për mëdhenj shkeljet e kufijve , pointer-at e pavlefshme ,etj Dhe kjo është diskutuar që nga
konstruktet e programimit të avancuar që janë të kushtueshme dhe ato që janë të lira, në lidhje
me kohën e ekzekutimit .
Analiza ,implementimi dhe optimizimi gabimeve në kod
63
7.6 Sfidat e optimizimit Të zbulosh gabimet që ndodhin në kod është një process jo i lehtë pasi ka kosto.Sic
është përcaktuar edhe në këtë tezë diplome ka lloje te ndryshme gabimesh të cilët janë
shpeshherë të vështirë për tu dedektuar.Sfida për këtë tezë është shmangia e tyre gjetja e
metodave të cilat mund të eleminojnë këto gabime,pse jo propozimin e ndonjë algoritmi për
menaxhimin e tyre.
Sfidë kuptimplotë është pëfshirja e rrjeteve artificiale domethëne fushë se inteligjencës artificiale
per realizimi e kodeve vetëdetektuese për të realizuar
1. Shmangien e gabimeve
2. Ujen e kompleksitetit
3. Ndarjen e metodave nga njëra tjetra
4. Shmangjen e pjesëve përsëritëse
5. Shmangien hapësirave boshe
Të gjithë elementët e mësipërm rritin kohën e kompilimit gjithsesi kjo mbetet një sfidë për të
ardhmen vazhdimin e ketij projekti sidomos ndërhyrja e inteligjencës artificiale maja e
programimit në ditët e sotme.
Analiza ,implementimi dhe optimizimi gabimeve në kod
64
8 Përfundimet Ky punim konsistoi në dy drejtime kryesore.E para me ane të një analize statike kodet në java
jane vlerësuar duke përdorur metrikat e paracaktuara dhe vlerat e metrikave të ndryshme janë
llogaritur.Nga vlerat e llogaritura të metrikave dmth rrjeshtave të kodit, numrin e gabimeve dhe
kompleksiteti ciklomatik është e qartë që këto metrika përdoren për të parashikuar nivelin e
cilësisë të software-it të zhvilluar duke nxjerrë këto përfundime.
1. Identifikimi dhe përfshirja e gjithë metrikave në studim.Nga ky studim u realizua një
analize e plotë e gjithë metrikave të Sotës dhe Cccc.
2. Krijimi i nënseteve minimale për rritjen e performances, në përgjithësi rritja e numrit të
seteve të testscase-ve rrit kohen e ekzekutimit dhe ul performancën e vet sistemit.
3. Nënseti më i mirë i testcase-ve varion nga programi në program,dmth nuk është e thënë
se nje program me shumë LOC të ketë një mbulim më te madh se një me më pak rreshta
pasi kjo varet nga kushtet atomike të këtij programi.
4. Gabimet në kod nuk duhet të trajtohen gjithmonë njësoj ,dmth jo cdo tip gabimi është i të
njejtës fuqi ka gabime që sduhen neglizhuar pasi mund të sjellin dështime katastrofike.
5. Kompleksiteti cikolomatik përcakton pjese të kodit ku kompleksiteti është më i
madh,kështu më shumë përqëndrim duhet dhënë tek këto pjesët, të cilat janë më të
prirura për gabime. Zgjidhje për të thjeshtuar kompleksitetin është të rishkruhen dhe të
ndahen metodat në disa metoda.
6. Në analizën dinamike të po kodeve të ndërtuara në java u arrit të gjendej numri minimal i
testcase-ve të cilat realizonin mbulimin e kodit edhe pse jo plotësisht mbulimi është i
mundshëm ,kjo në fakt nuk është shumë e vërtetë sepse disa pathe janë të paarritshme, si
pasojë e strukturës logjike të programit.
7. Lidhur me aspektin optimizues të gabimeve në kod është një problem i cili lihet si punë
në vijim qoftë në propozimin e një algoritmi apo qoftë në realizimin e kodeve inteligjente
nëpërmjet përdorimit të inteligjencës artificiale,vetëdetektuese dhe vetë manipuluese
nëpërmjet heqjes se hapësirave, heqjen e pjesëve përsëritëse.
Analiza ,implementimi dhe optimizimi gabimeve në kod
65
Lista e figurave Figura 1 Fazat e zhvillimit të një software .................................................................................................... 7
Figura 2 Modeli Waterfall ............................................................................................................................. 8
Figura 3 Nivelet e testimit ........................................................................................................................... 12
Figura 4 Cikli i jetës së një gabimi në kod .................................................................................................... 19
Figura 5 Drejtimet për të përmirësuar sistemet e gjurmimit të gabimeve në kod ...................................... 24
Figura 6 Parashikimi i gabimeve në kod ...................................................................................................... 25
Figura 7 Struktura e skuadrës ..................................................................................................................... 30
Figura 8 Grafiku i kurbës së Lorenz ............................................................................................................. 31
Figura 9 Paraqitja grafike e SOTA ............................................................................................................... 32
Figura 10 Matësit e analizës statike ............................................................................................................ 33
Figura 11 Matësit e analizës dinamike ........................................................................................................ 33
Figura 12 Zip file-i i SOTA ............................................................................................................................ 35
Figura 13 Ndërfaqja e SOTA-ës ................................................................................................................... 35
Figura 14 Menuaja pas instalimit të CCCC .................................................................................................. 36
Figura 15 Dritarja e instalimit të CCCC nëpermjet cmd ............................................................................... 37
Figura 16 Treguesi që dritarja është e gatshme për përdorim ................................................................... 37
Figura 17 Paraqitja grafike pas ekzekurimit të testit FECC ......................................................................... 41
Figura 18 Paraqitja grafike pas ekzekutimit të test case-ve të 5 parametrave të para .............................. 43
Figura 19 Paraqitja grafike pas ekzekutimit të testit e MCDC .................................................................... 44
Figura 20 Paraqitja grafike e pas ekzekutimit të testit C3 .......................................................................... 45
Figura 21.Paraqitja grafike pas anlizes se testit MBI dhe BI ..................................................................... 46
Figura 22 Vlerat e metrikave të llogaritura nga CCCC ................................................................................ 49
Figura 23 Vlerat e metrikave të llogaritura nga SOTA ................................................................................ 49
Figura 24 Vlerat e metrikave të llogaritura nga CCCC ................................................................................ 52
Figura 25 Vlerat e metrikave të llogaritura nga SOTA ................................................................................ 53
Analiza ,implementimi dhe optimizimi gabimeve në kod
66
Lista e tabelave Tabela 1 Krahasimi i metodave të testimit ................................................................................................. 14
Tabela 2 Matjet absolute dhe relative duke përdorur Code Churn ............................................................. 26
Tabela 3 Metrikat e CCCC më të pëdorura ............................................................................................... 37
Tabela 4 Tabela e rezultateve ..................................................................................................................... 47
Analiza ,implementimi dhe optimizimi gabimeve në kod
67
Shtojca 1 Kodi burim i përdorur për realizimin e implementimit.
public class DateParser {
/**
* Parses the given string and tries to extract the date.
*
* @param dateString
* date string in the format 'yyyy.mm.dd'.
* @return
*/
public static Date parseDate(String dateString) {
int year = 0;
int month = 0;
int day = 0;
String whereAmI = "year";
boolean errorFree = true;
int index = 1;
while((index <= dateString.length()) & errorFree) {
String chr = dateString.substring(index - 1, index);
if (chr.matches("[0-9]")) {
if(whereAmI.equals("year")) {
year = year * 10 + Integer.parseInt(chr);
} else if(whereAmI.equals("month")) {
month = month * 10 + Integer.parseInt(chr);
} else {
day = day * 10 + Integer.parseInt(chr);
}
} else if (chr.equals(".") & whereAmI.equals("year")) {
if(year < 0 | index == 1) {
errorFree = false;
}
whereAmI = "month";
} else if (chr.equals(".") & whereAmI.equals("month")) {
if(month < 1 | month > 12) {
errorFree = false;
}
whereAmI = "day";
} else {
errorFree = false;
}
index++;
}
if(!errorFree | day < 1 | day > 31) {
return null;
} else {
return new Date(year, month, day);
}
}
} /** Simple Date class for simple output of dates. */
public class Date {
private int year;
private int month;
private int day;
Analiza ,implementimi dhe optimizimi gabimeve në kod
68
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
@Override
public String toString() {
String result = new String();
if (year < 10) {
result += "000" + year;
} else if (year < 100) {
result += "00" + year;
} else if (year < 1000) {
result += "0" + year;
} else {
result += year;
}
if (month < 10) {
result += ".0" + month;
} else {
result += "." + month;
}
if (day < 10) {
result += ".0" + day;
} else {
result += "." + day;
}
return result;
}
}
Analiza ,implementimi dhe optimizimi gabimeve në kod
69
Shtojca 2 Klasa Scanner.java
import java.io.*;
/**
* Simple scanner for lexical analysis of Pas-0 (Simple Pascal)
*
* @author Andreas Kunert
*/
public class Scanner implements TokenConsts {
private char nextChar;
private char currentChar;
private Symbol currentSymbol;
private Symbol lastSymbol; //1//
private InputStreamReader input;
private int line;
private int pos;
private ViewScanner viewScan; //1//
/**
Generates a scanner using as input the InputStreamReader
*/
Scanner(InputStreamReader input) {
try {
viewScan = new ViewScanner(); //1//
line = 1;
pos = 0;
this.input = input;
nextChar = (char) input.read();
currentSymbol = null;
Analiza ,implementimi dhe optimizimi gabimeve në kod
70
}
catch (Exception e) {
Error.ioError();
}
}
/**
Checks whether the input char c is a digit.
*/
private boolean charIsDigit (char c) {
if ((c >= '0') && (c <= '9')) {
return true;
}
else {
return false;
}
}
/**
Checks whether the input char c is a letter.
*/
private boolean charIsAlpha (char c) {
if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) {
return true;
}
else {
return false;
}
}
/**
Analiza ,implementimi dhe optimizimi gabimeve në kod
71
Reads the next character from the input.
*/
private void readNextChar() {
try {
pos++;
currentChar = nextChar;
nextChar = (char) input.read();
viewScan.update(line, pos, currentChar, nextChar, lastSymbol); //1//
}
catch (java.io.IOException e) {
Error.ioError();
}
}
/**
Searches the next symbol, identifies it, and instatiates a
corresponding symbol object to be returned
@see Symbol
@return ideentified symbol as an objcet
*/
public Symbol getSymbol() {
viewScan.update("\nSuche neues Symbol"); //1//
lastSymbol = currentSymbol; //1//
currentSymbol = null;
while (currentSymbol == null) {
readNextChar();
if (charIsAlpha(currentChar)) {
String identifier = (new Character(currentChar)).toString();
viewScan.update("\nStringbau: " + identifier); //1//
Analiza ,implementimi dhe optimizimi gabimeve në kod
72
while (charIsAlpha(nextChar) || charIsDigit(nextChar)) {
viewScan.update(String.valueOf(nextChar)); //1//
identifier = identifier + nextChar;
readNextChar();
}
currentSymbol = handleIdentifier(identifier.toUpperCase());
}
else if (charIsDigit(currentChar)) {
currentSymbol = number();
}
else {
viewScan.update("\nSymbol may consist of two letters"); //1//
switch (currentChar) {
case ' ' :
viewScan.update("\nScip empty character"); //1//
break;
case '\n' : line++; pos=0;
viewScan.update("\nScip end of line"); //1//
break;
case 65535 : currentSymbol = new Symbol(EOP);
viewScan.update("\nEnd of program reached"); //1//
break;
case '{' : comment(); break;
case ':' : if (nextChar == '=') {
readNextChar();
currentSymbol = new Symbol(BECOMES);
}
else {
Analiza ,implementimi dhe optimizimi gabimeve në kod
73
currentSymbol = new Symbol(COLON);
}
break;
case '<' : if (nextChar == '=') {
readNextChar();
currentSymbol = new Symbol(LEQSY);
}
else if (nextChar == '>') {
readNextChar();
currentSymbol = new Symbol(NEQSY);
}
else {
currentSymbol = new Symbol(LSSSY);
}
break;
case '>' : if (nextChar == '=') {
readNextChar();
currentSymbol = new Symbol(GEQSY);
}
else {
currentSymbol = new Symbol(GRTSY);
}
break;
case '.' : currentSymbol = new Symbol(PERIOD); break;
case '(' : currentSymbol = new Symbol(LPARENT); break;
case ',' : currentSymbol = new Symbol(COMMA); break;
case '*' : currentSymbol = new Symbol(TIMES); break;
case '/' : currentSymbol = new Symbol(SLASH); break;
Analiza ,implementimi dhe optimizimi gabimeve në kod
74
case '+' : currentSymbol = new Symbol(PLUS); break;
case '-' : currentSymbol = new Symbol(MINUS); break;
case '=' : currentSymbol = new Symbol(EQLSY); break;
case ')' : currentSymbol = new Symbol(RPARENT); break;
case ';' : currentSymbol = new Symbol(SEMICOLON); break;
default : if (currentChar > ' ') Error.error(100,line,pos);
else viewScan.update("\nUeberlese Steuerzeichen"); //1//
}
}
}
viewScan.update(currentSymbol); //1//
return currentSymbol;
}
/**Tries to identify in the given String a keyword.
If it is a keyword, the corresponding object will be returned.
Otherwise, the returned object represents an Identifier covering its name.
@see Symbol
@see SymbolIdent
@return if Keyword found, return it, otherwise SymbolIdent
*/
private Symbol handleIdentifier(String identifier) {
if (identifier == "AND") return new Symbol(ANDSY);
else if (identifier.compareTo("DIV" ) == 0) return new Symbol(DIVSY);
else if (identifier.compareTo("OR" ) == 0) return new Symbol(ORSY);
else if (identifier.compareTo("NOT" ) == 0) return new Symbol(NOTSY);
else if (identifier.compareTo("CONST" ) == 0) return new Symbol(CONSTSY);
else if (identifier.compareTo("TYPE" ) == 0) return new Symbol(TYPESY);
else if (identifier.compareTo("VAR" ) == 0) return new Symbol(VARSY);
Analiza ,implementimi dhe optimizimi gabimeve në kod
75
else if (identifier.compareTo("TO" ) == 0) return new Symbol(TOSY);
else if (identifier.compareTo("PROCEDURE") == 0) return new Symbol(PROCEDURESY);
else if (identifier.compareTo("BEGIN" ) == 0) return new Symbol(BEGINSY);
else if (identifier.compareTo("OF" ) == 0) return new Symbol(OFSY);
else if (identifier.compareTo("IF" ) == 0) return new Symbol(IFSY);
else if (identifier.compareTo("THEN" ) == 0) return new Symbol(THENSY);
else if (identifier.compareTo("ELSE" ) == 0) return new Symbol(ELSESY);
else if (identifier.compareTo("WHILE" ) == 0) return new Symbol(WHILESY);
else if (identifier.compareTo("DO" ) == 0) return new Symbol(DOSY);
else if (identifier.compareTo("FOR" ) == 0) return new Symbol(FORSY);
else if (identifier.compareTo("END" ) == 0) return new Symbol(ENDSY);
else if (identifier.compareTo("PROGRAM" ) == 0) return new Symbol(PROGRAMSY);
else return new SymbolIdent(identifier);
}
/** Tries to identify a number: either as an integer or as a floating point number
@see SymbolIntcon
@see SymbolRealcon
@return SymbolIntcon- or SymbolRealcon object
*/
private Symbol number() {
final int maxInt = 2147483647;
final int maxIntDiv10 = maxInt / 10;
final int maxIntMod10 = maxInt % 10;
boolean isInteger = true;
boolean integerTooLong = false;
int integerMantisse;
double realMantisse;
int exponent = 0;
Analiza ,implementimi dhe optimizimi gabimeve në kod
76
int expCounter = -1;
int expSign = 1;
integerMantisse = currentChar - '0';
while (charIsDigit(nextChar) && ((integerMantisse < maxIntDiv10))
|| ((integerMantisse == maxIntDiv10) && ((nextChar - '0') <= maxIntMod10))) {
integerMantisse *= 10;
integerMantisse += nextChar - '0';
readNextChar();
}
realMantisse = integerMantisse;
while (charIsDigit(nextChar)) {
integerTooLong = true;
realMantisse *= 10;
realMantisse += nextChar - '0';
readNextChar();
}
if (nextChar == '.') {
readNextChar();
isInteger = false;
if (!charIsDigit(nextChar)) {
Error.error(101,line,pos);
viewScan.update(101); //1//
}
while (charIsDigit(nextChar)) {
realMantisse += (nextChar - '0') * Math.pow(10, expCounter);
readNextChar();
expCounter--;
}
Analiza ,implementimi dhe optimizimi gabimeve në kod
77
}
if (nextChar == 'E') {
isInteger = false;
readNextChar();
if (nextChar == '-') {
expSign = -1;
readNextChar();
}
if (!charIsDigit(nextChar)) {
Error.error(101,line,pos);
viewScan.update(101); //1//
}
while (charIsDigit(nextChar)) {
exponent *= exponent;
exponent += nextChar - '0';
readNextChar();
}
}
if (isInteger) {
if (integerTooLong) {
Error.error(102,line,pos);
viewScan.update(102); //1//
}
return new SymbolIntcon(integerMantisse);
}
else {
return new SymbolRealcon(realMantisse * Math.pow(10, (expSign * exponent)));
}
Analiza ,implementimi dhe optimizimi gabimeve në kod
78
}
/**scip comments
*/
private void comment() {
viewScan.update("\nUberlese einen Kommentar"); //1//
while (currentChar != '}') {
if (currentChar == 65535) {
Error.error(103,line,pos);
viewScan.update(103); //1//
}
else {
if (currentChar == '\n') {
line++;
pos = 0;
}
readNextChar();
}}
}
/**return current line number @return current line number */
public int getLine() {
return line;
}
/**@return current column number */
public int getPos() {
return pos;
}
/** run a test: it generates a scanner object and reads symbols by means of getsymbol()
*/
Analiza ,implementimi dhe optimizimi gabimeve në kod
79
public static void main(String argv[])
throws java.io.IOException {
Scanner scan;
Symbol c;
if (argv.length == 0) {
scan = new Scanner(new FileReader("test.pas"));
}
else { scan = new Scanner(new FileReader(argv[0]));
}
do {c = scan.getSymbol();
System.out.println(c);
} while (c.getTyp() != EOP);
}}
Klasa Error .java
/**
* This class covers all error messages to be printed by the method "error".
*/
class Error implements TokenConsts {
public static void error(int number, int line, int pos) {
System.err.println("Error " + number + ": line " + line + " pos " + pos);
switch(number) {
// lexical errors
case 100: System.err.println("illegal character"); break;
case 101: System.err.println("error in constant"); break;
case 102: System.err.println("constant out of range"); break;
case 103: System.err.println("open comment at end of file"); break;
// syntactical errors
Analiza ,implementimi dhe optimizimi gabimeve në kod
80
case 106: System.err.println("identifier expected"); break;
case 108: System.err.println("error in block"); break;
case 109: System.err.println("error in expression"); break;
case 110: System.err.println("error in procedure declaration"); break;
case 111: System.err.println("error in type declaration"); break;
case 113: System.err.println("error in formal parameter list"); break;
case 114: System.err.println("error in statement sequence"); break;
// semantical errors (static semantics = context-sensitive syntax)
case 201: System.err.println("identifier not declared"); break;
case 204: System.err.println("identifier declared twice"); break;
case 300: System.err.println("type identifier expected"); break;
case 301: System.err.println("procedure expected"); break;
case 302: System.err.println("variable, parameter or constant expected");
break;
case 303: System.err.println("Boolean constant expected"); break;
case 304: System.err.println("integer constant expected"); break;
case 305: System.err.println("more actual parameters expected"); break;
case 306: System.err.println("too many actual parameters"); break;
case 307: System.err.println("type incompatibility in parameter"); break;
case 308: System.err.println("boolean type expected"); break;
case 309: System.err.println("type incompatibility in assignment"); break;
case 310: System.err.println("type incompatibility"); break;
case 311: System.err.println("integer type expected"); break;
case 312: System.err.println("type incompatibility in expression"); break;
case 313: System.err.println("parameter must be a VAR parameter");
break;
case 314: System.err.println("variable expected"); break;
Analiza ,implementimi dhe optimizimi gabimeve në kod
81
default: System.err.println("Other errors");
}
}
public static void symbolError(int typ, int line, int pos) {
System.err.println("Error 105: line " + line + " pos " + pos);
System.err.println("missing " + tokenNames[typ]);
}
public static void ioError() {
System.err.println("IOException");
}
}
Analiza ,implementimi dhe optimizimi gabimeve në kod
82
Shtojca 3
Rezutatet grafike për analizën statike
Analiza ,implementimi dhe optimizimi gabimeve në kod
83
Analiza ,implementimi dhe optimizimi gabimeve në kod
84
Analiza ,implementimi dhe optimizimi gabimeve në kod
85
Analiza ,implementimi dhe optimizimi gabimeve në kod
86
Analiza ,implementimi dhe optimizimi gabimeve në kod
87
Referencat 1. University of Toronto. Introduction to testing. Toronto : s.n., 2012. 2. Jones, Capers. SOFTWARE DEFECT ORIGINS AND REMOVAL METHODS. 2012. 3. Software defects 2. [Në linjë] [Cituar më: 21 August 2014.] http://sgraham745.net/. 4. Software Testing Tutorial. [Në linjë] [Cituar më: 21 August 2014.]
http://actoolkit.unprme.org/wp-content/resourcepdf/software_testing.pdf. 5. Software Testing. [Në linjë]
www.careervarsity.com/careertools/SOFTWARETESTING.ppt. 6. Software Testing. [Në linjë] [Cituar më: 21 August 2014.]
www.ecs.csun.edu/~rlingard/COMP595VAV/SoftwareTesting.ppt. 7. Gao, Jerry. Introduction to Software Testing. [Në linjë] [Cituar më: 20 July 2014.]
http://www.engr.sjsu.edu/gaojerry. 8. BUG PREDICTION APPROACHES – A SURVEY ANALYSIS. N., Ganeshan dhe Gupta,
Varuna. s.l. : VSRD International Journal of Computer Science & Information Technology, 2013.
9. Wagner, Stefan. Defect Classification and Defect Types Revisited. 2008. 10. Software Testing. [Në linjë] 2018. http://softwaretestingfundamentals.com/defect/. 11. [Në linjë] 2002. http://www.abeacha.com/NIST_press_release_bugs_cost.htm. 12. Test. [Në linjë] 2013. http://university.utest.com/participation-submitting-reports/. 13. Anderson, Lisa dhe Francis, Brenda. The Bug Life Cycle. s.l. : The Journal of Defense
Software Engineering, 2003. 14. Software Testing Help. [Në linjë] 2013. http://www.softwaretestinghelp.com/bug-life-
cycle/. 15. Oracle. [Në linjë] 2010. [Cituar më: 29 August 2014.]
http://docs.oracle.com/cd/E19205-01/819-5264/afacc/index.html. 16. Computer Science. [Në linjë] [Cituar më: 29 August 2014.]
www.cs.umd.edu/~mvz/mswe609/change.pdf. 17. MIT OpenCourseWare, Massachusetts Institute of Technology. [Në linjë] 2009. [Cituar
më: 29 August 2014.] http://ocw.mit.edu/. 18. Caulfield, William, Jette, Remy dhe Rivera, Joe. https://www.wpi.edu/. Worcester
Polytechnic Institute. [Në linjë] 2012. [Cituar më: 29 August 2014.] https://www.wpi.edu/Pubs/E-project/.../E.../CodeChurnDashboard.pdf.
19. GOTEL, ORLENA dhe FINKELSTEIN, ANTHONY. http://eprints.ucl.ac.uk/. UCL Discovery. [Në linjë] 1995. [Cituar më: 29 August 2014.] eprints.ucl.ac.uk/747/1/2.0_contrib.pd. Testimi dhe parashikimi i gabimeve në kod.
20. Giger, Emanuel. http://www.ifi.uzh.ch/index.html. University of Zurich. [Në linjë] 25 May 2012. [Cituar më: 29 August 2014.] ww.ifi.uzh.ch/seal/teaching/courses/archive/...1/evolution/sw_evo.pdf.
21. Giger, Emanuel, Pinzger, Martin dhe Gall, Harald C. http://swerl.tudelft.nl/. The Software Evolution Research Lab. [Në linjë] 2011. [Cituar më: 10 September 2014.] http://swerl.tudelft.nl/twiki/pub/Main/TechnicalReports/TUD-SERG-2011-018.pdf.
22. Rodriguez, Daniel dhe Harrison, Rachel. http://www.cc.uah.es/. [Në linjë] 2001. http://www.cc.uah.es/drg/b/RodHarRama00.English.pdf.
23. Giger, Emanuel, Pinzger, Martin dhe Gall, Harald C. http://repository.tudelft.nl/. TUDelft. [Në linjë] 21 May 2011. [Cituar më: 29 August 2014.]
Analiza ,implementimi dhe optimizimi gabimeve në kod
88
24. Herzig, Kim, Just, Sascha dhe Zeller, Andreas. It’s Not a Bug, It’s a Feature: How Miscssification Impacts Bug Prediction. San Francisco, CA : ICSE 2013, 2014.
25. Kelly, Mike. [Në linjë] http://searchsoftwarequality.techtarget.com/answer/Software-bugs-errors-and-defects-Whats-the-difference.
26. Mousavi, Mohammad. Software Testing: IntThere are no sources in the current document.roduction. 2008.
27. http://www.quora.com/. Quora. [Në linjë] 2012. [Cituar më: 12 September 2014.] http://www.quora.com/What-is-the-difference-between-a-software-bug-or-defect-and-a-feature-request-improvement-or-enhancement.
28. Kollur, Akhilesh Babu, Gudikandula, Kalpana and K., Tameezuddin. Effective Bug Tracking Systems: Theories and Implementation. s.l. : Journal of Computer Engineering, 2012.
29. https://www2.informatik.hu-.berlin.de/swt/lehre/TestTools/sota/ 30. H. Mcheick, H. Dhiab, M. Dbouk and R. Mcheik, “Detecting Type Errors and Secure
Coding’’ 31. http://dl.acm.org/citation.cfm?id=225405 32. http://dl.acm.org/citation.cfm? 33. Paper: Application of Sampling Methods for statistical toler-ance analysis Andreas
Stockinger Sandro Wartzack 34. http://www.locmetrics.com/alternatives.html 35. P.R.Caseley, and M.J.Hadley, “Assessing the Effectiveness of Static Code Analysis,”
Proceedings of the 1st Institution of Engineering and Technology International Conference on System Safety, pp.227-237, 2006.
36. P. Brereton, B. Kitchenham, D. Budgen, et al., "Lessons from applying the systematic literature review process within the software engineering domain," Journal of Systems and Software, vol. 80 (4), pp. 571-583, 2007.
37. A. Arsanjani, S. Ghosh, A. Allam, et al., "SOMA: A method for developing service-oriented solutions," IBM Systems Journal, vol. 47 (3), pp. 377-396, 2008.
38. Sanjay Singla, Dharminder Kumar, H M Rai and Priti Singla, A Hybrid PSO Approach to Automate Test Data Generation for Data Flow Coverage with Dominance Concepts, International Journal of Advanced Science and Technology, Vol. 37, December, 2011.
39. International Journal of Advanced Research in Computer Science and Software Engineering Research Paper Available online at: www.ijarcsse.com ‘A Review on Optimization Methodologies Used for Randomized Unit Testing’