Ako implementovať analyzátor statického kódu v starom projekte bez demotivácie tímu

Ako implementovať analyzátor statického kódu v starom projekte bez demotivácie tímu
Je ľahké vyskúšať analyzátor statického kódu. Ale implementovať to, najmä pri vývoji veľkého starého projektu, si vyžaduje zručnosť. Ak sa to urobí nesprávne, analyzátor môže pridať prácu, spomaliť vývoj a demotivovať tím. Poďme si v krátkosti povedať, ako správne pristúpiť k integrácii statickej analýzy do procesu vývoja a začať ju používať ako súčasť CI/CD.

Úvod

Nedávno ma upútala publikácia „Začíname so statickou analýzou bez preťaženia tímu". Na jednej strane je to dobrý článok, s ktorým sa oplatí zoznámiť. Na druhej strane sa mi zdá, že stále neposkytuje úplnú odpoveď na to, ako bezbolestne realizovať statickú analýzu v projekte s množstvom Článok hovorí, že môžete prijať technický dlh a pracovať iba na novom kóde, ale neexistuje žiadna odpoveď na to, čo s týmto technickým dlhom urobiť neskôr.

Náš tím PVS-Studio ponúka svoj pohľad na túto tému. Pozrime sa, ako vôbec problém implementácie statického analyzátora kódu vzniká, ako tento problém prekonať a ako bezbolestne postupne odstraňovať technický dlh.

Problémy

Zvyčajne nie je ťažké spustiť a zistiť, ako funguje statický analyzátor [1]. V kóde môžete vidieť zaujímavé chyby alebo dokonca desivé potenciálne zraniteľnosti. Môžete dokonca niečo opraviť, ale potom to mnohí programátori vzdajú.

Všetky statické analyzátory produkujú falošne pozitívne výsledky. Toto je vlastnosť metodiky analýzy statického kódu a nedá sa s tým nič robiť. Vo všeobecnom prípade ide o neriešiteľný problém, čo potvrdzuje Riceova veta [2]. Nepomôžu ani algoritmy strojového učenia [3]. Aj keď človek nemôže vždy povedať, či je ten alebo ten kód nesprávny, potom by ste to od programu nemali očakávať :).

Falošné poplachy nie sú problémom, ak je statický analyzátor už nakonfigurovaný:

  • Zakázané irelevantné sady pravidiel;
  • Niektoré irelevantné diagnostiky boli deaktivované;
  • Ak hovoríme o C alebo C++, potom sú označené makrá, ktoré obsahujú špecifické konštrukcie, ktoré spôsobujú, že sa na každom mieste, kde sa takéto makrá používajú, objavujú zbytočné varovania;
  • Sú označené vlastné funkcie, ktoré vykonávajú činnosti podobné systémovým funkciám (vlastný analóg memcpy alebo printf) [4];
  • Falošné poplachy sú špecificky zakázané pomocou komentárov;
  • A tak ďalej.

V tomto prípade môžeme očakávať nízku mieru falošnej pozitivity okolo 10-15 % [5]. Inými slovami, 9 z 10 varovaní analyzátora bude indikovať skutočný problém v kóde, alebo aspoň „silne zapáchajúci kód“. Súhlasím, tento scenár je mimoriadne príjemný a analyzátor je skutočným priateľom programátora.

Ako implementovať analyzátor statického kódu v starom projekte bez demotivácie tímu
V skutočnosti vo veľkom projekte bude počiatočný obraz úplne iný. Analyzátor vydáva stovky alebo tisíce upozornení na starý kód. Nie je možné rýchlo pochopiť, ktoré z týchto upozornení sú relevantné a ktoré nie. Je iracionálne sadnúť si a začať sa zaoberať všetkými týmito varovaniami, pretože hlavná práca sa v tomto prípade zastaví na niekoľko dní alebo týždňov. Typicky si tím nemôže dovoliť takýto scenár. Bude tu tiež obrovské množstvo rozdielov, ktoré kazia históriu zmien. A rýchla hromadná úprava toľkých fragmentov v kóde nevyhnutne povedie k novým preklepom a chybám.

