En sammanställning av komplexitetsmått.



Relevanta dokument
Kodkomplexitet i agil utveckling. Axel Nilsson Svegard, Patrick Fogwall EDA270 - Djupstudie 2 mars 2010

UTMANINGSBASERAT LÄRANDE I FÖRSTA PROGRAMMERINGSKURSEN

Bakgrund och motivation. Definition av algoritmer Beskrivningssätt Algoritmanalys. Algoritmer. Lars Larsson VT Lars Larsson Algoritmer 1

Objektorienterad programmering, allmänt

Viktiga egenskaper hos ett program (Meyer): Objektorienterad programmering, allmänt. Vilka egenskaper vill vi att våra program ska ha?

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 11 Jonas Lindgren, Institutionen för Datavetenskap, LiU

OMTENTAMEN I DATASTRUKTURER OCH ALGORITMER DVG B kl. 08:15-13:15

Tentamen ID1004 Objektorienterad programmering October 29, 2013

Objektorienterad analys och design

PROGRAMMERING. Ämnets syfte. Kurser i ämnet

Spekulativ exekvering i CPU pipelining

Mälardalens högskola

OBJEKTORIENTERAD PROGRAMVARUUTVECKLING. Övningstentamen 1

Tentamen på kursen DA7351, Programmering , kl Malmö högskola Teknik och samhälle. DA7351, Programmering

Optimala koder. Övre gräns för optimala koder. Gränser. Övre gräns för optimala koder, forts.

Tillämpad Programmering (ID1218) :00-13:00

Optimala koder. Det existerar förstås flera koder som har samma kodordsmedellängd. Enklaste fallet är att bara byta 0:or mot 1:or.

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design (DIT953) Niklas Broberg, 2018

Introduktion till programmering med hjälp av Lego Mindstorm

Föreläsningsanteckningar F6

Objekt-orienterad utveckling. Objektorienterad analys och design. Objekt-orienterad programutveckling. Objekt-orienterad analys och design: Litteratur

Objektorienterad programmering

Kodkomplexitet - Hur mäts det? Sara Nilsson D05, Lunds Tekniska Högskola 1 mars 2011

Tentamen i Objektorienterad modellering och design Helsingborg

Föreläsning 5: Dynamisk programmering

Statistik över heltal

Kursplanering Objektorienterad programmering

Beräkning med ord. -hur en dator hanterar perception. Linköpings universitet Artificiell intelligens Erik Claesson

Inledande programmering med C# (1DV402) Introduktion till C#

F5 Selektion och iteration. ID1004 Objektorienterad programmering Fredrik Kilander

Kodanalys med mjukvarumetriker

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Föreläsning 5: Giriga algoritmer. Kruskals och Prims algoritmer

SKOLFS. beslutade den XXX 2017.

Kopiering av objekt i Java

Föreläsning 2 Datastrukturer (DAT037)

Static vs Dynamic binding Polymorfism. Objekt-orienterad programmering och design Alex Gerdes, 2016

public static void mystery(int n) { if (n > 0){ mystery(n-1); System.out.print(n * 4); mystery(n-1); } }

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

OBJEKTORIENTERAD PROGRAMVARUUTVECKLING

Beräkningsvetenskap introduktion. Beräkningsvetenskap I

IT OCH PROGRAMMERING I SKOLAN. Jan Erik Moström Peter Vinnervik

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

F9 - Polymorfism. ID1004 Objektorienterad programmering Fredrik Kilander

Tentamen. 2D4135 vt 2004 Objektorienterad programmering, design och analys med Java Torsdagen den 3 juni 2004 kl

Objektorienterade programmeringsspråk. Objektorienterade språk. Den objekt-orienterade modellen. Jämför med icke-oo

Mer källkod. Styrstrukturer Val Slingor Operatorer Källkodsexempel med minne. Erik Forslin. Rum 1445, plan 4 på Nada

Laboration: Grunderna i MATLAB

Föreläsning 5: Giriga algoritmer. Kruskals och Prims algoritmer

Säkerhetslagrets andel av beställningspunkten som funktion av ledtid

Introduktion till algoritmer - Lektion 4 Matematikgymnasiet, Läsåret Lektion 4

