EDA270 - Coaching av programvaruteam Verktyg för kodanalys Petter Berglund D05, Lunds Tekniska Högskola dt05pb2@student.lth.se 2008-02-10 Sammanfattning Verktyg för kodanalys blir allt vanligare i programvaruutvecklingsprojekt för att underlätta utvecklingsprocessen och öka kodkvalité. Denna artikel ämnar introducera ett antal verktyg för kodanalys av Java-kod. Artikeln kommer introducera metoder för kodanalys och verktygen PMD, SemmleCode, FindBugs och RevJava.
Introduktion Moderna programvaruutvecklingsprojekt har ständiga krav på sig om hög funktionalitet, stabilitet, effektivitet och kort utvecklingstid. Att skriva programvara utgående ifrån dessa krav är problematiskt då de indirekt eller direkt påverkar varandra. För att lägga till ny funktionaliteten i ett program krävs det en utökad kodbas, vilket i många fall leder till både försämrad stabilitet och effektivtet. Kort utvecklingstid ger mindre tid för att testning vilket kan leda till att allvarliga buggar inte upptäckas och lanseras med en färdig produkt. Kort sagt, det finns många anledningar till att det är svårt att skriva programvara med dagens höga krav. Ett sätt att effektivisera en utvecklingsprocess är genom verktyg som analyserar kod automatiskt. Verktyg underlättar genom att en delmängd av testning och analys av programvara kan automatiseras, vilket leder till att mer resurser kan spenderas på själva utvecklingsprocessen. Kodanalys kan utföras i många varianter, men gemensama nämnare är att problem ska kunna identifieras, kodkvalité och stabilitet förbättras. Då verktyg för kodanalys finns för i princip alla programmeringsspråk är denna artikel begränsad till verktyg som analyserar Java-kod. Verktygen kommer att introduceras och utvärderas utgående ifrån deras lämplighet i programvaruutveckling. Metoder för kodanalys Kodanalys kan göras utifrån två differentierande metodiker, statisk och dynamisk analys [5]. Verktygen som introduceras i artikeln använder statisk kodanalys men dynamisk analys kommer presenteras likaväl. Att verktyg som utför dynamisk analys inte introduceras beror på att det krävs mer förberedelser i form av relevanta körningar för att kunna utvärdera verktygen. Statisk kodanalys Statisk kodanalys är inte en enskild metod för kodanalys utan en benämning på alla former av automatiserad analys som sker på källkod. Analyserna kan ske på enskilda metodanrop upp till hela program beroende på vilket verktyg som används. Metoder som utnyttjas för statisk kodanalys är samtliga matematiskt betingade. Analyser utförs genom att approximera matematiska funktioner som representar programmet i något tillstånd. I många fall kan dessa matematiska approximationer imitera ett program väldigt nära vilket medför att utvärderingar av de matematiska approximationerna återspeglas på programmet. Vid statisk kodanalys är det vanligt förekommande att precision i modellen abstraheras bort genom att ersätta faktiska värden med symboliska värden, detta för att förenkla beräkningar. Statisk kodanalys används aktivt inom analys av säkerhetskritiska program just på grund av dess matematiska grund. Dynamisk kodanalys Dynamisk kodanalys kan ses som en motsats till statisk kodanalys, då dynamisk kodanalys exekverar programmet som ska analyseras och utvärderar det under exekveringen.
Dynamisk kodanalys utförs genom att programmet som ska analyseras exekveras i en virtuell exekveringsmiljö eller via specialla bibliotek som sonderar programmet så att dess exekvering kan följas i dess ordinare exekveringsmiljö. För att dynamisk kodanalys ska vara effektiv krävs det att en stor mängd av koden täcks av tester så att man på förhand vet att programmets samtliga exekveringsmöjligheter kommer att exekveras. Dynamisk kodanalys lämpar sig väl för att upptäcka exekveringsfel som minnesläckor och problem orsakade av samtida exekvering (concurrent execution). Verktygsintroduktion Verktygen som undersöks är alla utvecklade för kodanalys men har olika mål och metoder. Kod kan analyseras utifrån källkod, bytekod, mätvärden (metrics) och regelverk. För att jämförelser mellan verktygen ska vara relevanta kommer varje verktygs mål och metod att presenteras kortfattat. PMD är ett verktyg utvecklat för statisk kodanalys av källkod, släppt under en licens som bygger på Berkeley Software Distribution (BSD) licensen. Källkoden som skall analyseras kommer att passera en tolk som översätter koden till ett Abstrakt Syntax Träd (AST). Ett AST representerar det tolkade programmets struktur på ett sätt som utelämnar syntaktiska detaljer [4]. Analysen sker genom att en uppsättning regler skrivna i ett specifikt språk översätts till matchningar som får traversera trädet. Om reglerna matchas mot någon av trädets noder representerar detta ett regelbrott vilket kommer rapporteras. PMD tillhandahåller en stor mängd fördefinerade regler och stödjer utveckling av egna regler. PMD har utvecklats för att upptäcka enklare fel i kod som oanvänd kod, for-loopar som borde vara while-loopar, felaktigt användande av StringBuffer och liknande fel. RevJava utför statisk kodanalys på bytekod och kan därför utföras på program där källkoden inte är tillgänglig. Programmet är släppt under en proprietär licens. RevJava har utvecklats för kunna automatiskt ta fram en stor mängd mätvärden för ett programs interna struktur och för att kunna utgående ifrån olika regelverk skapa kritiska kommentarer (critics) om potentiella svagheter i koden. Grundutbudet på regler är stort men går att utökas genom egen utvecklade regler för att kunna anpassas till speciella projekt [2]. SemmleCode är ett verktyg för statisk kodanalys utifrån olika regelverk. Semmlecode är kommersiellt men tillhandahåller en gratis proprietär version som plugin till Eclipse. Reglerna avviker lite från PMD och RevJava i den mån att de är uppbyggda som frågor som ställs till Java-kod. Beroende på frågans uppbyggnad kan mätvärden genereras, buggar lokaliseras, avvikelser från kodningsstandarder identifieras och förändringar i kod kan analyseras utifrån dess påverkan på koden [6]. FindBugs är ett verktyg för att finna mönster i kod som kan orsaka problem via statisk kodanalys. Fundbugs är släppt under Lesser General Public License (LGPL) [7]. Analysen utförs på bytekod utgående ifrån regelverk som refereras till som bugg mönster. FindBugs stödjer ett stort regelverk som standard men kan även utökas ytterligare via en plugin-arkitektur [3]. Utvärdering Samtliga verktyg kommer att utvärderas mot Team 02s enduro-projekt från kursen Programvaruutveckling i grupp EDA260. Projektets tillstånd i korta ordalag vid
utvärderingen är följande: Antal tester: 45 Antal varningar i eclipse (Av typen oanvända import, oanvända variablar etc.): 47 Antal paket: 5 Antal klasser: 17 PMD PMD kan utnyttjas som ett fristående verktyg eller enkelt integreras med olika utvecklingsmiljöer, i detta fallet har PMD utvärderats som ett plugin till Eclipse. När PMD är installerat som plugin till Eclipse kan det utnyttjas på två olika sätt, antingen genom manuellt användande, eller genom att integereras med Eclipses problem-flik. Om PMD integreras med Eclipses problem-flik körs PMD automatiskt vid kodändringar. Figur 1: Visar ett utdrag ur PMDs rapport och en översikt av rapporterade regelbrott. Resultatet från PMD visar att koden innehåller totalt 106 regelbrott varav de tidigare 47 regelbrotten Eclipse rapporterar är exkluderade. Som översikten visar kan mycket av regelbrotten spåras till testfallen, detta antyder att mindre tid spenderas på att korrigera problem med testfallen. Regelbrotten som rapporteras är alla av olika karaktär, en del av de upptäcka regelbrotten är brott mot kodningskonventioner som anses vara bra att följa. Regelbrott nummer två i rapporten uttrycker att variabelnamn inte bör vara för korta t ex. Andra regelbrott pekar på möjliga optimeringar, variablar som kan deklareras som final då de endast initialiseras i konstruktor eller vid deklarering.
Fördelar PMD lämpar sig mycket väl för att upptäcka mindre optimeringar, avvikelser från kodkonvetioner och s.k. "Code smells" i ett projekt speciellt då PMD körs integrerat med Eclipses problem-flik. Det stora utbudet av färdigskrivna regler gör verktyget enkelt att använda utan egna modifikationer, medans stödet för egna regler utökar användningsområdena. Nackdelar Trots att det är en stor fördel med färdigskrivna regler kan dessa vara problematiska då konfigureringsgränssnitt inte är helt självklart, det kräver vissa insatser av användaren för att utesluta vissa regler. PMD saknar möjlighet att förklara ett regelbrott utifrån den regeln som brutits, dv s det lämnas till användaren att tolka eller slå upp i regelverket vilket fel detta motsvarar. RevJava RevJava körs som ett fristående javaprogram och konfigureras enkelt via ett grafiskt gränssnitt. Eftersom RevJava analyserar bytekod kommer projektets release i jar-form analyseras. Figur 2: Statisk från RevJavas analys Figur 2 visar den sammanfattande statistiken från RevJavas analys, totalt 210 insamlade kritiska kommentarer gällande projektet. Statistiken ger en snabb översikt över på vilken nivå problem eventuellt befinner sig, i projektet gäller nästan 60% av alla kommenterar enskilda metoder. RevJavas vy över programstruktur ger en översikt över programmets struktur och information om varje pakets kritik och mätvärden.
Figur 3: RevJavas vy över programstrukturen för projektet innehåller stora mängder information presenterad i en välstrukturerad lista I figur 3 visas information om kritik och mätvärden paket- och klassvis. För att det inte ska vara några tveksamheter kring vad man studerar, är varje nivå kodad med bokstäver. P Paket C V M Klass Variabel Metod
Figur 4: RevJavas vy över mätvärden Kritiken som RevJava producerar är välformulerad, ett måste för att åtgärder ska vara möjliga. I vissa fall framgår det tydligt av detaljbeskrivningen hur problem kan lösas. Fördelar RevJavas mätvärden som produceras är intressanta för att identifiera svagheter i arkitekturen, stora klasser, många beroenden eller dylika designproblem kan lätt upptäckas. RevJava lämpar sig väl för att användas i samband med utvärdering av milstenar eller löpande under utvecklingsprocessen. Eftersom RevJava utför analysen på bytekod behöver en utvärderare inte ha tillgång till källkoden och kan utgående ifrån upptäckt kritik och mätvärden granska programmets struktur. Detta kan utnyttjas i samband med acceptanstestning, då programvaran kan analyseras med RevJava för att upptäcka eventuella svagheter eller framtida problem i designen. RevJava kan utnyttjas för att se hur refaktoreringar påverkar kodens struktur genom att jämföra mätvärden innan och efter. Nackdelar Ett problem med RevJava är att information presenteras för användaren på ett sätt som gör den svårtolkad. Många utav vyerna innehåller stora mängder information som gör det svårt att få en bra uppfattning om vad det är som studeras, mer specifika vyer tappar viktig information. RevJava kräver att koden kompileras för att kunna utnyttjas och kan inte integreras mot te x Eclipse vilket försvårar kontinuerlig användning.
SemmleCode SemmleCode är utvecklat för att användas i Eclipse som ett plugin. En stor skillnad gentemot PMD och RevJava som analyserar koden utifrån en stor mängd krav kan SemmleCode begränsas till att ställa en fråga i taget. I Eclipse kan SemmleCode utnyttjas på olika sätt, men ett utav de bekvämare tillvägagångsätten är att utnyttja Eclipses "Run"-meny och välja att köra SemmleCode. Grundutbudet på frågor är stort och kan fördelaktigt utnyttjas utan att kompletteras med egna. Figur 5: Ett exempel på en testkonfiguration för SemmleCode och resultatet från en fråga gällande medelantalet metoder per paket. Fördelar SemmleCode stödjer många typer av presentationer av resultat, allt ifrån grafer till trädvyer vilket ger ett snyggt resultat. I jämförelse mot andra verktyg är SemmleCode mycket mer anpassningsbart då det är så gott som utvecklat för att användas med egna frågor, men begränsas av att generell kodanalys kräver stora insatser av användaren. SemmleCode lämpar sig väl för att identifera specifika problemområden, men kan även utnyttjas för att
förutsäga en refaktorerings påverkan på koden i överlag. Te x kan en en fråga genereras för antalet beroenden mellan klasser. Om frågan ställs först innan och sedan efter refaktoreringen införs kan resultatet enkelt jämföras och en eventuellt onödig refaktorering undvikas. Nackdelar Ett problem med SemmleCode är att det är svårt att ställa flera frågor och få ett övergripligt resultat. Problemet beror mycket på att varje enskild fråga presenteras i en enskild flik. För en delmängd av frågorna kan resultatet presenteras i Eclipses problem-flik som varningar, vilket underlättar hantering. I jämförelse mot de andra verktygen är Semmlecode svårare att använda då det kräver mer insatser från användaren. FindBugs FindBugs finns i tre utförande, ett kommandoradbaserat, ett som Eclipse plugin och ett med grafiskt gränssnitt. Eftersom alla varianter är likvärdiga kommer FindBugs som plugin till Eclipse att utvärderas. FindBugs kan integreras med Eclipses problem-flik och presenterar där upptäckta problem likväl som i kodvyn. Problemidentifiering kan automatiseras i samband med att klasser uppdateras, så att informationen till användaren alltid hålls uppdaterad. Figur 6: Eclipses problem-flik med FindBugs problembeskrivning. Vid en problemidentifiering på projektet upptäcks totalt 182 problem, varav 76 lyfts fram till användaren (inkluderat de 47 initiala varningarna). Att bara 76 lyfts fram till användaren beror på att FindBugs standardinställning gällande problemrapportering försöker filtrera ut allvarliga problem som kräver korrigering. För varje problem som identifieras kan FindBugs visa en problembeskrivning med hänvisning till vart problemet är lokaliserat som Figur 7 visar.
Fördelar FindBugs är ett bra komplement till Eclipses inbyggda problemhanterare och är lättanvänt på grund av integreringen med Eclipses problemflik. Eventuella upptäcka problem markeras med en liten insekt i kodvyn (från engelskans bug, insekt) så utan att konsultera problemvyn kan problem upptäckas direkt. I princip alla problem som upptäcks är utförligt beskrivna vilket resulterar i att det är enkelt att åtgärda problem utan att konsultera någon annan källa. Att FindBugs kan justera gällande vilken nivå problem ska rapporteras på samt vilka problem ska rapporteras gör det användbart i vilket utvecklingsprojekt som helst som kontrollant av kodkvalité. Tack vare ett pluginsystem kan FindBugs dessutom anpassas och utökas med nya problemidentifieringar specifika för projekt. Nackdelar FindBugs är precis som PMD användbart löpande i utvecklingen, men trots att FindBugs har utförligare problembeskrivningar så upptäcker FindBugs mycket färre problem i koden. FindBugs kräver också att koden är kompilerad för att kunna analyseras, större program där kompilering tar längre tid kan medföra att FindBugs blir mindre användbart. Slutsatser Efter att ha utvärderat de fyra verktygen kan det konstateras att resultaten mellan de olika verktygen skiljer sig markant. Trots att verktygen samtliga utför statisk analys är resultaten skiljda, så för att få ett riktigt bra resultat är en kombination önskvärd. PMD och FindBugs som integrerar väl med Eclipse är ett bra komplement till alla Java-projekt, kombinationen av analys på källkod och bytekod ökar chanserna för att problem ska kunna identiferas tidigt i processen. Under utvärderingen användes PMD och FindBugs samtidigt i automatiskt läge, utan några indikationer på problem. SemmleCode skiljer sig från de andra verktygen genom att ha ett mer kraftfullt språk för kodanalys men mycket mer begränsat användningsområde, det lämpar sig mycket väl för att utföra specifika analyser. Ett användningsområde som RevJav och SemmleCode stödjer till skillnad från de övriga verktygen är analys av hur ändringar i koden kommer att påverka programmets helhet, detta kan vara mycket användbart för att få en uppfattning om refaktoreringars omfattning. RevJava lämpar sig väl att användas i acceptanstestning men kan även utan problem användas löpande i utvecklingsprocessen. Utgående ifrån RevJavas mätvärden kan arkitekturmässiga fel upptäckas och åtgärdas tidigt. Referenser [1] Eva van Emden, Leon Moonen: Java Quality Assurance by Detecting Code Smells. Proceedings of the Ninth Working Conference on Reverse Engineering, 2002. [2] Gert Florijn: RevJava Design Critiques and Architectural Conformance Checking for Java Software Software Engineering Research Centre SERC, 2002 [3] David Hovemeyer, William Pugh: Finding Bugs is Easy Dept. of Computer Science, University of Maryland, 2004
[4] Joel Jones: Abstract Syntax Tree Implementation Idioms Department of Computer Science, University of Alabama, 2003 [5] Michael D. Ernst: Static and dynamic analysis: synergy and duality MIT Lab for Computer Science, 2003 [6] Mathieu Verbaere, Elnar Hajiyev, Oege de Moor: Improve Software Quality with SemmleCode Semmle Ltd., Robert Robinson Avenue, Oxford OX4 4GA, United Kingdom, 2007 [7] GNU Lesser General Public License http://www.gnu.org/licenses/lgpl.html - Besökt 2008-02-17