A čo je najdôležitejšie, takýto výkon v boji proti varovaniam nemá zmysel. Súhlaste s tým, že keďže projekt úspešne funguje už mnoho rokov, väčšina kritických chýb v ňom už bola opravená. Áno, tieto opravy boli veľmi drahé, museli byť odladené, dostávali negatívnu spätnú väzbu od používateľov o chybách atď. Statický analyzátor by pomohol opraviť mnohé z týchto chýb vo fáze kódovania, rýchlo a lacno. V súčasnosti sú však tieto chyby tak či onak opravené a analyzátor zisťuje hlavne nekritické chyby v starom kóde. Tento kód sa nesmie používať, môže sa používať veľmi zriedkavo a chyba v ňom nemusí viesť k viditeľným následkom. Možno niekde má tieň z tlačidla nesprávnu farbu, ale to nikomu nezasahuje do používania produktu.

Samozrejme, aj drobné chyby sú stále chybami. A niekedy chyba môže skrývať skutočnú zraniteľnosť. Vzdať sa všetkého a tráviť dni/týždne riešením defektov, ktoré sa sotva prejavujú, však vyzerá ako pochybný nápad.

Programátori pozerajú, pozerajú, pozerajú na všetky tieto varovania o starom funkčnom kóde... A myslia si: bez statickej analýzy sa zaobídeme. Poďme napísať nejaké nové užitočné funkcie.

Svojím spôsobom majú pravdu. Uvedomujú si, že najprv sa musia nejako zbaviť všetkých týchto varovaní. Len potom budú môcť využívať výhody pravidelného používania analyzátora kódu. V opačnom prípade sa nové varovania jednoducho utopia v starých a nikto im nebude venovať pozornosť.

Ide o rovnakú analógiu ako pri varovaniach kompilátora. Nie nadarmo odporúčajú ponechať počet upozornení kompilátora na 0. Ak je varovaní 1000, potom keď ich bude 1001, nikto tomu nebude venovať pozornosť a nie je jasné, kde toto najnovšie varovanie hľadať.

Ako implementovať analyzátor statického kódu v starom projekte bez demotivácie tímu
Najhoršie na tomto príbehu je, ak vás niekto zhora v tejto chvíli núti použiť statickú analýzu kódu. Tým to len demotivuje, keďže z ich pohľadu to bude ďalšia byrokratická zložitosť, ktorá len prekáža. Nikto sa nebude pozerať na správy analyzátora a všetko použitie bude len „na papieri“. Tie. Formálne je analýza zabudovaná do procesu DevOps, ale v praxi to nikomu neprospieva. Vypočuli sme si podrobné príbehy v stánkoch od účastníkov konferencie. Takáto skúsenosť môže odradiť programátorov od používania nástrojov statickej analýzy na dlhú dobu, ak nie navždy.

Implementácia a odstraňovanie technického dlhu

V skutočnosti nie je nič ťažké alebo strašidelné na zavedení statickej analýzy aj do veľkého starého projektu.

CI / CD

Okrem toho môže byť analyzátor okamžite súčasťou procesu neustáleho vývoja. Napríklad distribúcia PVS-Studio obsahuje nástroje na pohodlné prezeranie zostavy vo formáte, ktorý potrebujete, a upozornenia pre vývojárov, ktorí napísali problematické časti kódu. Pre tých, ktorí sa viac zaujímajú o spustenie PVS-Studio z CI/CD systémov, odporúčam oboznámiť sa s príslušnými oddiele dokumentácia a séria článkov:

Vráťme sa však k problému veľkého počtu falošných poplachov v prvých fázach implementácie nástrojov na analýzu kódu.

Oprava existujúceho technického dlhu a riešenie nových upozornení

Moderné komerčné statické analyzátory vám umožňujú študovať iba nové varovania, ktoré sa objavujú v novom alebo zmenenom kóde. Implementácia tohto mechanizmu sa líši, ale podstata je rovnaká. V statickom analyzátore PVS-Studio je táto funkcia implementovaná nasledovne.

Ak chcete rýchlo začať používať statickú analýzu, odporúčame používateľom PVS-Studio použiť mechanizmus na hromadné potlačenie varovaní [6]. Všeobecná myšlienka je nasledovná. Používateľ spustil analyzátor a dostal veľa upozornení. Keďže projekt, ktorý sa vyvíja už mnoho rokov, je živý, vyvíja sa a zarába peniaze, potom s najväčšou pravdepodobnosťou v správe nebude veľa varovaní, ktoré by poukazovali na kritické chyby. Inými slovami, kritické chyby už boli opravené tak či onak pomocou drahších metód alebo vďaka spätnej väzbe od zákazníkov. Preto všetko, čo analyzátor v súčasnosti nájde, možno považovať za technický dlh, ktorý je nepraktické okamžite odstrániť.

