Hur man implementerar en statisk kodanalysator i ett äldre projekt utan att demotivera teamet

Hur man implementerar en statisk kodanalysator i ett äldre projekt utan att demotivera teamet
Det är lätt att prova en statisk kodanalysator. Men för att genomföra det, särskilt i utvecklingen av ett stort gammalt projekt, krävs skicklighet. Om det görs på fel sätt kan analysatorn lägga till arbete, bromsa utvecklingen och demotivera teamet. Låt oss kort prata om hur man korrekt närmar sig integrationen av statisk analys i utvecklingsprocessen och börjar använda den som en del av CI/CD.

Inledning

Nyligen uppmärksammades min publikation "Komma igång med statisk analys utan att överväldiga teamet". Å ena sidan är detta en bra artikel som är värd att bekanta sig med. Å andra sidan tycks det mig att den fortfarande inte ger ett fullständigt svar på hur man smärtfritt implementerar statisk analys i ett projekt med mycket Artikeln säger att du kan acceptera tekniska skulder och bara arbeta med ny kod, men det finns inget svar på vad du ska göra med denna tekniska skuld senare.

Vårt PVS-Studio-team ger sin syn på detta ämne. Låt oss titta på hur problemet med att implementera en statisk kodanalysator uppstår i första hand, hur man kan övervinna detta problem och hur man smärtfritt gradvis eliminerar teknisk skuld.

frågor

Det är vanligtvis inte svårt att starta och se hur en statisk analysator fungerar [1]. Du kan se intressanta fel eller till och med skrämmande potentiella sårbarheter i koden. Man kan till och med fixa något, men då ger många programmerare upp.

Alla statiska analysatorer ger falska positiva resultat. Detta är en egenskap hos den statiska kodanalysmetoden, och ingenting kan göras åt det. I det allmänna fallet är detta ett olösligt problem, vilket bekräftas av Rices teorem [2]. Maskininlärningsalgoritmer hjälper inte heller [3]. Även om en person inte alltid kan se om den eller den koden är fel, så ska du inte förvänta dig detta från programmet :).

Falska positiva är inte ett problem om den statiska analysatorn redan är konfigurerad:

  • Inaktiverade irrelevanta regeluppsättningar;
  • Vissa irrelevanta diagnostik har inaktiverats;
  • Om vi ​​pratar om C eller C++, så markeras makron som innehåller specifika konstruktioner som gör att värdelösa varningar visas på varje plats där sådana makron används;
  • Egna funktioner är markerade som utför åtgärder som liknar systemfunktioner (sin egen analog memcpy eller printf) [4];
  • Falska positiva inaktiveras specifikt med kommentarer;
  • Och så vidare.

I det här fallet kan vi förvänta oss en låg falsk positiv frekvens på cirka 10-15 % [5]. Med andra ord kommer 9 av 10 analysatorvarningar att indikera ett verkligt problem i koden, eller åtminstone "starkt luktande kod". Håller med, det här scenariot är extremt trevligt, och analysatorn är en riktig vän till programmeraren.

Hur man implementerar en statisk kodanalysator i ett äldre projekt utan att demotivera teamet
I verkligheten, i ett stort projekt, blir den initiala bilden en helt annan. Analysatorn utfärdar hundratals eller tusentals varningar för äldre kod. Det är omöjligt att snabbt förstå vilka av dessa varningar som är relevanta och vilka som inte är det. Det är irrationellt att sätta sig ner och börja ta itu med alla dessa varningar, eftersom huvudarbetet i det här fallet kommer att stanna i dagar eller veckor. Vanligtvis har ett lag inte råd med ett sådant scenario. Det kommer också att finnas ett stort antal diffar som förstör förändringshistorien. Och snabb massredigering av så många fragment i koden kommer oundvikligen att resultera i nya stavfel och fel.

