Hoe u een statische code-analysator in een bestaand project implementeert zonder het team te demotiveren

Hoe u een statische code-analysator in een bestaand project implementeert zonder het team te demotiveren
Het is gemakkelijk om een ​​statische code-analysator uit te proberen. Maar om het te implementeren, vooral bij de ontwikkeling van een groot oud project, is vaardigheid vereist. Als het verkeerd wordt gedaan, kan de analysator werk toevoegen, de ontwikkeling vertragen en het team demotiveren. Laten we het kort hebben over hoe we de integratie van statische analyse in het ontwikkelingsproces op de juiste manier kunnen benaderen en hoe we deze kunnen gaan gebruiken als onderdeel van CI/CD.

Introductie

Onlangs werd mijn aandacht gevestigd op de publicatie "Aan de slag met statische analyse zonder het team te overweldigen". Aan de ene kant is dit een goed artikel dat de moeite waard is om kennis mee te maken. Aan de andere kant lijkt het mij dat het nog steeds geen volledig antwoord geeft over hoe je statische analyse pijnloos kunt implementeren in een project met veel Het artikel zegt dat u technische schulden kunt accepteren en alleen aan nieuwe code kunt werken, maar er is geen antwoord op de vraag wat u later met deze technische schulden moet doen.

Ons PVS-Studio team geeft zijn visie op dit onderwerp. Laten we eens kijken hoe het probleem van het implementeren van een statische code-analysator in de eerste plaats ontstaat, hoe dit probleem kan worden opgelost en hoe we technische schulden pijnloos en geleidelijk kunnen elimineren.

Problemen

Het is meestal niet moeilijk om een ​​statische analysator te starten en te zien hoe hij werkt [1]. Mogelijk ziet u interessante fouten of zelfs angstaanjagende potentiële kwetsbaarheden in de code. Je kunt zelfs iets repareren, maar dan geven veel programmeurs het op.

Alle statische analysatoren produceren valse positieven. Dit is een kenmerk van de methodologie voor statische codeanalyse en er kan niets aan worden gedaan. In het algemene geval is dit een onoplosbaar probleem, zoals bevestigd door de stelling van Rice.2]. Machine learning-algoritmen zullen ook niet helpen [3]. Zelfs als een persoon niet altijd kan zeggen of deze of gene code verkeerd is, dan mag je dit niet van het programma verwachten :).

Valse positieve resultaten zijn geen probleem als de statische analysator al is geconfigureerd:

  • Niet-relevante regelsets uitgeschakeld;
  • Sommige irrelevante diagnostiek is uitgeschakeld;
  • Als we het over C of C++ hebben, dan zijn macro's gemarkeerd met specifieke constructies die ervoor zorgen dat nutteloze waarschuwingen verschijnen op elke plaats waar dergelijke macro's worden gebruikt;
  • Eigen functies zijn gemarkeerd die acties uitvoeren die vergelijkbaar zijn met systeemfuncties (zijn eigen analoog memcpy of printf) [4];
  • Valse positieven worden specifiek uitgeschakeld met behulp van opmerkingen;
  • En ga zo maar door.

In dit geval kunnen we een laag percentage fout-positieve resultaten verwachten van ongeveer 10-15% [5]. Met andere woorden: 9 van de 10 analyserwaarschuwingen duiden op een reëel probleem in de code, of op zijn minst op ‘sterk ruikende code’. Mee eens, dit scenario is buitengewoon aangenaam en de analysator is een echte vriend van de programmeur.

Hoe u een statische code-analysator in een bestaand project implementeert zonder het team te demotiveren
In werkelijkheid zal het initiële beeld bij een groot project compleet anders zijn. De analyser geeft honderden of duizenden waarschuwingen voor verouderde code. Het is onmogelijk om snel te begrijpen welke van deze waarschuwingen relevant zijn en welke niet. Het is irrationeel om te gaan zitten en al deze waarschuwingen in behandeling te nemen, aangezien het hoofdwerk in dit geval dagen of weken zal stilvallen. Normaal gesproken kan een team zich een dergelijk scenario niet veroorloven. Er zullen ook een groot aantal verschillen zijn die de veranderingsgeschiedenis bederven. En het snel massaal bewerken van zoveel fragmenten in de code zal onvermijdelijk resulteren in nieuwe typefouten en fouten.