Môžete povedať PVS-Studio, aby tieto upozornenia nateraz považovalo za irelevantné (technický dlh si odložte na neskôr) a už ich nebude zobrazovať. Analyzátor vytvorí špeciálny súbor, do ktorého uloží informácie o chybách, ktoré ešte nie sú zaujímavé. A teraz bude PVS-Studio vydávať upozornenia iba na nový alebo zmenený kód. Toto všetko je navyše implementované šikovne. Ak sa napríklad na začiatok súboru zdrojového kódu pridá prázdny riadok, analyzátor pochopí, že sa v skutočnosti nič nezmenilo a bude naďalej mlčať. Tento značkovací súbor je možné vložiť do systému správy verzií. Súbor je veľký, ale to nie je problém, pretože nemá zmysel ho často ukladať.

Teraz všetci programátori uvidia upozornenia týkajúce sa iba nového alebo zmeneného kódu. Analyzátor teda môžete začať používať, ako sa hovorí, od nasledujúceho dňa. A neskôr sa môžete vrátiť k technickému dlhu a postupne opravovať chyby a konfigurovať analyzátor.

Prvý problém s implementáciou analyzátora vo veľkom starom projekte bol teda vyriešený. Teraz poďme zistiť, čo robiť s technickým dlhom.

Opravy chýb a refaktoringy

Najjednoduchšie a najprirodzenejšie je vyhradiť si čas na analýzu masívne potláčaných varovaní analyzátora a postupne sa s nimi vysporiadať. Niekde by ste mali opraviť chyby v kóde, niekde by ste mali refaktorovať, aby ste analyzátoru povedali, že kód nie je problematický. Jednoduchý príklad:

if (a = b)

Väčšina kompilátorov a analyzátorov C++ sa sťažuje na takýto kód, pretože existuje vysoká pravdepodobnosť, že skutočne chceli napísať (a == b). Existuje však nevyslovená dohoda, a to je zvyčajne uvedené v dokumentácii, že ak existujú ďalšie zátvorky, potom sa má za to, že programátor napísal takýto kód úmyselne a nie je potrebné nadávať. Napríklad v dokumentácii PVS-Studio pre diagnostiku V559 (CWE-481) je jasne napísané, že nasledujúci riadok sa bude považovať za správny a bezpečný:

if ((a = b))

Ďalší príklad. Je to zabudnuté v tomto kóde C++? rozbiť alebo nie?

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

Analyzátor PVS-Studio tu vydá varovanie V796 (CWE-484). Nemusí to byť chyba, v takom prípade by ste mali dať analyzátoru nápovedu pridaním atribútu [[prepadnúť]] alebo napr __attribute__((fallthrough)):

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

Dá sa povedať, že takéto zmeny kódu chybu neopravujú. Áno, to je pravda, ale robí to dve užitočné veci. Po prvé, správa analyzátora sa zbaví falošných poplachov. Po druhé, kód sa stáva zrozumiteľnejším pre ľudí, ktorí sa podieľajú na jeho údržbe. A to je veľmi dôležité! Len kvôli tomu sa oplatí vykonať menšie refaktoringy, aby bol kód prehľadnejší a ľahšie sa udržiaval. Keďže analyzátor nerozumie tomu, či je „prestávka“ potrebná alebo nie, nebude to jasné ani ostatným programátorom.

Okrem opráv chýb a refaktoringov môžete špecificky potlačiť zjavne falošné varovania analyzátora. Niektoré irelevantné diagnostiky možno deaktivovať. Niekto si napríklad myslí, že varovania sú zbytočné V550 o porovnaní hodnôt float/double. A niektorí ich klasifikujú ako dôležité a hodné štúdia [7]. Ktoré varovania sa považujú za relevantné a ktoré nie, je na rozhodnutí vývojového tímu.

Existujú aj iné spôsoby, ako potlačiť falošné upozornenia. Napríklad makro značenie bolo spomenuté skôr. Toto všetko je podrobnejšie popísané v dokumentácii. Najdôležitejšie je pochopiť, že ak postupne a systematicky pristupujete k práci s falošnými pozitívami, nie je na nich nič zlé. Drvivá väčšina nezaujímavých upozornení po konfigurácii zmizne a ostanú len miesta, ktoré si naozaj vyžadujú dôkladné preštudovanie a nejaké zmeny v kóde.