Och viktigast av allt, en sådan bedrift i kampen mot varningar är inte meningsfull. Håller med om att eftersom projektet har körts framgångsrikt i många år har de flesta av de kritiska felen i det redan korrigerats. Ja, dessa korrigeringar var mycket dyra, måste felsökas, fick negativ feedback från användare om buggar och så vidare. En statisk analysator skulle hjälpa till att åtgärda många av dessa fel i kodningsstadiet, snabbt och billigt. Men för tillfället, på ett eller annat sätt, har dessa fel åtgärdats, och analysatorn upptäcker huvudsakligen icke-kritiska fel i den gamla koden. Den här koden kanske inte används, den kan användas mycket sällan och ett fel i den kanske inte leder till märkbara konsekvenser. Kanske någonstans är skuggan från knappen i fel färg, men detta stör inte någons användning av produkten.

Självklart är även mindre misstag fortfarande misstag. Och ibland kan ett misstag dölja en verklig sårbarhet. Att ge upp allt och ägna dagar/veckor åt att ta itu med defekter som knappt visar sig ser dock ut som en tveksam idé.

Programmerare tittar, tittar, tittar på alla dessa varningar om den gamla arbetskoden... Och de tänker: vi klarar oss utan statisk analys. Låt oss skriva lite ny användbar funktionalitet.

På sitt sätt har de rätt. De tror att först måste de på något sätt bli av med alla dessa varningar. Först då kommer de att kunna dra nytta av regelbunden användning av kodanalysatorn. Annars kommer nya varningar helt enkelt att drunkna i gamla, och ingen kommer att uppmärksamma dem.

Detta är samma analogi som med kompilatorvarningar. Det är inte utan anledning som de rekommenderar att man håller antalet kompilatorvarningar på 0. Om det finns 1000 varningar, då när det finns 1001 kommer ingen att uppmärksamma det, och det är inte klart var man ska leta efter denna senaste varning.

Hur man implementerar en statisk kodanalysator i ett äldre projekt utan att demotivera teamet
Det värsta i den här historien är om någon uppifrån just nu tvingar dig att använda statisk kodanalys. Detta kommer bara att demotivera teamet, eftersom det ur deras synvinkel kommer att finnas ytterligare byråkratisk komplexitet som bara kommer i vägen. Ingen kommer att titta på analysatorns rapporter, och all användning kommer endast att vara "på papper". De där. Formellt är analys inbyggd i DevOps-processen, men i praktiken gynnar detta ingen. Vi hörde detaljerade berättelser i bås från konferensdeltagare. En sådan upplevelse kan avskräcka programmerare från att använda statiska analysverktyg under lång tid, om inte för alltid.

Implementera och eliminera tekniska skulder

Det finns faktiskt inget svårt eller skrämmande med att införa statisk analys även i ett stort gammalt projekt.

CI / CD

Dessutom kan analysatorn omedelbart ingå i den kontinuerliga utvecklingsprocessen. Till exempel innehåller distributionen av PVS-Studio verktyg för att bekvämt se rapporten i det format du behöver, och meddelanden till utvecklare som skrev problematiska delar av koden. För den som är mer intresserad av att lansera PVS-Studio från CI/CD-system rekommenderar jag att du bekantar dig med motsvarande sektion dokumentation och en serie artiklar:

Men låt oss återgå till frågan om ett stort antal falska positiva i de första stadierna av implementering av kodanalysverktyg.

Fastställande av befintlig teknisk skuld och hantering av nya varningar

Moderna kommersiella statiska analysatorer låter dig studera endast nya varningar som visas i ny eller ändrad kod. Implementeringen av denna mekanism varierar, men kärnan är densamma. I den statiska analysatorn PVS-Studio implementeras denna funktion enligt följande.

För att snabbt börja använda statisk analys föreslår vi att PVS-Studio-användare använder mekanismen för massundertryckning av varningar [6]. Den allmänna tanken är följande. Användaren startade analysatorn och fick många varningar. Eftersom ett projekt som har varit under utveckling i många år lever, utvecklas och tjänar pengar, så kommer det med största sannolikhet inte att finnas många varningar i rapporten som indikerar kritiska defekter. Kritiska buggar har med andra ord redan åtgärdats på ett eller annat sätt med hjälp av dyrare metoder eller tack vare feedback från kunder. Följaktligen kan allt som analysatorn för närvarande hittar betraktas som teknisk skuld, vilket är opraktiskt att försöka eliminera omedelbart.