Objektorienterad programmering E. Telefonboken, än en gång. Gränssnitt. Telefonboken med gränssnitt specificerat, del 1.

Beräkningsvetenskap introduktion. Beräkningsvetenskap I

Föreläsning 1: Intro till kursen och programmering

Dagens föreläsning (F15)

Programmering B med Visual C

Skapa en generell informationsmodell?

Objektorienterad programmering Föreläsning 2

TENTAMEN I PROGRAMSPRÅK -- DVG C kl. 08:15-13:15

TDDD92 Artificiell intelligens -- projekt

Introduktion till objektorientering. Vad är objektorientering egentligen? Hur relaterar det till datatyper? Hur relaterar det till verkligheten?

Imperativ programmering. Föreläsning 2

Objektorienterad programmering Föreläsning 8. Copyright Mahmud Al Hakim Agenda (halvdag)

Objektorienterad programmering, analys och design med Java, 5p 2D4135, vt Kursprogram

DAT043 Objektorienterad Programmering

Anujan Balasingam IDA14 NAND flashminnen

Personal. Objektorienterad programmeringsmetodik 5DV133. Kursmål. Kursens uppläggning. Lärare. Handledare och gruppövningar.

Programmering = modellering

Inlämning 3 IKOT Gruppmedlemmar. Marcus Anemo Simon Hall Kristoffer Johnsen Abedin Karalic Lian Hong Zheng. Handledare.

F6 Objektorienterad design. ID1004 Objektorienterad programmering Fredrik Kilander

Tentamen. 2D4135 vt 2005 Objektorienterad programmering, design och analys med Java Lördagen den 28 maj 2005 kl

Projekt i programmering 1 (ver 2)... 2 Projektidé... 2 Planering... 2 Genomförande... 2 Testning och buggar... 3 Utvärdering... 3 Planering...

Objektorienterad analys och design

Föreläsning 4: Giriga algoritmer. Giriga algoritmer

Tentamen Datastrukturer (DAT036)

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Programmering. Seminarier i datavetenskap, datorteknik och informationsteknik. Niklas Broberg niklas.broberg@chalmers.

MMA132: Laboration 2 Matriser i MATLAB

Introduktion. Byggstenar TDBA

Inledande programmering med C# (1DV402) Introduktion till programmering

Introduktion till programmering D0009E. Föreläsning 5: Fruktbara funktioner

Tentamen i Introduktion till programmering

TENTAMEN I DATAVETENSKAP

UML 1(5) Introduktion till Unified Modeling Language. 1 Bakgrund och historik

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor

Precis som var fallet med förra artikeln, Geogebra för de yngre i Nämnaren

TDDI16 Datastrukturer och algoritmer. Algoritmanalys

Inledning. Vad är ett datorprogram, egentligen? Olika språk. Problemlösning och algoritmer. 1DV433 Strukturerad programmering med C Mats Loock

Tentamen, EDA501/EDAA20 Programmering M MD W BK L

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Föreläsning 1: Intro till kursen och programmering

Ingenjörsinriktad yrkesträning

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson

Antennförstärkare för UHF-bandet

Programmering. Seminarier i datavetenskap, datorteknik och informationsteknik. Niklas Broberg

Labb i Datorsystemteknik och programvaruteknik Programmering av kalkylator i Visual Basic

Distribuerade affärssystem

Introduktion till programmering SMD180. Föreläsning 4: Villkor och rekursion

HT1 2013, FÖRELÄSNING 14 (INFÖR TENTAN)

Transkript:

En sammanställning av komplexitetsmått. D08 Lunds Tekniska Högskola Arvid Lindell dt08al6@student.lth.se 28 Februari 2012 Abstrakt Denna artikel diskuterar kodkomplexitetsmått i allmänhet. Några av de vanligaste kodkomplexitetsmåtten förklaras och det tidigare litteratur konstaterat angående dem sammanställs. Några av måtten testkörs mot 10 upplagor av ett studentprojekt gjort av andra årets datateknikstudenter vid LTH och en bedömning av måttens relevans görs.

