Com implementar un analitzador de codi estàtic en un projecte heretat sense desmotivar l'equip

Com implementar un analitzador de codi estàtic en un projecte heretat sense desmotivar l'equip
És fàcil provar un analitzador de codi estàtic. Però per implementar-lo, especialment en el desenvolupament d'un gran projecte antic, requereix habilitat. Si es fa incorrectament, l'analitzador pot afegir feina, frenar el desenvolupament i desmotivar l'equip. Parlem breument sobre com abordar correctament la integració de l'anàlisi estàtica en el procés de desenvolupament i començar a utilitzar-la com a part de CI/CD.

Introducció

Recentment em va cridar l'atenció la publicació "Com començar amb l'anàlisi estàtica sense aclaparar l'equip". D'una banda, aquest és un bon article que val la pena conèixer. D'altra banda, em sembla que encara no ofereix una resposta completa sobre com implementar sense dolor l'anàlisi estàtica en un projecte amb molt de codi heretat. L'article diu que podeu acceptar el deute tècnic i treballar només amb el codi nou, però no hi ha resposta sobre què fer amb aquest deute tècnic més endavant.

El nostre equip de PVS-Studio ofereix la seva visió sobre aquest tema. Vegem en primer lloc com sorgeix el problema d'implementar un analitzador de codi estàtic, com superar aquest problema i com eliminar gradualment el deute tècnic sense dolor.

Problemes

Normalment no és difícil llançar i veure com funciona un analitzador estàtic [1]. És possible que vegeu errors interessants o fins i tot vulnerabilitats potencials espantoses al codi. Fins i tot podeu arreglar alguna cosa, però després molts programadors es rendeixen.

Tots els analitzadors estàtics produeixen falsos positius. Aquesta és una característica de la metodologia d'anàlisi de codi estàtic i no es pot fer res. En el cas general, es tracta d'un problema insoluble, tal com confirma el teorema de Rice [2]. Els algorismes d'aprenentatge automàtic tampoc ajudaran [3]. Fins i tot si una persona no sempre pot saber si aquest o aquell codi és incorrecte, no hauríeu d'esperar això del programa :).

Els falsos positius no són un problema si l'analitzador estàtic ja està configurat:

  • Conjunts de regles irrellevants desactivats;
  • S'han desactivat alguns diagnòstics irrellevants;
  • Si parlem de C o C++, les macros es marquen que contenen construccions específiques que fan que apareguin advertències inútils a cada lloc on s'utilitzen aquestes macros;
  • Es marquen les funcions pròpies que realitzen accions similars a les funcions del sistema (el seu propi analògic memcpy o imprimirf) [4];
  • Els falsos positius es desactiven específicament mitjançant els comentaris;
  • I així successivament.

En aquest cas, podem esperar una taxa baixa de falsos positius d'un 10-15% [5]. En altres paraules, 9 de cada 10 advertències de l'analitzador indicaran un problema real al codi, o almenys un "codi de forta olor". D'acord, aquest escenari és extremadament agradable i l'analitzador és un veritable amic del programador.

Com implementar un analitzador de codi estàtic en un projecte heretat sense desmotivar l'equip
En realitat, en un projecte gran, la imatge inicial serà completament diferent. L'analitzador emet centenars o milers d'avisos per al codi heretat. És impossible entendre ràpidament quines d'aquestes advertències són rellevants i quines no. És irracional seure i començar a fer front a tots aquests avisos, ja que la feina principal en aquest cas s'aturarà durant dies o setmanes. Normalment, un equip no es pot permetre un escenari així. També hi haurà un gran nombre de diferències que fan malbé l'historial de canvis. I una ràpida edició massiva de tants fragments del codi, inevitablement, donarà lloc a nous errors d'ortografia i errors.