Du kan säga till PVS-Studio att betrakta dessa varningar som irrelevanta för tillfället (spara tekniska skulder till senare), och den kommer inte längre att visa dem. Analysatorn skapar en speciell fil där den sparar information om fel som ännu inte är intressanta. Och nu kommer PVS-Studio att utfärda varningar endast för ny eller ändrad kod. Dessutom är allt detta implementerat smart. Om till exempel en tom rad läggs till i början av källkodsfilen, förstår analysatorn att ingenting har förändrats, och kommer att fortsätta att vara tyst. Denna uppmärkningsfil kan läggas in i ett versionskontrollsystem. Filen är stor, men det är inget problem, eftersom det inte är någon idé att lagra den ofta.

Nu kommer alla programmerare att se varningar endast relaterade till ny eller ändrad kod. Således kan du börja använda analysatorn, som de säger, från nästa dag. Och du kan återgå till tekniska skulder senare, och gradvis korrigera fel och konfigurera analysatorn.

Så det första problemet med implementeringen av analysatorn i ett stort gammalt projekt har lösts. Låt oss nu ta reda på vad vi ska göra med tekniska skulder.

Buggfixar och omstruktureringar

Det enklaste och mest naturliga är att avsätta lite tid för att analysera massivt undertryckta analysatorvarningar och gradvis hantera dem. Någonstans bör du fixa fel i koden, någonstans bör du refaktorera för att tala om för analysatorn att koden inte är problematisk. Enkelt exempel:

if (a = b)

De flesta C++-kompilatorer och analysatorer klagar på sådan kod, eftersom det är stor sannolikhet att de faktiskt ville skriva (a == b). Men det finns en outtalad överenskommelse, och detta noteras vanligtvis i dokumentationen, att om det finns ytterligare parenteser, anses det att programmeraren medvetet skrev sådan kod, och det finns ingen anledning att svära. Till exempel i PVS-Studios dokumentation för diagnostik V559 (CWE-481) det är tydligt skrivet att följande rad kommer att anses vara korrekt och säker:

if ((a = b))

Ett annat exempel. Är det glömt i den här C++-koden? bryta eller inte?

case A:
  foo();
case B:
  bar();
  break;

PVS-Studio-analysatorn kommer att utfärda en varning här V796 (CWE-484). Detta kanske inte är ett fel, i så fall bör du ge parsern en ledtråd genom att lägga till attributet [[falla igenom]] eller till exempel __attribut__((fallthrough)):

case A:
  foo();
  [[fallthrough]];
case B:
  bar();
  break;

Man kan säga att sådana kodändringar inte fixar buggen. Ja, det är sant, men det gör två användbara saker. För det första tar analysatorns rapport bort falska positiva resultat. För det andra blir koden mer begriplig för de personer som är involverade i underhållet. Och detta är väldigt viktigt! Enbart för detta är det värt att utföra mindre omfaktorer för att göra koden tydligare och lättare att underhålla. Eftersom analysatorn inte förstår om "paus" behövs eller inte, kommer det också att vara oklart för andra programmerare.

Förutom buggfixar och refaktoreringar kan du specifikt undertrycka uppenbart falska analysatorvarningar. Viss irrelevant diagnostik kan inaktiveras. Någon tycker till exempel att varningar är meningslösa V550 om att jämföra float/double-värden. Och vissa klassificerar dem som viktiga och värda att studera [7]. Vilka varningar som anses relevanta och vilka som inte är det är upp till utvecklingsteamet att avgöra.

Det finns andra sätt att undertrycka falska varningar. Till exempel nämndes makrouppmärkning tidigare. Allt detta beskrivs mer i detalj i dokumentationen. Det viktigaste är att förstå att om du gradvis och systematiskt närmar dig att arbeta med falska positiva, är det inget fel på dem. De allra flesta ointressanta varningar försvinner efter konfigurering, och bara platser som verkligen kräver noggranna studier och vissa ändringar i koden finns kvar.