Tiež vždy pomáhame našim klientom nastaviť PVS-Studio, ak sa vyskytnú nejaké ťažkosti. Okrem toho sa vyskytli prípady, keď sme sami odstránili falošné varovania a opravili chyby [8]. Pre každý prípad som sa rozhodol spomenúť, že je možná aj táto možnosť rozšírenej spolupráce :).

Ratchetova metóda

Existuje ďalší zaujímavý prístup k postupnému zlepšovaniu kvality kódu odstránením varovania statického analyzátora. Pointa je, že počet varovaní sa môže len znižovať.

Ako implementovať analyzátor statického kódu v starom projekte bez demotivácie tímu

Zaznamenáva sa počet varovaní vydaných statickým analyzátorom. Brána kvality je nakonfigurovaná tak, že teraz môžete zadať iba kód, ktorý nezvyšuje počet operácií. Výsledkom je, že proces postupného znižovania počtu alarmov začína nastavením analyzátora a opravou chýb.

Aj keď chce človek trochu podvádzať a rozhodne sa prejsť bránou kvality nie odstránením varovaní vo svojom novom kóde, ale vylepšením starého kódu tretej strany, nie je to desivé. Napriek tomu sa rohatka otáča jedným smerom a postupne sa počet defektov zníži. Aj keď človek nechce opravovať svoje vlastné nové defekty, stále bude musieť niečo vylepšiť v susednom kóde. V určitom bode jednoduché spôsoby, ako znížiť počet upozornení, končia a prichádza bod, kedy budú opravené skutočné chyby.

Táto metodika je podrobnejšie opísaná vo veľmi zaujímavom článku Ivana Ponomareva “Implementujte statickú analýzu do procesu a nepoužívajte ju na hľadanie chýb“, ktorý odporúčam prečítať každému, kto má záujem o zlepšenie kvality kódu.

Autor článku má na túto tému aj správu: "Priebežná statická analýza".

Záver

Dúfam, že po tomto článku budú čitatelia viac akceptovať nástroje statickej analýzy a budú ich chcieť implementovať do procesu vývoja. Ak máte akékoľvek otázky, sme vždy pripravení poradiť užívateľov nášho statického analyzátora PVS-Studio a pomoc s jeho implementáciou.

Existujú aj ďalšie typické pochybnosti o tom, či môže byť statická analýza skutočne pohodlná a užitočná. Väčšinu z týchto pochybností som sa pokúsil rozptýliť v publikácii „Dôvody zavedenia analyzátora statického kódu PVS-Studio do procesu vývoja“ [9].

Ďakujem za pozornosť a príďte k stiahnutiu a vyskúšajte analyzátor PVS-Studio.

Ďalšie odkazy

  1. Andrej Karpov. Ako môžem rýchlo vidieť zaujímavé upozornenia, ktoré analyzátor PVS-Studio vytvára pre kód C a C++?
  2. Wikipedia. Riceova veta.
  3. Andrey Karpov, Victoria Khanieva. Využitie strojového učenia pri statickej analýze zdrojového kódu programu.
  4. PVS-Štúdio. Dokumentácia. Ďalšie diagnostické nastavenia.
  5. Andrej Karpov. Charakteristika analyzátora PVS-Studio na príklade EFL Core Libraries, 10-15 % falošne pozitívnych výsledkov.
  6. PVS-Štúdio. Dokumentácia. Hromadné potlačenie správ analyzátora.
  7. Ivan Andryashin. O tom, ako sme testovali statickú analýzu na našom projekte edukačného simulátora RTG endovaskulárnej chirurgie.
  8. Pavel Eremeev, Svyatoslav Razmyslov. Ako tím PVS-Studio vylepšil kód Unreal Engine.
  9. Andrej Karpov. Dôvody na zavedenie statického analyzátora kódu PVS-Studio do procesu vývoja.

Ako implementovať analyzátor statického kódu v starom projekte bez demotivácie tímu

Ak chcete zdieľať tento článok s anglicky hovoriacim publikom, použite odkaz na preklad: Andrey Karpov. Ako zaviesť analyzátor statického kódu v staršom projekte a neodradiť tím.

Zdroj: hab.com

Pridať komentár