I el més important, aquesta gesta en la lluita contra les advertències té poc sentit. D'acord que, com que el projecte ha funcionat amb èxit durant molts anys, la majoria dels errors crítics ja s'han corregit. Sí, aquestes correccions eren molt cares, s'havien de depurar, rebre comentaris negatius dels usuaris sobre errors, etc. Un analitzador estàtic ajudaria a solucionar molts d'aquests errors en l'etapa de codificació, de manera ràpida i econòmica. Però de moment, d'una manera o altra, aquests errors s'han corregit, i l'analitzador detecta principalment errors no crítics en el codi antic. És possible que aquest codi no s'utilitzi, que s'utilitzi molt poques vegades i que un error no tingui conseqüències notables. Potser en algun lloc l'ombra del botó és del color incorrecte, però això no interfereix amb l'ús que fa ningú del producte.

Per descomptat, fins i tot els errors menors segueixen sent errors. I de vegades un error pot amagar una vulnerabilitat real. Tanmateix, renunciar a tot i passar dies/setmanes tractant defectes que amb prou feines es manifesten sembla una idea dubtosa.

Els programadors miren, miren, miren tots aquests avisos sobre l'antic codi de treball... I pensen: podem prescindir de l'anàlisi estàtica. Anem a escriure una nova funcionalitat útil.

A la seva manera, tenen raó. Pensen que primer s'han de desfer d'alguna manera de tots aquests avisos. Només així es podran beneficiar de l'ús regular de l'analitzador de codi. En cas contrari, els nous avisos simplement s'ofegaran amb els antics i ningú els prestarà atenció.

Aquesta és la mateixa analogia que amb les advertències del compilador. No és sense cap raó que recomanen mantenir el nombre d'avisos del compilador a 0. Si hi ha 1000 avisos, aleshores quan n'hi ha 1001, ningú hi prestarà atenció i no està clar on buscar aquest avís més recent.

Com implementar un analitzador de codi estàtic en un projecte heretat sense desmotivar l'equip
El pitjor d'aquesta història és si algú de dalt en aquest moment us obliga a utilitzar l'anàlisi de codi estàtic. Això només desmotivarà l'equip, ja que des del seu punt de vista hi haurà una complexitat burocràtica addicional que només s'interposarà. Ningú mirarà els informes de l'analitzador i tot ús serà només "en paper". Aquells. Formalment, l'anàlisi s'incorpora al procés DevOps, però a la pràctica això no beneficia ningú. Vam escoltar històries detallades dels assistents a la conferència als estands. Aquesta experiència pot dissuadir els programadors d'utilitzar eines d'anàlisi estàtica durant molt de temps, si no per sempre.

Implantació i eliminació del deute tècnic

De fet, no hi ha res difícil o espantós a introduir l'anàlisi estàtica fins i tot en un gran projecte antic.

CI / CD

A més, l'analitzador es pot convertir immediatament en part del procés de desenvolupament continu. Per exemple, la distribució PVS-Studio conté utilitats per visualitzar còmodament l'informe en el format que necessiteu i notificacions als desenvolupadors que han escrit seccions problemàtiques del codi. Per a aquells que estiguin més interessats a llançar PVS-Studio des de sistemes CI/CD, us recomano que us familiaritzeu amb els corresponents secció documentació i una sèrie d'articles:

Però tornem al problema d'un gran nombre de falsos positius en les primeres etapes d'implementació d'eines d'anàlisi de codi.

Arreglar el deute tècnic existent i fer front als nous avisos

Els analitzadors estàtics comercials moderns us permeten estudiar només els avisos nous que apareixen en codi nou o modificat. La implementació d'aquest mecanisme varia, però l'essència és la mateixa. A l'analitzador estàtic PVS-Studio, aquesta funcionalitat s'implementa de la següent manera.

Per començar ràpidament a utilitzar l'anàlisi estàtica, suggerim que els usuaris de PVS-Studio utilitzin el mecanisme per a la supressió massiva dels avisos [6]. La idea general és la següent. L'usuari va iniciar l'analitzador i va rebre molts avisos. Com que un projecte que s'ha desenvolupat durant molts anys està viu, desenvolupa i guanya diners, és probable que no hi hagi molts avisos a l'informe que indiquin defectes crítics. En altres paraules, els errors crítics ja s'han solucionat d'una manera o altra mitjançant mètodes més cars o gràcies als comentaris dels clients. En conseqüència, tot el que troba l'analitzador actualment es pot considerar deute tècnic, cosa que és impracticable intentar eliminar-ho immediatament.