Dessutom hjälper vi alltid våra kunder att sätta upp PVS-Studio om några problem uppstår. Dessutom fanns det fall då vi själva eliminerade falska varningar och rättade fel [8]. För säkerhets skull bestämde jag mig för att nämna att det här alternativet för utökat samarbete också är möjligt :).

Spärrmetod

Det finns en annan intressant metod för att gradvis förbättra kodkvaliteten genom att eliminera varningen för statisk analysator. Summan av kardemumman är att antalet varningar bara kan minska.

Hur man implementerar en statisk kodanalysator i ett äldre projekt utan att demotivera teamet

Antalet varningar som utfärdats av den statiska analysatorn registreras. Quality gate är konfigurerad på ett sådant sätt att du nu bara kan ange en kod som inte ökar antalet operationer. Som ett resultat börjar processen att gradvis minska antalet larm genom att justera analysatorn och korrigera fel.

Även om en person vill fuska lite och bestämmer sig för att passera kvalitetsporten inte genom att eliminera varningar i sin nya kod, utan genom att förbättra den gamla tredjepartskoden, är detta inte skrämmande. Ändå roterar spärrhaken i en riktning, och gradvis kommer antalet defekter att minska. Även om en person inte vill åtgärda sina egna nya defekter, måste han fortfarande förbättra något i grannkoden. Vid någon tidpunkt slutar de enkla sätten att minska antalet varningar, och det kommer en punkt då riktiga buggar kommer att fixas.

Denna metod beskrivs mer detaljerat i en mycket intressant artikel av Ivan Ponomarev "Implementera statisk analys i processen istället för att använda den för att hitta buggar", som jag rekommenderar att läsa till alla som är intresserade av att förbättra kodkvaliteten.

Författaren till artikeln har också en rapport om detta ämne: "Kontinuerlig statisk analys".

Slutsats

Jag hoppas att läsarna efter den här artikeln kommer att acceptera statiska analysverktyg mer och kommer att vilja implementera dem i utvecklingsprocessen. Om du har några frågor är vi alltid redo ge råd användare av vår statiska analysator PVS-Studio och hjälpa till med dess implementering.

Det finns andra typiska tvivel om huruvida statisk analys verkligen kan vara bekväm och användbar. Jag försökte skingra de flesta av dessa tvivel i publikationen "Reasons to introduce the PVS-Studio static code analyzer in the development process" [9].

Tack för din uppmärksamhet och kom hämta och prova analysatorn PVS-Studio.

Ytterligare länkar

  1. Andrey Karpov. Hur kan jag snabbt se intressanta varningar som PVS-Studio-analysatorn producerar för C- och C++-kod?
  2. Wikipedia. Rices sats.
  3. Andrey Karpov, Victoria Khanieva. Använda maskininlärning i statisk analys av programkällkod.
  4. PVS-studio. Dokumentation. Ytterligare diagnostiska inställningar.
  5. Andrey Karpov. Egenskaper för PVS-Studio-analysatorn med exemplet EFL Core Libraries, 10-15 % falska positiva.
  6. PVS-studio. Dokumentation. Massundertryckning av analysatormeddelanden.
  7. Ivan Andryashin. Om hur vi testade statisk analys på vårt projekt av en pedagogisk simulator för röntgenendovaskulär kirurgi.
  8. Pavel Eremeev, Svyatoslav Razmyslov. Hur PVS-Studio-teamet förbättrade Unreal Engine-koden.
  9. Andrey Karpov. Skäl att introducera den statiska kodanalysatorn PVS-Studio i utvecklingsprocessen.

Hur man implementerar en statisk kodanalysator i ett äldre projekt utan att demotivera teamet

Om du vill dela den här artikeln med en engelsktalande publik, använd gärna översättningslänken: Andrey Karpov. Hur man introducerar en statisk kodanalysator i ett äldre projekt och inte för att avskräcka laget.

Källa: will.com

Lägg en kommentar