Innehåll 1 Introduktion 3 2 Bakgrund 3 3 Några olika mått 4 3.1 McCabes cyklomatiska komplexitet................. 4 3.2 Halsteads............................... 5 3.3 Nästlingsdjup............................. 6 3.4 CKMetrics.............................. 6 3.5 Diverse................................ 6 4 Test mot projektkod 7 4.1 Resultat................................ 7 4.2 Slutsats................................ 7 4.2.1 Cyklomatisk komplexitet.................. 7 4.2.2 Nestningsdjup........................ 8 4.2.3 Rader kod........................... 8 5 Måttens korrekthet 8 5.1 Studentprojekten........................... 8 5.2 Andras undersökningar........................ 8 6 Slutord 8 2

1 Introduktion Det har sedan länge funnits ett intresse av att mäta hur komplext ett givet datorprogram är, och därav har det också utvecklats ett flertal olika mått med detta syfte.[1] Egenskaper hos datorprogram så som komplexitet, förståbarhet, utbyggnadsbarhet är ofta subjektiva och svåra att kvantifiera. Komplexitetsmått är ett försök att göra sådana egenskaper mätbara eller åtminstone hitta mätvärden som korrelerar med dem. Syftet med denna artikel är att sammanfatta funktion och resonemang bakom några vanliga sådana mått. Många andra [2][3][1] har tidigare också gjort jämförelser mått emellan Man har försökt utvärdera deras relevans, med varierande resultat. Denna artikel skrivs som en del av kursen Coaching av programvaruteam vid Lunds tekniska högskola som också innefattar studentprojekt gjorda av yngre studenter. Dessa projekt är vad som använts för att testa olika måtts beteende och likhet. Förhoppningen är också att kunna identifiera vad som leder till dåliga resultat för olika mått. Två av de första mer avancerade och mest välkända måtten är Halsteads[7] komplexitetsmått och McCabes cyklomatiska komplexitet[4]. Dessa och några andra kommer att beskrivas i sektion 3. I sektion 2 ges en bakgrund för komplexitetsmått i allmänhet. I sektion 4 testas olika mått på studentprojektens kod med syfte att bedöma måttens rimlighet. Sektion 5 innehåller viss diskussion angående måttens relevans och rimlighet, delvis baserat på resultat av testandet i sektion 4 och delvis på andras undersökningar. 2 Bakgrund Att mäta ett programs komplexitet vill man göra av flera anledningar. Ett programs komplexitet är avgörande för dess kostnad dels under produktion men framför allt under en efterliggande underhållsfas och vid eventuell påbyggnad vid senare tillfälle. [5] Vidare ger en del av existerande mått redan i under designen av ett system viss hjälp att försöka förutsäga hur svårt systemet sedan kommer vara att implementera.[5] Det första och mest grundläggande måttet på komplexitet är rader kod (lines of code, LOC), ett ganska primitivt och simpelt mått. En uppenbar svaghet med detta mått är att det till stor del beror på programspråk och dessutom säger mer om storlek än komplexitet, även om en viss korrelation däremellan finns. Nuförtiden används mer komplicerade mått som tar mer av kodens struktur i hänsyn, och det finns speciella mått för objekt-orienterad programmering. Så vilka egenskaper bör då ett komplexitetsmått ha? Jo, följande[1]: De bör vara robusta på så sätt att små förändringar i ett program ej drastiskt förändrar mätvärdet. Om ett mätvärde minskar på grund av förändring i ett program bör man också kunna visa att programmet faktiskt blivit bättre och tydligare. Ett bra mått bör kunna identifiera källan till komplexiteten. Om en viss del av ett program är betydligt komplexare än resten ska måttet kunna visa detta så att problemet enklare kan åtgärdas. 3

