Hvordan man implementerer en statisk kodeanalysator i et ældre projekt uden at demotivere teamet

Hvordan man implementerer en statisk kodeanalysator i et ældre projekt uden at demotivere teamet
Det er nemt at prøve en statisk kodeanalysator. Men at implementere det, især i udviklingen af ​​et stort gammelt projekt, kræver dygtighed. Hvis det gøres forkert, kan analysatoren tilføje arbejde, bremse udviklingen og demotivere teamet. Lad os kort tale om, hvordan man korrekt griber integrationen af ​​statisk analyse ind i udviklingsprocessen og begynder at bruge den som en del af CI/CD.

Indledning

For nylig blev min opmærksomhed henledt til publikationen "Kom godt i gang med statisk analyse uden at overvælde holdet". På den ene side er dette en god artikel, som er værd at sætte sig ind i. På den anden side forekommer det mig, at den stadig ikke giver et fuldstændigt svar på, hvordan man smertefrit implementerer statisk analyse i et projekt med meget Artiklen siger, at du kan acceptere teknisk gæld og kun arbejde på ny kode, men der er ikke noget svar på, hvad du skal gøre med denne tekniske gæld senere.

Vores PVS-Studio-team giver sit syn på dette emne. Lad os se på, hvordan problemet med at implementere en statisk kodeanalysator opstår i første omgang, hvordan man overvinder dette problem, og hvordan man smertefrit gradvist eliminerer teknisk gæld.

Problemer

Det er normalt ikke svært at starte og se, hvordan en statisk analysator fungerer [1]. Du kan muligvis se interessante fejl eller endda skræmmende potentielle sårbarheder i koden. Du kan endda ordne noget, men så giver mange programmører op.

Alle statiske analysatorer producerer falske positiver. Dette er en funktion af den statiske kodeanalysemetodologi, og der kan ikke gøres noget ved det. I det generelle tilfælde er dette et uløseligt problem, som bekræftet af Rices teorem [2]. Maskinlæringsalgoritmer hjælper heller ikke [3]. Selvom en person ikke altid kan se, om denne eller hin kode er forkert, så skal du ikke forvente dette af programmet :).

Falske positiver er ikke et problem, hvis den statiske analysator allerede er konfigureret:

  • Deaktiveret irrelevante regelsæt;
  • Nogle irrelevante diagnostik er blevet deaktiveret;
  • Hvis vi taler om C eller C++, så er makroer markeret, der indeholder specifikke konstruktioner, der forårsager, at ubrugelige advarsler vises alle steder, hvor sådanne makroer bruges;
  • Egne funktioner er markeret, der udfører handlinger, der ligner systemfunktioner (sin egen analog memcpy eller printf) [4];
  • Falske positiver er specifikt deaktiveret ved hjælp af kommentarer;
  • Og så videre.

I dette tilfælde kan vi forvente en lav falsk positiv rate på omkring 10-15 % [5]. Med andre ord vil 9 ud af 10 analysatoradvarsler indikere et reelt problem i koden, eller i det mindste "stærkt lugtende kode." Enig, dette scenarie er ekstremt behageligt, og analysatoren er en rigtig ven af ​​programmøren.

Hvordan man implementerer en statisk kodeanalysator i et ældre projekt uden at demotivere teamet
I virkeligheden vil det indledende billede i et stort projekt være et helt andet. Analysatoren udsender hundredvis eller tusindvis af advarsler for ældre kode. Det er umuligt hurtigt at forstå, hvilke af disse advarsler der er relevante, og hvilke der ikke er. Det er irrationelt at sætte sig ned og begynde at håndtere alle disse advarsler, da hovedarbejdet i dette tilfælde vil stoppe i dage eller uger. Typisk har et hold ikke råd til et sådant scenario. Der vil også være et stort antal diffs, der spolerer forandringshistorien. Og hurtig masseredigering af så mange fragmenter i koden vil uundgåeligt resultere i nye tastefejl og fejl.