En het allerbelangrijkste: zo'n prestatie in de strijd tegen waarschuwingen heeft weinig zin. Ben het ermee eens dat, aangezien het project al vele jaren met succes draait, de meeste kritieke fouten erin al zijn gecorrigeerd. Ja, deze oplossingen waren erg duur, moesten worden opgespoord, kregen negatieve gebruikersfeedback over bugs, enzovoort. Een statische analysator zou veel van deze fouten in de codeerfase snel en goedkoop kunnen oplossen. Maar op dit moment zijn deze fouten op de een of andere manier verholpen en detecteert de analysator voornamelijk niet-kritieke fouten in de oude code. Deze code mag niet worden gebruikt, deze kan zeer zelden worden gebruikt en een fout daarin mag niet tot merkbare gevolgen leiden. Misschien heeft ergens de schaduw van de knop de verkeerde kleur, maar dit staat niemands gebruik van het product in de weg.

Natuurlijk zijn zelfs kleine fouten nog steeds fouten. En soms kan een fout een echte kwetsbaarheid verbergen. Het lijkt echter een twijfelachtig idee om alles op te geven en dagen/weken te besteden aan het omgaan met gebreken die zich nauwelijks manifesteren.

Programmeurs kijken, kijken, kijken naar al deze waarschuwingen over de oude werkende code... En ze denken: we kunnen het zonder statische analyse stellen. Laten we wat nieuwe nuttige functionaliteit gaan schrijven.

Op hun eigen manier hebben ze gelijk. Ze denken dat ze eerst op de een of andere manier van al deze waarschuwingen af ​​moeten komen. Alleen dan kunnen ze profiteren van regelmatig gebruik van de code-analyzer. Anders zullen nieuwe waarschuwingen eenvoudigweg in de oude verdrinken, en niemand zal er aandacht aan besteden.

Dit is dezelfde analogie als bij compilerwaarschuwingen. Niet voor niets raden ze aan om het aantal compilerwaarschuwingen op 0 te houden. Als er 1000 waarschuwingen zijn, zal niemand er aandacht aan besteden als het er 1001 zijn, en is het niet duidelijk waar je deze nieuwste waarschuwing moet zoeken.

Hoe u een statische code-analysator in een bestaand project implementeert zonder het team te demotiveren
Het ergste in dit verhaal is als iemand van bovenaf je op dit moment dwingt om statische code-analyse te gebruiken. Dit zal het team alleen maar demotiveren, omdat er vanuit hun oogpunt extra bureaucratische complexiteit zal zijn die alleen maar in de weg zit. Niemand zal naar de rapporten van de analysator kijken en al het gebruik zal alleen “op papier” plaatsvinden. Die. Formeel is analyse ingebouwd in het DevOps-proces, maar in de praktijk heeft niemand er baat bij. We hoorden gedetailleerde verhalen bij stands van conferentiedeelnemers. Een dergelijke ervaring kan programmeurs ervan weerhouden om statische analysehulpmiddelen voor lange tijd, zo niet voor altijd, te gebruiken.

Implementeren en elimineren van technische schulden

In feite is er niets moeilijks of angstaanjagends aan het introduceren van statische analyse, zelfs in een groot, oud project.

CI / CD

Bovendien kan de analyser direct onderdeel worden van het continue ontwikkelingsproces. De PVS-Studio-distributie bevat bijvoorbeeld hulpprogramma's waarmee u het rapport gemakkelijk kunt bekijken in het formaat dat u nodig hebt, en meldingen voor ontwikkelaars die problematische delen van de code hebben geschreven. Voor degenen die meer geïnteresseerd zijn in het starten van PVS-Studio vanaf CI/CD-systemen, raad ik aan dat u zich vertrouwd maakt met de bijbehorende sectie documentatie en een reeks artikelen:

Maar laten we terugkeren naar de kwestie van een groot aantal valse positieven in de eerste fasen van de implementatie van codeanalysetools.

Het oplossen van bestaande technische schulden en het omgaan met nieuwe waarschuwingen

Met moderne commerciële statische analysers kunt u alleen nieuwe waarschuwingen bestuderen die in nieuwe of gewijzigde code verschijnen. De implementatie van dit mechanisme varieert, maar de essentie is hetzelfde. In de statische analysator van PVS-Studio is deze functionaliteit als volgt geïmplementeerd.

Om snel statische analyse te gaan gebruiken, raden we gebruikers van PVS-Studio aan om het mechanisme voor massale onderdrukking van waarschuwingen te gebruiken [6]. Het algemene idee is het volgende. De gebruiker startte de analysator en ontving veel waarschuwingen. Aangezien een project dat al vele jaren in ontwikkeling is, leeft, zich ontwikkelt en geld verdient, zullen er hoogstwaarschijnlijk niet veel waarschuwingen in het rapport staan ​​die wijzen op kritieke gebreken. Met andere woorden: kritieke bugs zijn op de een of andere manier al opgelost met behulp van duurdere methoden of dankzij feedback van klanten. Dienovereenkomstig kan alles wat de analysator momenteel vindt, worden beschouwd als technische schulden, wat onpraktisch is om onmiddellijk te proberen te elimineren.