Någon slags standardvärde bör finnas, som talar om vilka intervall som är rimliga och vilka som är för mycket. Utan detta kan ett program ej bedömas utan att jämföra det med andra. I [6] definierar Weyuker några mer generella egenskaper som mått bör ha. Hon presenterar dem i en slags stigande ordning av viktighet. De första egenskaperna är nödvändiga för att ett mått alls skall vara meningsfull och de senare är mer detaljerade. Exempelvis är den första egenskap hon presenterar: ( P )( Q)( P Q ) (1) P och Q är här program, eller stycken programkod. Egenskapen säger att det bör finnas program P och Q som ej har samma mätvärde. Uppenbarligen är ett mått som ger samma värde till alla program inte meningsfull. Weyuker fortsätter med att konstatera att ett mått bör bero på implementationen och inte på problemet som löses. Två program som beräknar samma sak har alltså ej nödvändigtvis samma mätvärde. Hon anser också att en sammanslagning av två kodstycken bör ha ett högre mätvärde är de enskilda kodstyckenas värden, enligt följande egenskap: ( P )( Q)( P P ; Q ) & ( Q P ; Q ) (2) Hon noterar att Halsteads ansträngnings-mått E ej har denna egenskap (Se 3.2). I sin slutsats konstaterar Weyuker att det i huvudsak finns två olika sätt att konstruera ett mått. Antingen ser man komplexiteten hos ett stort program som summan av komplexiteten för delarna, eller så undersöker man hur de olika delarna interagerar med varandra. 3 Några olika mått 3.1 McCabes cyklomatiska komplexitet McCabes cyklomatiska komplexitet utgår från ett programs kontrollflödesgraf och mäter hur många olika vägval exekveringen kan göra. En kontrollflödesgraf är en riktad graf och består av noder motsvarande olika sammanhängande stycken kod, och kanter motsvarande exekveringsvägar emellan dessa. Exempelvis kan programkoden i figur 1 översättas till grafen i figur 2. do { if (y) { A; } else { B; } } while (x); Figur 1: Simpelt kodexempel 4

Figur 2: Kontrollflödesgrafen för koden i figur 1 Den cyklomatiska komplexiteten V i en sådan graf G med n noder och e kanter definieras sedan som: V (G) = e n + 2 (3) Koden i figur 1 har då alltså komplexiteten 3. Ju lägre värde desto enklare kod, McCabe själv gör bedömningen att 10 är en lämplig övre gräns.[4] Värdet kan också räknas ut genom att helt enkelt räkna antalet if- loop- och liknande uttryck som finns i koden och addera 1. Helt rak kod ger följaktligen värdet 1 En modifikation av originaldefinitionen som många väljer att använda är att se switch-caseliknande strukturer som ett enda val. 3.2 Halsteads Halsteads mått är i själva verket ett par stycken olika; volym, svårighet och ansträngning.[7][1] Beräkningarna använder följande parametrar: n 1 antalet unika operatorer. n 2 antalet unika operander. N 1 det totala antalet operatorer. N 2 det totala antalet operander. Med hjälp av dessa definieras sedan ett programs volym V som: och svårighet D som: V = (N 1 + N 2 ) log 2 (n 1 + n 2 ) (4) D = (n 1 N 2 ) (2 n 2 ) Ansträngningen E för att implementera ett sådant program uppskattas sedan till: (5) E = D V (6) 5

Som nämdes i sektion 2 har måttet en svaghet i att en utökning av ett program teoretiskt kan minska mätvärdet E. Om man tänker sig en utökning som ökar antalet unika operander mycket men som bara använder dem en gång var så kan värdet på n 2 tänkas dubblas, medan N 2 endast ökar marginellt jämfört med dess gamla värde. På så sätt minskar värdet D vilket i vissa fall också leder till att hela E minskar. 3.3 Nästlingsdjup Piwowarski föreslår i [8] att komplexitetsmått även bör ta hänsyn till hur djupt nästlade uttryck i programmet är. En loop inuti en annan anses mer komplext än två loopar som följer efter varandra. McCabes cyklomatiska komplexitet tar ej hänsyn till detta utan dessa båda fall får samma värde. Piwowarski föreslår därför en utökning av måttet så att även tar hänsyn till hur denna struktur ser ut. N = V (G) + i P (i) (7) Där V (G) är den cyklomatiska komplexitet med switch-casesatser räknade som ett val, och där P (i) är nästlingsdjupet för ett uttryck i i programmet. 3.4 CKMetrics Chidamber och Kemerer beskriver i [9] en uppsättning mått specifikt utvecklade för objektorienterad programmering, som diskuterats vidare av andra [10][3]. De mått de kom fram till behövdes var följande: Metoder per klass. Arvsträds-djup. Exempelvis i javas fall hur många arvs-steg från Object. Antal barn, alltså klasser som ärver från en viss klass. Sammankoppling mellan klasser. C & K definierar sammankoppling som att en klass använder objekt av, eller kallar metoder på, en annan klass. En klass svar, vilket är mängden av alla metoder som kan tänkas kallas vidare när någon metod på klassen i sig kallas. 3.5 Diverse Några andra vanliga enklare mått: Antal parametrar till funktioner. Rader kod. Antal metoder per klass. Rader kod per metod / funktion. Dessa är ganska självklara och lätta att mäta och för alla gäller att ett mindre värde representerar ett mindre komplext program. 6