Og vigtigst af alt giver en sådan bedrift i kampen mod advarsler ingen mening. Enig i, at da projektet har kørt med succes i mange år, er de fleste af de kritiske fejl i det allerede blevet rettet. Ja, disse rettelser var meget dyre, skulle fejlfindes, modtog negativ brugerfeedback om fejl og så videre. En statisk analysator ville hjælpe med at rette mange af disse fejl på kodningsstadiet, hurtigt og billigt. Men i øjeblikket, på den ene eller anden måde, er disse fejl blevet rettet, og analysatoren opdager hovedsageligt ikke-kritiske fejl i den gamle kode. Denne kode bruges muligvis ikke, den kan bruges meget sjældent, og en fejl i den fører muligvis ikke til mærkbare konsekvenser. Måske et eller andet sted er skyggen fra knappen den forkerte farve, men dette forstyrrer ikke nogens brug af produktet.

Selvfølgelig er selv små fejl stadig fejl. Og nogle gange kan en fejl skjule en reel sårbarhed. Men at opgive alt og bruge dage/uger på at beskæftige sig med skavanker, der knap nok viser sig, ligner en tvivlsom idé.

Programmører ser, ser, ser på alle disse advarsler om den gamle arbejdskode... Og de tænker: vi kan undvære statisk analyse. Lad os skrive nogle nye nyttige funktioner.

På hver deres måde har de ret. De regner med, at først skal de på en eller anden måde slippe af med alle disse advarsler. Først da vil de kunne drage fordel af regelmæssig brug af kodeanalysatoren. Ellers vil nye advarsler simpelthen drukne i gamle, og ingen vil være opmærksomme på dem.

Dette er den samme analogi som med compiler-advarsler. Det er ikke uden grund, at de anbefaler at holde antallet af compiler-advarsler på 0. Hvis der er 1000 advarsler, så når der er 1001, vil ingen være opmærksomme på det, og det er ikke klart, hvor man skal lede efter denne nyeste advarsel.

Hvordan man implementerer en statisk kodeanalysator i et ældre projekt uden at demotivere teamet
Det værste i denne historie er, hvis nogen fra oven i dette øjeblik tvinger dig til at bruge statisk kodeanalyse. Dette vil kun demotivere holdet, da der fra deres synspunkt vil være yderligere bureaukratisk kompleksitet, der kun kommer i vejen. Ingen vil se på analysatorens rapporter, og al brug vil kun være "på papir". De der. Formelt er der indbygget analyse i DevOps-processen, men i praksis kommer det ingen til gode. Vi hørte detaljerede historier ved standene fra konferencedeltagere. En sådan oplevelse kan afholde programmører fra at bruge statiske analyseværktøjer i lang tid, hvis ikke for evigt.

Implementering og eliminering af teknisk gæld

Faktisk er der ikke noget svært eller skræmmende ved at indføre statisk analyse selv i et stort gammelt projekt.

CI / CD

Desuden kan analysatoren straks blive en del af den kontinuerlige udviklingsproces. For eksempel indeholder PVS-Studio-distributionen værktøjer til bekvemt at se rapporten i det format, du har brug for, og meddelelser til udviklere, der har skrevet problematiske dele af koden. For dem, der er mere interesserede i at lancere PVS-Studio fra CI/CD-systemer, anbefaler jeg, at du gør dig bekendt med de tilsvarende afsnit dokumentation og en række artikler:

Men lad os vende tilbage til spørgsmålet om et stort antal falske positiver i de første stadier af implementering af kodeanalyseværktøjer.

Udbedring af eksisterende teknisk gæld og håndtering af nye advarsler

Moderne kommercielle statiske analysatorer giver dig mulighed for kun at studere nye advarsler, der vises i ny eller ændret kode. Implementeringen af ​​denne mekanisme varierer, men essensen er den samme. I den statiske analysator PVS-Studio er denne funktionalitet implementeret som følger.

For hurtigt at begynde at bruge statisk analyse foreslår vi, at PVS-Studio-brugere bruger mekanismen til masseundertrykkelse af advarsler [6]. Den generelle idé er følgende. Brugeren startede analysatoren og modtog mange advarsler. Da et projekt, der har været under udvikling i mange år, lever, udvikler sig og tjener penge, så vil der højst sandsynligt ikke være mange advarsler i rapporten, der indikerer kritiske mangler. Med andre ord er kritiske fejl allerede blevet rettet på den ene eller anden måde ved hjælp af dyrere metoder eller takket være feedback fra kunder. Derfor kan alt, hvad analysatoren i øjeblikket finder, betragtes som teknisk gæld, hvilket er upraktisk at forsøge at fjerne med det samme.