U kunt PVS-Studio vertellen dat deze waarschuwingen voorlopig als irrelevant moeten worden beschouwd (bewaar technische schulden voor later), waarna ze niet langer worden weergegeven. De analyser maakt een speciaal bestand aan waarin informatie wordt opgeslagen over fouten die nog niet interessant zijn. En nu geeft PVS-Studio alleen waarschuwingen voor nieuwe of gewijzigde code. Bovendien is dit alles slim geïmplementeerd. Als er bijvoorbeeld een lege regel wordt toegevoegd aan het begin van het broncodebestand, begrijpt de analysator dat er in feite niets is veranderd en blijft hij stil. Dit opmaakbestand kan in een versiebeheersysteem worden geplaatst. Het bestand is groot, maar dit is geen probleem, aangezien het geen zin heeft om het vaak op te slaan.

Nu zullen alle programmeurs alleen waarschuwingen zien die verband houden met nieuwe of gewijzigde code. U kunt de analysator dus, zoals ze zeggen, vanaf de volgende dag gaan gebruiken. En u kunt later terugkeren naar de technische schulden en geleidelijk fouten corrigeren en de analysator configureren.

Het eerste probleem met de implementatie van de analysator in een groot oud project is dus opgelost. Laten we nu eens kijken wat we met technische schulden moeten doen.

Bugfixes en refactorings

Het eenvoudigste en meest natuurlijke is om wat tijd vrij te maken voor het analyseren van massaal onderdrukte analysatorwaarschuwingen en deze geleidelijk aan af te handelen. Ergens moet je fouten in de code herstellen, ergens moet je refactoren om de analysator te vertellen dat de code geen problemen oplevert. Eenvoudig voorbeeld:

if (a = b)

De meeste C++-compilers en -analyzers klagen over dergelijke code, omdat de kans groot is dat ze daadwerkelijk wilden schrijven (een == b). Maar er is een onuitgesproken overeenkomst, en dit wordt meestal vermeld in de documentatie, dat als er extra haakjes zijn, wordt aangenomen dat de programmeur opzettelijk dergelijke code heeft geschreven, en dat het niet nodig is om te zweren. Bijvoorbeeld in de PVS-Studio-documentatie voor diagnostiek V559 (CWE-481) er staat duidelijk geschreven dat de volgende regel als correct en veilig wordt beschouwd:

if ((a = b))

Een ander voorbeeld. Is het vergeten in deze C++-code? breken of niet?

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

De PVS-Studio-analysator geeft hier een waarschuwing V796 (CWE-484). Dit hoeft geen fout te zijn. In dat geval moet u de parser een hint geven door het attribuut toe te voegen [[fallthrough]] of bijvoorbeeld __kenmerk__((fallthrough)):

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

Er kan worden gezegd dat dergelijke codewijzigingen de bug niet oplossen. Ja, dat is waar, maar het doet twee nuttige dingen. Ten eerste verwijdert het analyserapport valse positieven. Ten tweede wordt de code begrijpelijker voor de mensen die betrokken zijn bij het onderhoud ervan. En dit is heel belangrijk! Alleen al daarom is het de moeite waard om kleine refactorings uit te voeren om de code duidelijker en gemakkelijker te onderhouden te maken. Omdat de analysator niet begrijpt of ‘break’ nodig is of niet, zal het ook onduidelijk zijn voor collega-programmeurs.

Naast bugfixes en refactorings kunt u duidelijk valse analyserwaarschuwingen specifiek onderdrukken. Sommige irrelevante diagnostiek kan worden uitgeschakeld. Iemand vindt bijvoorbeeld waarschuwingen zinloos V550 over het vergelijken van float/double-waarden. En sommigen classificeren ze als belangrijk en het bestuderen waard [7]. Welke waarschuwingen als relevant worden beschouwd en welke niet, is aan het ontwikkelteam om te beslissen.

Er zijn andere manieren om valse waarschuwingen te onderdrukken. Macro-opmaak werd bijvoorbeeld eerder genoemd. Dit alles wordt in meer detail beschreven in de documentatie. Het belangrijkste is dat u begrijpt dat als u geleidelijk en systematisch aan de slag gaat met valse positieven, er niets mis mee is. De overgrote meerderheid van oninteressante waarschuwingen verdwijnt na configuratie, en alleen plaatsen die echt zorgvuldige studie vereisen en enkele wijzigingen in de code blijven over.