4 Test mot projektkod 4.1 Resultat För enkelhetens skull har vi valt ut ett fåtal mått att beräkna på de studentprojekt som finns att tillgå, specifikt nestningsdjup, cyklomatisk komplexitet per metod, och rader kod. Det finns 10 stycken olika projekt som ska ha ungefär samma funktionalitet och bör vara rimligt jämförbara. Måtten är framtagna med hjälp av en plugin till utvecklingsmiljön Eclipse som heter just Metrics. 1 TeamNr Nestningsdjup Cyklomatisk kompl. Rader kod 1 1,34 (max: 5) 1,57 (max: 10) 2179 2 1,59 (max: 5) 1,91 (max: 16) 1498 3 1,34 (max: 6) 1,61 (max: 9) 1718 4 1,44 (max: 5) 1,59 (max: 11) 1961 5 1,33(max: 4) 1,63(max: 10) 1670 6 1,21(max: 5) 1,41(max: 13) 1669 7 1,51(max: 4) 2,00(max: 14) 1356 8 1,49(max: 7) 1,68(max: 14) 1567 9 1,36(max: 4) 1,68(max: 14) 1567 10 1,36(max: 5) 1,62(max: 9) 1577 Figur 3: Mätvärden från studentprojekten Cyklomatisk komplexitet har som tidigare nämnt ett rekomenderat maxvärde på 10. Värt att nämna är att alla projekten har en sak gemensamt angående deras cyklomatiska komplexitet. De har alla en enda eller maximalt två olika metoder som har drastiskt mycket högre komplexitet än alla andra i programmet. Projekt 2 exempelvis har sitt maxvärde 16, men alla andra metoder utom denna har 7 eller mindre. Övriga projekt har liknande situationer. Ytterligare något att nämna är att i 6 av 10 projekt var den metod med högst cyklomatisk komplexitet också den metod med flest rader kod. 4.2 Slutsats 4.2.1 Cyklomatisk komplexitet Efter att ha undersökt koden närmre handlar nästan alla fall av förhöjd komplexitet om någon typ av stränghantering. Projektet handlar om att samla in tid-data i textformat om förare i ett motorcykel-race och sammanställa denna som ett resultat, även detta i textformat. Det får därför anses förståeligt om än ej optimalt att det ser ut som det gör. En potentiell lösning hade varit att refaktorisera koden och införa några stycken mindre hjälpmetoder som då ansvarar för olika mindre moment av parsningen. Detta visar också att det viktigaste att titta på när det gäller måttet cyklomatisk komplexitet är maxvärdena och till mindre grad medelvärdena. Medelvärdena varierar från 1,41 till 2,00 medan maxvärdena spänner över intervallet 9 till 16. Tio små studentprojekt är förvisso inget stort sampel men det är vad som här fanns att tillgå och visar måttens möjligheter. 1 Finns att hämta på http://metrics.sourceforge.net/ 7