Du kan bede PVS-Studio om at betragte disse advarsler som irrelevante indtil videre (gem teknisk gæld til senere), og det vil ikke længere vise dem. Analysatoren opretter en speciel fil, hvor den gemmer information om fejl, der endnu ikke er interessante. Og nu vil PVS-Studio kun udstede advarsler for ny eller ændret kode. Desuden er alt dette implementeret smart. Hvis der f.eks. tilføjes en tom linje i begyndelsen af ​​kildekodefilen, så forstår analysatoren, at i virkeligheden intet er ændret, og vil fortsætte med at være tavs. Denne markup-fil kan lægges ind i et versionskontrolsystem. Filen er stor, men det er ikke et problem, da det ikke nytter at gemme det ofte.

Nu vil alle programmører kun se advarsler relateret til ny eller ændret kode. Således kan du begynde at bruge analysatoren, som man siger, fra næste dag. Og du kan vende tilbage til teknisk gæld senere og gradvist rette fejl og konfigurere analysatoren.

Så det første problem med implementeringen af ​​analysatoren i et stort gammelt projekt er blevet løst. Lad os nu finde ud af, hvad vi skal gøre med teknisk gæld.

Fejlrettelser og refactorings

Det enkleste og mest naturlige er at afsætte lidt tid til at analysere massivt undertrykte analysatoradvarsler og gradvist håndtere dem. Et eller andet sted bør du rette fejl i koden, et eller andet sted bør du refaktorere for at fortælle analysatoren, at koden ikke er problematisk. Simpelt eksempel:

if (a = b)

De fleste C++ compilere og analysatorer klager over sådan kode, da der er stor sandsynlighed for, at de faktisk ønskede at skrive (a == b). Men der er en uudtalt aftale, og det er normalt noteret i dokumentationen, at hvis der er yderligere parenteser, så anses det for, at programmøren bevidst skrev en sådan kode, og der er ingen grund til at bande. For eksempel i PVS-Studio dokumentation for diagnostik V559 (CWE-481) det er tydeligt skrevet, at følgende linje vil blive betragtet som korrekt og sikker:

if ((a = b))

Et andet eksempel. Er det glemt i denne C++ kode? bryde eller ikke?

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

PVS-Studio-analysatoren vil udsende en advarsel her V796 (CWE-484). Dette er muligvis ikke en fejl, i så fald bør du give parseren et hint ved at tilføje attributten [[falder gennem]] eller for eksempel __attribut__((gennemfald)):

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

Det kan siges, at sådanne kodeændringer ikke løser fejlen. Ja, det er sandt, men det gør to nyttige ting. For det første fjerner analysatorrapporten falske positiver. For det andet bliver koden mere forståelig for de personer, der er involveret i dens vedligeholdelse. Og dette er meget vigtigt! Alene til dette er det værd at udføre mindre refactorings for at gøre koden klarere og lettere at vedligeholde. Da analysatoren ikke forstår, om "pause" er nødvendig eller ej, vil det også være uklart for andre programmører.

Ud over fejlrettelser og refactorings kan du specifikt undertrykke åbenlyst falske analysatoradvarsler. Nogle irrelevante diagnostik kan deaktiveres. For eksempel synes nogen, at advarsler er meningsløse V550 om at sammenligne float/double værdier. Og nogle klassificerer dem som vigtige og værdige at studere [7]. Hvilke advarsler der anses for relevante, og hvilke der ikke er, er op til udviklingsteamet at afgøre.

Der er andre måder at undertrykke falske advarsler på. For eksempel blev makromarkup nævnt tidligere. Alt dette er beskrevet mere detaljeret i dokumentationen. Det vigtigste er at forstå, at hvis du gradvist og systematisk nærmer dig arbejdet med falske positiver, er der ikke noget galt med dem. Langt de fleste uinteressante advarsler forsvinder efter konfiguration, og der er kun steder tilbage, der virkelig kræver omhyggelig undersøgelse og nogle ændringer i koden.