Ook helpen we onze klanten altijd bij het opzetten van PVS-Studio als er zich problemen voordoen. Bovendien waren er gevallen waarin we zelf valse waarschuwingen elimineerden en fouten corrigeerden [8]. Voor de zekerheid heb ik besloten te vermelden dat deze optie voor uitgebreide samenwerking ook mogelijk is :).

Ratelmethode

Er is nog een interessante aanpak om de codekwaliteit geleidelijk te verbeteren door de statische analysatorwaarschuwing te elimineren. Het komt erop neer dat het aantal waarschuwingen alleen maar kan afnemen.

Hoe u een statische code-analysator in een bestaand project implementeert zonder het team te demotiveren

Het aantal waarschuwingen dat door de statische analysator wordt afgegeven, wordt geregistreerd. Quality Gate is zo geconfigureerd dat u nu alleen nog maar een code kunt invoeren die het aantal handelingen niet vergroot. Als gevolg hiervan begint het proces van het geleidelijk verminderen van het aantal alarmen met het aanpassen van de analysator en het corrigeren van fouten.

Zelfs als iemand een beetje vals wil spelen en besluit de kwaliteitspoort te passeren, niet door waarschuwingen in zijn nieuwe code te elimineren, maar door de oude code van derden te verbeteren, is dit niet eng. Toch draait de ratel in één richting en geleidelijk zal het aantal defecten afnemen. Zelfs als iemand zijn eigen nieuwe gebreken niet wil herstellen, zal hij toch iets in de aangrenzende code moeten verbeteren. Op een gegeven moment komt er een einde aan de gemakkelijke manieren om het aantal waarschuwingen te verminderen, en komt er een moment waarop echte bugs worden opgelost.

Deze methodologie wordt gedetailleerder beschreven in een zeer interessant artikel van Ivan Ponomarev "Implementeer statische analyses in het proces, in plaats van deze te gebruiken om bugs te vinden", die ik aanbeveel aan iedereen die geïnteresseerd is in het verbeteren van de codekwaliteit.

De auteur van het artikel heeft ook een rapport over dit onderwerp: "Continue statische analyse".

Conclusie

Ik hoop dat lezers na dit artikel de statische analysehulpmiddelen meer zullen accepteren en deze in het ontwikkelingsproces willen implementeren. Als u vragen heeft, staan ​​wij altijd klaar adviseren gebruikers van onze statische analysator PVS-Studio en hulp bij de implementatie ervan.

Er zijn nog andere typische twijfels over de vraag of statische analyse echt handig en nuttig kan zijn. Ik heb geprobeerd de meeste van deze twijfels weg te nemen in de publicatie “Redenen om de PVS-Studio statische code-analysator in het ontwikkelingsproces te introduceren” [9].

Bedankt voor uw aandacht en kom скачать en probeer de PVS-Studio-analysator.

Extra koppelingen

  1. Andrej Karpov. Hoe kan ik snel interessante waarschuwingen zien die de PVS-Studio-analysator produceert voor C- en C++-code?
  2. Wikipedia. De stelling van Rice.
  3. Andrej Karpov, Victoria Khanieva. Machine learning gebruiken bij statische analyse van programmabroncode.
  4. PVS-Studio. Documentatie. Aanvullende diagnostische instellingen.
  5. Andrej Karpov. Kenmerken van de PVS-Studio-analysator met behulp van het voorbeeld van EFL Core Libraries, 10-15% valse positieven.
  6. PVS-Studio. Documentatie. Massale onderdrukking van analysatorberichten.
  7. Ivan Andrjasjin. Over hoe we statische analyse hebben getest op ons project van een educatieve simulator voor röntgen-endovasculaire chirurgie.
  8. Pavel Eremeev, Svjatoslav Razmyslov. Hoe het PVS-Studio-team de Unreal Engine-code verbeterde.
  9. Andrej Karpov. Redenen om de statische code-analysator PVS-Studio in het ontwikkelingsproces te introduceren.

Hoe u een statische code-analysator in een bestaand project implementeert zonder het team te demotiveren

Als u dit artikel met een Engelssprekend publiek wilt delen, gebruik dan de vertaallink: Andrey Karpov. Hoe je een statische code-analysator in een bestaand project introduceert en het team niet ontmoedigt.

Bron: www.habr.com

Voeg een reactie