4.2.2 Nestningsdjup Måttet nestningsdjup är inte fullt så spännande i detta resultat, dels varierar det mindre och dels är det färre ställen där det rekomenderade maxvärdet 5 överstigs. En majoritet av projekten har ej sin djupaste nestning i samma metod som deras högsta cyklomatisak komplexitet uppmätts så man kan konstatera att de två ej nödvändigtvis följs åt. 4.2.3 Rader kod Måttet rader kod togs med i hopp om att se ett samband mellan programmens storlek och deras övriga komplexitetsmått. Någon sådan går ej att finna i denna undersöknings data. Däremot, som nämnt i 4.1 så finns ett samband på metodnivå. 5 Måttens korrekthet 5.1 Studentprojekten För att undersöka hur bra komplexitetsmåtten fungerar ombads alla studenter involverade i projekten att identifiera de tre metoder i sitt eget projekt som de tyckte var minst överskådliga och rörigast. Tanken är att se hur bra måttens bedömning stämmer överens med den verkliga svårighetsgraden av att förstå koden. Tyvärr, på grund av bristfällig svarsfrekvens bland de tillfrågade så finns det inte så mycket data. Baserat på de svar som inkommit och viss diskution med enskilda studenter så anser vi dock att måtten fungerar dugligt. De metoder som komplexitetsmåtten identifierar som onödigt komplexa bedömes också vara det av människor. Det finns dock fler metoder som de tillfrågade anser komplexa som måtten ej lyckas identifiera. 5.2 Andras undersökningar Gordon utför i [11] en uppsättning experiment med Halsteads mått E av ansträngning. Han underesöker hur måttet påverkas av att ett program följer erkända best-practices såsom att undvika goto, ej ha för djupa loop-nästningar etc. Hans resultat visar att i majoriteten av fall så blir måttet bättre samtidigt som programkoden också blir lättare att förstå. Han hittar ett fåtal undantag men överlag fungerar måttet väl. 6 Slutord Behovet att objektivt mäta kod-kvalitet och komplexitet är en effekt av att programmering är komplicerat i sig. Med de mått som presenterats här kan man åtminstone någorlunda bedöma komplexitet, och framför allt identifiera källorna till denna. Måtten är på inga sätt felfria och det finns situationer där man bör ta dem med en nypa salt. Även om låga komplexitetsmått inte är en garanti för ett välorganiserat program så är höga värden ett tecken på att man bör undersöka källan till dessa närmre. Det är framför allt i att identifiera brister som måtten kommer till sin rätt. Baserat på den undersökning som gjorts 8

här ser man att måtten ej hittar alla brister i ett program, men de saker som identifieras som brister är i allmänhet det. Olika mått har olika strategier och fokus, och för en komplett bild bör man kombinera flera olika varianter. Acknowledgements Tack till Johan Wennersten för genomläsning och hjälp med formatering. 9

Referenser [1] J. P. Kearney, R. L. Sedlmeyer, W. B. Thompson, M. A. Gray, and M. A. Adler, Software complexity measurement, Commun. ACM, vol. 29, pp. 1044 1050, November 1986. [2] S. Henry, D. Kafura, and K. Harris, On the relationships among three software metrics, SIGMETRICS Perform. Eval. Rev., vol. 10, pp. 81 88, January 1981. [3] R. Subramanyam and M. Krishnan, Empirical analysis of ck metrics for object-oriented design complexity: implications for software defects, IEEE Transactions on Software Engineering, vol. 29, pp. 297 310, april 2003. [4] T. McCabe, A complexity measure, IEEE Transactions on Software Engineering, vol. SE-2, pp. 308 320, dec. 1976. [5] M. Rafighi and N. Modiri, Framework of software complexity methodology, in Networked Computing and Advanced Information Management (NCM), 2011 7th International Conference on, pp. 41 44, june 2011. [6] E. Weyuker, Evaluating software complexity measures, IEEE Transactions on Software Engineering, vol. 14, pp. 1357 1365, sep 1988. [7] M. H. Halstead, Elements of Software Science (Operating and programming systems series). New York, NY, USA: Elsevier Science Inc., 1977. [8] P. Piwowarski, A nesting level complexity measure, SIGPLAN Not., vol. 17, pp. 44 50, September 1982. [9] S. Chidamber and C. Kemerer, A metrics suite for object oriented design, IEEE Transactions on Software Engineering, vol. 20, pp. 476 493, jun 1994. [10] V. Basili, L. Briand, and W. Melo, A validation of object-oriented design metrics as quality indicators, IEEE Transactions on Software Engineering, vol. 22, pp. 751 761, oct 1996. [11] R. Gordon, Measuring improvements in program clarity, IEEE Transactions on Software Engineering, vol. SE-5, pp. 79 90, march 1979. 10