Vi hjælper også altid vores kunder med at opsætte PVS-Studio, hvis der opstår problemer. Desuden var der tilfælde, hvor vi selv fjernede falske advarsler og rettede fejl [8]. For en sikkerheds skyld besluttede jeg at nævne, at denne mulighed for udvidet samarbejde også er mulig :).

Skraldemetode

Der er en anden interessant tilgang til gradvist at forbedre kodekvaliteten ved at eliminere den statiske analysator-advarsel. Den nederste linje er, at antallet af advarsler kun kan falde.

Hvordan man implementerer en statisk kodeanalysator i et ældre projekt uden at demotivere teamet

Antallet af advarsler udstedt af den statiske analysator registreres. Quality gate er konfigureret på en sådan måde, at du nu kun kan indtaste en kode, der ikke øger antallet af operationer. Som et resultat starter processen med gradvist at reducere antallet af alarmer ved at justere analysatoren og rette fejl.

Selvom en person ønsker at snyde lidt og beslutter sig for at passere kvalitetsporten, ikke ved at fjerne advarsler i sin nye kode, men ved at forbedre den gamle tredjepartskode, er dette ikke skræmmende. Alligevel roterer skralden i én retning, og gradvist vil antallet af defekter falde. Selvom en person ikke ønsker at rette sine egne nye defekter, bliver han stadig nødt til at forbedre noget i nabokoden. På et tidspunkt slutter de nemme måder at reducere antallet af advarsler på, og der kommer et tidspunkt, hvor rigtige fejl vil blive rettet.

Denne metode er beskrevet mere detaljeret i en meget interessant artikel af Ivan Ponomarev "Implementer statisk analyse i processen i stedet for at bruge den til at finde fejl", som jeg anbefaler at læse til alle, der er interesseret i at forbedre kodekvaliteten.

Forfatteren af ​​artiklen har også en rapport om dette emne: "Kontinuerlig statisk analyse".

Konklusion

Jeg håber, at læserne efter denne artikel vil være mere accepterede af statiske analyseværktøjer og ønsker at implementere dem i udviklingsprocessen. Hvis du har spørgsmål, er vi altid klar rådgive brugere af vores statiske analysator PVS-Studio og hjælpe med implementeringen.

Der er andre typiske tvivl om, hvorvidt statisk analyse virkelig kan være praktisk og nyttig. Jeg forsøgte at fjerne de fleste af disse tvivl i publikationen "Reasons to introduce the PVS-Studio static code analyzer in the development process" [9].

Tak for din opmærksomhed og kom скачать og prøv PVS-Studio-analysatoren.

Yderligere links

  1. Andrey Karpov. Hvordan kan jeg hurtigt se interessante advarsler, som PVS-Studio-analysatoren producerer for C- og C++-kode?
  2. Wikipedia. Rice's teorem.
  3. Andrey Karpov, Victoria Khanieva. Brug af maskinlæring i statisk analyse af programkildekode.
  4. PVS-Studio. Dokumentation. Yderligere diagnostiske indstillinger.
  5. Andrey Karpov. Karakteristika for PVS-Studio-analysatoren ved hjælp af eksemplet med EFL Core Libraries, 10-15 % falske positiver.
  6. PVS-Studio. Dokumentation. Masseundertrykkelse af analysatormeddelelser.
  7. Ivan Andryashin. Om hvordan vi testede statisk analyse på vores projekt af en pædagogisk simulator for røntgen-endovaskulær kirurgi.
  8. Pavel Eremeev, Svyatoslav Razmyslov. Hvordan PVS-Studio-teamet forbedrede Unreal Engine-koden.
  9. Andrey Karpov. Grunde til at introducere den statiske kodeanalysator PVS-Studio i udviklingsprocessen.

Hvordan man implementerer en statisk kodeanalysator i et ældre projekt uden at demotivere teamet

Hvis du vil dele denne artikel med et engelsktalende publikum, så brug venligst oversættelseslinket: Andrey Karpov. Hvordan man introducerer en statisk kodeanalysator i et ældre projekt og ikke for at afskrække holdet.

Kilde: www.habr.com

Tilføj en kommentar