Podeu dir-li a PVS-Studio que consideri aquests avisos irrellevants de moment (deseu el deute tècnic per a més endavant) i ja no els mostrarà. L'analitzador crea un fitxer especial on desa informació sobre errors que encara no són interessants. I ara PVS-Studio emetrà avisos només per al codi nou o modificat. A més, tot això s'implementa de manera intel·ligent. Si, per exemple, s'afegeix una línia buida a l'inici del fitxer de codi font, l'analitzador entén que, de fet, no ha canviat res i seguirà en silenci. Aquest fitxer de marcatge es pot posar en un sistema de control de versions. El fitxer és gran, però això no és un problema, ja que no té sentit emmagatzemar-lo sovint.

Ara tots els programadors veuran avisos relacionats només amb el codi nou o modificat. Així, podeu començar a utilitzar l'analitzador, com diuen, a partir de l'endemà. I podeu tornar al deute tècnic més tard, corregir errors gradualment i configurar l'analitzador.

Així, s'ha resolt el primer problema amb la implementació de l'analitzador en un gran projecte antic. Ara anem a esbrinar què fer amb el deute tècnic.

Correcció d'errors i refactorització

El més senzill i natural és reservar un temps per analitzar els avisos de l'analitzador suprimits massivament i tractar-los gradualment. En algun lloc hauríeu de corregir els errors del codi, en algun lloc hauríeu de refactoritzar per dir a l'analitzador que el codi no és problemàtic. Exemple senzill:

if (a = b)

La majoria dels compiladors i analitzadors de C++ es queixen d'aquest codi, ja que hi ha una gran probabilitat que realment volguessin escriure (a == b). Però hi ha un acord tàcit, i això sol assenyalar-se a la documentació, que si hi ha parèntesis addicionals, es considera que el programador va escriure aquest codi deliberadament i no cal jurar. Per exemple, a la documentació de diagnòstic de PVS-Studio V559 (CWE-481) està clarament escrit que la línia següent es considerarà correcta i segura:

if ((a = b))

Un altre exemple. S'oblida en aquest codi C++? trencar o no?

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

L'analitzador PVS-Studio emetrà un avís aquí V796 (CWE-484). Pot ser que això no sigui un error, en aquest cas hauríeu de donar una pista a l'analitzador afegint l'atribut [[caiguda]] o per exemple __atribut__((fallthrough)):

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

Es pot dir que aquests canvis de codi no solucionen l'error. Sí, això és cert, però fa dues coses útils. En primer lloc, l'informe de l'analitzador elimina els falsos positius. En segon lloc, el codi es fa més entenedor per a les persones implicades en el seu manteniment. I això és molt important! Només per això, val la pena realitzar petites refactoritzacions per fer el codi més clar i fàcil de mantenir. Atès que l'analitzador no entén si es necessita "ruptura" o no, tampoc serà clar per als altres programadors.

A més de les correccions d'errors i les refactoritzacions, podeu suprimir específicament els avisos de l'analitzador òbviament falsos. Alguns diagnòstics irrellevants es poden desactivar. Per exemple, algú pensa que els avisos no tenen sentit V550 sobre la comparació de valors float/double. I alguns els classifiquen com a importants i dignes d'estudi [7]. Quins avisos es consideren rellevants i quins no ho són, depèn de l'equip de desenvolupament.

Hi ha altres maneres de suprimir les alertes falses. Per exemple, el marcatge macro es va esmentar anteriorment. Tot això es descriu amb més detall a la documentació. El més important és entendre que si t'acostes a treballar de manera gradual i sistemàtica amb falsos positius, no hi ha res dolent. La gran majoria dels avisos poc interessants desapareixen després de la configuració, i només queden llocs que realment requereixen un estudi acurat i alguns canvis en el codi.

A més, sempre ajudem els nostres clients a configurar PVS-Studio si sorgeixen dificultats. A més, hi va haver casos en què nosaltres mateixos vam eliminar els avisos falsos i vam corregir errors [8]. Per si de cas, vaig decidir esmentar que aquesta opció per a la cooperació ampliada també és possible :).

Mètode de trinquet

Hi ha un altre enfocament interessant per millorar gradualment la qualitat del codi eliminant l'avís de l'analitzador estàtic. La conclusió és que el nombre d'avisos només pot disminuir.

Com implementar un analitzador de codi estàtic en un projecte heretat sense desmotivar l'equip

Es registra el nombre d'avisos emesos per l'analitzador estàtic. La porta de qualitat està configurada de manera que ara només podeu introduir un codi que no augmenti el nombre d'operacions. Com a resultat, el procés de reducció gradual del nombre d'alarmes comença ajustant l'analitzador i corregint errors.

Fins i tot si una persona vol enganyar una mica i decideix passar la porta de qualitat no eliminant els avisos del seu nou codi, sinó millorant l'antic codi de tercers, això no fa por. Tot i així, el trinquet gira en una direcció i, a poc a poc, el nombre de defectes anirà disminuint. Fins i tot si una persona no vol solucionar els seus propis defectes nous, encara haurà de millorar alguna cosa al codi veí. En algun moment, les maneres fàcils de reduir el nombre d'avises s'acaben i arriba un moment en què es solucionaran errors reals.

Aquesta metodologia es descriu amb més detall en un article molt interessant d'Ivan Ponomarev "Implementeu l'anàlisi estàtica al procés, en lloc d'utilitzar-la per trobar errors", que recomano llegir a qualsevol persona interessada a millorar la qualitat del codi.

L'autor de l'article també té un informe sobre aquest tema: "Anàlisi estàtica contínua".

Conclusió

Espero que després d'aquest article, els lectors acceptin més les eines d'anàlisi estàtica i vulguin implementar-les en el procés de desenvolupament. Si teniu cap pregunta, sempre estem preparats aconsellar usuaris del nostre analitzador estàtic PVS-Studio i ajuda amb la seva implementació.

Hi ha altres dubtes típics sobre si l'anàlisi estàtica pot ser realment convenient i útil. Vaig intentar dissipar la majoria d'aquests dubtes a la publicació "Raons per introduir l'analitzador de codi estàtic PVS-Studio en el procés de desenvolupament" [9].

Gràcies per la vostra atenció i veniu descarregar i proveu l'analitzador PVS-Studio.

Enllaços addicionals

  1. Andrei Karpov. Com puc veure ràpidament els avisos interessants que produeix l'analitzador PVS-Studio per al codi C i C++?
  2. Wikipedia. Teorema de Rice.
  3. Andrey Karpov, Victòria Khanieva. Utilitzar l'aprenentatge automàtic en l'anàlisi estàtica del codi font del programa.
  4. PVS-Studio. Documentació. Paràmetres de diagnòstic addicionals.
  5. Andrei Karpov. Característiques de l'analitzador PVS-Studio utilitzant l'exemple de les biblioteques EFL Core, 10-15% de falsos positius.
  6. PVS-Studio. Documentació. Supressió massiva de missatges de l'analitzador.
  7. Ivan Andryashin. Sobre com vam provar l'anàlisi estàtica en el nostre projecte de simulador educatiu de cirurgia endovascular de raigs X.
  8. Pavel Eremeev, Sviatoslav Razmyslov. Com l'equip de PVS-Studio va millorar el codi Unreal Engine.
  9. Andrei Karpov. Raons per introduir l'analitzador de codi estàtic PVS-Studio en el procés de desenvolupament.

Com implementar un analitzador de codi estàtic en un projecte heretat sense desmotivar l'equip

Si voleu compartir aquest article amb un públic de parla anglesa, utilitzeu l'enllaç de traducció: Andrey Karpov. Com introduir un analitzador de codi estàtic en un projecte heretat i no desanimar l'equip.

Font: www.habr.com

Afegeix comentari