{"id":32848,"date":"2019-10-31T21:49:16","date_gmt":"2019-10-31T18:49:16","guid":{"rendered":"https:\/\/prohoster.info\/blog\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\/"},"modified":"2019-10-31T21:49:16","modified_gmt":"2019-10-31T18:49:16","slug":"vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","title":{"rendered":"Integra l'analisi statica nel processo, invece di cercare bug con essa","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>La mia scrittura di questo articolo \u00e8 stata stimolata da un gran numero di materiali sull'analisi statica, che sempre pi\u00f9 frequentemente attiravano la mia attenzione. Prima di tutto, \u00e8 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/pvs-studio\/blog\/\">il blog PVS-studio<\/a><\/noindex>, che promuove attivamente se stesso su Habr tramite recensioni sugli errori trovati dai loro strumenti in progetti open-source. Recentemente PVS-studio ha implementato <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/pvs-studio\/blog\/436496\/\">il supporto per Java<\/a><\/noindex>, e naturalmente, gli sviluppatori di IntelliJ IDEA, il cui analizzatore integrato \u00e8 attualmente, probabilmente, il pi\u00f9 avanzato per Java, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/en\/company\/JetBrains\/blog\/436278\/\">non potevano rimanere indifferenti<\/a><\/noindex>. <\/p>\n<p>Leggendo tali recensioni si ha l'impressione che si tratti di un elisir magico: premi il pulsante e voil\u00e0, ecco la lista dei difetti davanti a te. Sembra che con il perfezionamento degli analizzatori, i bug verranno trovati automaticamente in numero sempre maggiore, e i prodotti scansionati da questi robot diventeranno sempre migliori, senza alcuno sforzo da parte nostra.<\/p>\n<p>Ma non ci sono elisir magici. Vorrei parlare di ci\u00f2 di cui di solito non si discute nei post del tipo \"ecco cosa pu\u00f2 trovare il nostro robot\": cosa non possono fare gli analizzatori, qual \u00e8 il loro ruolo reale e il loro posto nel processo di consegna del software, e come implementarli correttamente.<\/p>\n<p><img decoding=\"async\" alt=\"Integra l&#039;analisi statica nel processo, invece di cercare bug con essa\" src=\"\/wp-content\/uploads\/2019\/05\/2a0339f10edcaed3310676ab6e2f975a.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ruota dentata (fonte: <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A5%D1%80%D0%B0%D0%BF%D0%BE%D0%B2%D0%BE%D0%B9_%D0%BC%D0%B5%D1%85%D0%B0%D0%BD%D0%B8%D0%B7%D0%BC#\/media\/File:Sperrklinke_Schema.svg\">Wikipedia<\/a><\/noindex>).<\/i><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Cosa non potranno mai fare gli analizzatori statici<\/h2>\n<p>\nCosa significa, dal punto di vista pratico, analizzare il codice sorgente? Forniamo alcuni sorgenti in input e in breve tempo (molto pi\u00f9 breve rispetto all'esecuzione dei test) otteniamo alcune informazioni sul nostro sistema. La limitazione fondamentale e matematicamente insormontabile consiste nel fatto che possiamo ottenere in questo modo solo una classe piuttosto ristretta di informazioni.<\/p>\n<p>Il pi\u00f9 famoso esempio di un problema irrisolvibile tramite analisi statica \u00e8 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Halting_problem\">il problema dell'arresto<\/a><\/noindex>: \u00e8 un teorema che dimostra che non \u00e8 possibile sviluppare un algoritmo generale in grado di determinare, a partire dal codice sorgente di un programma, se esso entrer\u00e0 in un ciclo infinito o terminer\u00e0 in un tempo finito. L'estensione di questo teorema \u00e8 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Rice%27s_theorem\">il teorema di Rice<\/a><\/noindex>, che afferma che, per qualsiasi propriet\u00e0 non banale delle funzioni calcolabili, la definizione di se un programma arbitrario calcola una funzione con tale propriet\u00e0 \u00e8 un problema algoritmicamente non risolvibile. Ad esempio, \u00e8 impossibile scrivere un analizzatore che, dato qualsiasi codice sorgente, determini se il programma analizzato \u00e8 l'implementazione di un algoritmo che calcola, per esempio, il quadrato di un intero.<\/p>\n<p>Pertanto, la funzionalit\u00e0 degli analizzatori statici presenta limitazioni insormontabili. Un analizzatore statico non sar\u00e0 mai in grado di determinare in tutti i casi cose come, ad esempio, l'insorgere di un \u00abnull pointer exception\u00bb nei linguaggi che ammettono un valore null, o di identificare in tutti i casi l'insorgere di un \u00abattribute not found\u00bb nei linguaggi con tipizzazione dinamica. Tutto ci\u00f2 che il pi\u00f9 sofisticato analizzatore statico pu\u00f2 fare \u00e8 evidenziare casi particolari, il cui numero rispetto a tutti i problemi possibili nel vostro codice sorgente \u00e8, senza esagerare, una goccia nell'oceano.<\/p>\n<h2>L'analisi statica non \u00e8 ricerca di bug.<\/h2>\n<p>\nDa quanto detto sopra si conclude: l'analisi statica non \u00e8 uno strumento per ridurre il numero di difetti in un programma. Oso affermare che, quando applicata per la prima volta al vostro progetto, essa trover\u00e0 nel codice dei punti 'interessanti', ma molto probabilmente non trover\u00e0 difetti che influiscono sulla qualit\u00e0 del lavoro del vostro programma.<\/p>\n<p>Esempi di difetti trovati automaticamente dagli analizzatori sono impressionanti, ma non bisogna dimenticare che questi esempi sono stati trovati grazie alla scansione di un ampio set di grandi basi di codice. Allo stesso modo, gli hacker che hanno la possibilit\u00e0 di provare diverse semplici password su un gran numero di account, alla fine trovano quegli account con password semplici.<\/p>\n<p>Questo significa che non bisogna applicare l'analisi statica? Certo che no! E per lo stesso motivo per cui \u00e8 utile controllare ogni nuova password per vedere se finisce nella lista nera delle 'password semplici'.<\/p>\n<h2>L'analisi statica \u00e8 pi\u00f9 della semplice ricerca di bug.<\/h2>\n<p>\nIn realt\u00e0, i compiti risolvibili tramite analisi sono molto pi\u00f9 ampi. Infatti, in generale, l'analisi statica \u00e8 qualsiasi verifica del sorgente, effettuata prima della loro esecuzione. Ecco alcune cose che si possono fare:<\/p>\n<ul>\n<li> Verifica dello stile di codifica in senso ampio. Questa include sia il controllo della formattazione, sia la ricerca di utilizzi di parentesi vuote\/extra, l'impostazione di soglie per metriche come il numero di righe \/ complessit\u00e0 ciclomatica del metodo, ecc. \u2014 insomma, tutto ci\u00f2 che potenzialmente ostacola la leggibilit\u00e0 e la manutenibilit\u00e0 del codice. In Java, uno di questi strumenti \u00e8 Checkstyle, in Python \u2014 flake8. I programmi di questa categoria sono comunemente chiamati \"linters\".<\/li>\n<li>Non solo il codice eseguibile pu\u00f2 essere analizzato. I file di risorse, come JSON, YAML, XML, .properties possono (e devono!) essere automaticamente verificati per la validit\u00e0. \u00c8 meglio sapere che a causa di qualche virgolette non abbinate la struttura del JSON \u00e8 rotta in un fase precoce di verifica automatica del Pull Request, piuttosto che durante l'esecuzione dei test o a Run time? Gli strumenti appropriati sono disponibili: ad esempio, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/adrienverge\/yamllint\">YAMLlint<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/zaach\/jsonlint\">JSONLint<\/a><\/noindex>.<\/li>\n<li> La compilazione (o il parsing per i linguaggi di programmazione dinamici) \u00e8 anch'essa una forma di analisi statica. Di solito, i compilatori sono in grado di emettere avvisi che segnalano problemi con la qualit\u00e0 del codice sorgente e non dovrebbero essere ignorati.<\/li>\n<li>A volte la compilazione non \u00e8 solo la compilazione del codice eseguibile. Ad esempio, se hai della documentazione in formato <noindex><a rel=\"nofollow\" href=\"https:\/\/asciidoctor.org\/\">AsciiDoctor<\/a><\/noindex>, al momento della sua trasformazione in HTML\/PDF, il processore AsciiDoctor (<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/asciidoctor\/asciidoctor-maven-plugin\">Maven plugin<\/a><\/noindex>) pu\u00f2 emettere avvisi, ad esempio, su collegamenti interni interrotti. E questo \u00e8 un motivo valido per non accettare un Pull Request con modifiche alla documentazione.<\/li>\n<li>Il controllo ortografico \u00e8 anch'esso una forma di analisi statica. L'utilit\u00e0 <noindex><a rel=\"nofollow\" href=\"http:\/\/aspell.net\/\">aspell<\/a><\/noindex> \u00e8 in grado di controllare l'ortografia non solo nella documentazione, ma anche nei codici sorgente dei programmi (commenti e letterali) in vari linguaggi di programmazione, tra cui C\/C++, Java e Python. Un errore di ortografia in un'interfaccia utente o nella documentazione \u00e8 anch'esso un difetto!<\/li>\n<li>I test di configurazione (per cosa siano \u2014 vedi <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=KaeEjsAjV6A&amp;index=30&amp;list=PLsVTVVvrKX9tuYyCtL8mASB6IOaa-kRCA&amp;t=0s\">questo<\/a><\/noindex> e <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=Tk_nmV-mWOA\">questo<\/a><\/noindex> relazioni), sebbene eseguiti in un ambiente di esecuzione di test unitari come pytest, sono in effetti una forma di analisi statica, poich\u00e9 non eseguono i codici sorgente durante il loro funzionamento.<\/li>\n<\/ul>\n<p>\nCome possiamo vedere, la ricerca di bug in questo elenco assume un ruolo di minor importanza, mentre tutto il resto \u00e8 accessibile utilizzando strumenti open source gratuiti.<\/p>\n<p>Quali di questi tipi di analisi statica dovresti applicare al tuo progetto? Certamente, tutti, pi\u00f9 ce ne sono \u2014 meglio \u00e8! L'importante \u00e8 implementare tutto correttamente, di cui parleremo pi\u00f9 avanti.<\/p>\n<h2>Il processo di fornitura come filtro multistrato e l'analisi statica come il primo stadio<\/h2>\n<p>\nLa metafora classica dell'integrazione continua \u00e8 un tubo (pipeline), attraverso il quale scorrono le modifiche \u2014 dalla modifica del codice sorgente alla consegna in produzione. La sequenza standard delle fasi di questo processo \u00e8:<\/p>\n<ol>\n<li>analisi statica<\/li>\n<li>compilazione<\/li>\n<li>test unitari<\/li>\n<li>test di integrazione<\/li>\n<li>test UI<\/li>\n<li>verifica manuale<\/li>\n<\/ol>\n<p>\nLe modifiche respinte alla fase N non vengono trasferite alla fase N+1.<\/p>\n<p>Perch\u00e9 proprio in questo modo e non in un altro? Nella parte del processo che riguarda i test, i tester conoscono la famosa piramide dei test.<\/p>\n<p><img decoding=\"async\" alt=\"Integra l&#039;analisi statica nel processo, invece di cercare bug con essa\" src=\"\/wp-content\/uploads\/2019\/05\/f155307fd4c1663800843c394098ea6f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>La piramide dei test. Fonte: <noindex><a rel=\"nofollow\" href=\"https:\/\/martinfowler.com\/bliki\/TestPyramid.html\">su Habr.<\/a><\/noindex> Martin Fowler.<\/i><\/p>\n<p>Nella parte inferiore di questa piramide si trovano i test pi\u00f9 facili da scrivere, che vengono eseguiti pi\u00f9 rapidamente e non tendono a falsi positivi. Pertanto, dovrebbero esserci di pi\u00f9, dovrebbero coprire pi\u00f9 codice e vengono eseguiti per primi. Nella parte superiore della piramide, invece, la situazione \u00e8 opposta; quindi, il numero di test di integrazione e UI dovrebbe essere ridotto al minimo necessario. L'essere umano in questa catena \u00e8 la risorsa pi\u00f9 costosa, lenta e inaffidabile, quindi si trova alla fine e lavora solo se le fasi precedenti non hanno rilevato difetti. Tuttavia, le stesse linee guida vengono utilizzate per costruire il processo anche nelle parti non direttamente legate ai test!<\/p>\n<p>Vorrei proporre un'analogia con un sistema di filtraggio dell'acqua a pi\u00f9 stadi. In ingresso viene fornita acqua sporca (modifiche con difetti), mentre in uscita dobbiamo ottenere acqua pulita, con tutte le impurit\u00e0 indesiderate filtrate.<\/p>\n<p><img decoding=\"async\" alt=\"Integra l&#039;analisi statica nel processo, invece di cercare bug con essa\" src=\"\/wp-content\/uploads\/2019\/05\/76b5be8f13d55c16970d67e09767a045.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Filtro multistrato. Fonte: <noindex><a rel=\"nofollow\" href=\"https:\/\/commons.wikimedia.org\/wiki\/File:Milli-Q_Water_filtration_station.JPG\">Wikimedia Commons<\/a><\/noindex><\/i><\/p>\n<p>Come \u00e8 noto, i filtri di pulizia sono progettati in modo che ogni successivo stadio possa separare frazioni sempre pi\u00f9 sottili di contaminanti. A tal fine, gli stadi di depurazione pi\u00f9 grossolani hanno una maggiore capacit\u00e0 di flusso e un costo inferiore. Nella nostra analogia, questo significa che i quality gates in ingresso hanno una maggiore reattivit\u00e0, richiedono meno sforzi per essere attivati e sono di per s\u00e9 pi\u00f9 semplici da gestire \u2014 e sono strutturati seguendo proprio questa sequenza. Il ruolo dell'analisi statica, che, come ora comprendiamo, \u00e8 capace di filtrare solo i difetti pi\u00f9 evidenti, \u00e8 quello di una griglia \u00abseparatrice\u00bb all'inizio del cascata di filtri.<\/p>\n<p>L'analisi statica di per s\u00e9 non migliora la qualit\u00e0 del prodotto finale, proprio come un separatore non rende potabile l'acqua. Eppure, nella sua totale integrazione con altri elementi della catena di produzione, la sua importanza \u00e8 evidente. Anche se in un filtro a pi\u00f9 stadi gli stadi di uscita possono potenzialmente catturare tutto ci\u00f2 che gli stadi di ingresso rilevano, \u00e8 chiaro a quali conseguenze conduce il tentativo di affidarsi esclusivamente a stadi di depurazione fine, senza quelli d'ingresso.<\/p>\n<p>L'obiettivo del separatore \u00e8 quello di alleggerire gli stadi successivi dalla cattura di difetti davvero grossolani. Ad esempio, almeno la persona che esegue la revisione del codice non dovrebbe distogliere l'attenzione da un codice mal formattato o dalla violazione delle norme di codifica stabilite (come parentesi superflue o ramificazioni troppo approfondite). I bug come NPE dovrebbero essere catturati dai test di unit\u00e0, ma se prima del test l'analizzatore ci indica che un bug accadr\u00e0 inevitabilmente, questo accelerer\u00e0 significativamente la sua correzione.<\/p>\n<p>Ritengo sia ora chiaro perch\u00e9 l'analisi statica non migliora la qualit\u00e0 del prodotto se applicata in modo episodico e deve essere utilizzata costantemente per filtrare i cambiamenti con difetti gravi. La domanda se l'uso di un analizzatore statico migliorer\u00e0 la qualit\u00e0 del tuo prodotto \u00e8 approssimativamente equivalente a chiedere: \u00abla qualit\u00e0 potabile dell'acqua prelevata da una fonte inquinata migliorer\u00e0 se la si passer\u00e0 attraverso un colino?\u00bb<\/p>\n<h2>Implementazione nel progetto legacy<\/h2>\n<p>\nUna domanda pratica importante: come integrare l'analisi statica nel processo di integrazione continua come \"quality gate\"? Nel caso dei test automatici, tutto \u00e8 chiaro: c'\u00e8 un insieme di test, la mancata esecuzione di uno di essi \u00e8 un motivo sufficiente per considerare che la build non ha superato il quality gate. Tentare di stabilire un gate basato sui risultati dell'analisi statica fallisce: nel codice legacy ci sono troppe avvertenze dell'analisi, non vogliamo ignorarle completamente, ma non possiamo fermare la consegna del prodotto solo perch\u00e9 ci sono avvertenze dell'analizzatore.<\/p>\n<p>Quando viene applicato per la prima volta, l'analizzatore fornisce un'enorme quantit\u00e0 di avvertenze, la stragrande maggioranza delle quali non ha nulla a che fare con il corretto funzionamento del prodotto. Correggere immediatamente tutte queste osservazioni non \u00e8 possibile, e molti non \u00e8 nemmeno necessario. Dopotutto, sappiamo che il nostro prodotto in generale funziona, anche prima dell'integrazione dell'analisi statica!<\/p>\n<p>Di conseguenza, molti si limitano a un uso episodico dell'analisi statica o la usano solo in modalit\u00e0 informativa, quando durante la build viene semplicemente emesso un rapporto dell'analizzatore. Questo \u00e8 equivalente all'assenza di qualsiasi analisi, perch\u00e9 se abbiamo gi\u00e0 un certo numero di avvertenze, l'emergere di un'altra (per quanto grave) durante la modifica del codice rimane inosservato.<\/p>\n<p>Sono noti i seguenti metodi per implementare quality gates:<\/p>\n<ul>\n<li>Impostazione di un limite sul numero totale di avvertenze o sul numero di avvertenze diviso per il numero di righe di codice. Questo funziona male, poich\u00e9 tale gate consente liberamente modifiche con nuovi difetti finch\u00e9 il loro limite non viene superato.<\/li>\n<li>La registrazione, in un dato momento, di tutti gli avvisi precedenti nel codice come ignorati, e il rifiuto della compilazione in caso di nuovi avvisi. Questa funzionalit\u00e0 \u00e8 fornita da PVS-studio e alcune risorse online, come Codacy. Non ho avuto esperienza con PVS-studio, ma per quanto riguarda la mia esperienza con Codacy, il loro problema principale \u00e8 che determinare cosa sia un errore \"vecchio\" e cosa sia un errore \"nuovo\" \u00e8 un algoritmo piuttosto complesso e non sempre corretto, soprattutto se i file subiscono modifiche radicali o vengono rinominati. A quanto ricordo, Codacy poteva trascurare nuovi avvisi in una pull request, e allo stesso tempo non permettere una pull request a causa di avvisi non relativi alle modifiche nel codice di quella PR.<\/li>\n<li>A mio avviso, la soluzione pi\u00f9 efficace \u00e8 quella descritta nel libro <noindex><a rel=\"nofollow\" href=\"https:\/\/www.amazon.com\/Continuous-Delivery-Deployment-Automation-Addison-Wesley\/dp\/0321601912\">Continuous Delivery<\/a><\/noindex> il \"metodo a cricchetto\". L'idea principale \u00e8 che ogni rilascio \u00e8 caratterizzato dal numero di avvisi di analisi statica, e sono consentite solo le modifiche che non aumentano il numero complessivo di avvisi.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Cricchetto<\/h2>\n<p>\nFunziona in questo modo:<\/p>\n<ol>\n<li>Nella fase iniziale, viene registrato nei metadati del rilascio il numero di avvisi nel codice trovati dagli analizzatori. In questo modo, durante la compilazione del ramo principale, il tuo gestore di repository registra non solo \"rilascio 7.0.2\", ma \"rilascio 7.0.2, contenente 100500 avvisi di Checkstyle\". Se utilizzi un gestore di repository avanzato (come Artifactory), \u00e8 facile mantenere tali metadati sul tuo rilascio.<\/li>\n<li>Ora ogni pull request, durante la compilazione, confronta il numero di avvisi ottenuti con quello attualmente presente nel rilascio. Se il PR porta a un aumento di questo numero, il codice non supera il controllo qualit\u00e0 dell'analisi statica. Se il numero di avvisi diminuisce o rimane invariato, allora passa.<\/li>\n<li>Nel prossimo rilascio, il numero di avvisi ricalcolato sar\u00e0 nuovamente registrato nei metadati del rilascio.<\/li>\n<\/ol>\n<p>\nCos\u00ec, poco a poco, ma con costanza (come nel lavoro di un cricchetto), il numero di avvisi tender\u00e0 a zero. Certo, il sistema pu\u00f2 essere ingannato inserendo un nuovo avviso ma correggendo uno gi\u00e0 esistente. Questo \u00e8 normale, poich\u00e9 a lungo termine porta risultati: gli avvisi vengono corretti non singolarmente, ma generalmente in gruppo per un certo tipo, e tutti gli avvisi facilmente risolvibili vengono eliminati piuttosto rapidamente.<\/p>\n<p>Questo grafico mostra il numero totale di avvisi di Checkstyle per sei mesi di lavoro di questo \"cricchetto\" su <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\">uno dei nostri progetti OpenSource<\/a><\/noindex>. Il numero di avvisi \u00e8 diminuito di un ordine di grandezza, \u00e8 avvenuto in modo naturale, parallelamente allo sviluppo del prodotto!<\/p>\n<p><img decoding=\"async\" alt=\"Integra l&#039;analisi statica nel processo, invece di cercare bug con essa\" src=\"\/wp-content\/uploads\/2019\/05\/9529bb2fb32187057088e8d2c4203333.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nUso una versione modificata di questo metodo, contando separatamente gli avvisi suddivisi per moduli del progetto e strumenti di analisi. Il file YAML dei metadati di compilazione che si forma appare all'incirca come segue:<\/p>\n<pre><code class=\"plaintext\">celesta-sql:\n  checkstyle: 434\n  spotbugs: 45\ncelesta-core:\n  checkstyle: 206\n  spotbugs: 13\ncelesta-maven-plugin:\n  checkstyle: 19\n  spotbugs: 0\ncelesta-unit:\n  checkstyle: 0\n  spotbugs: 0\n<\/code><\/pre>\n<p>\nIn qualsiasi sistema CI avanzato, il \"cricchetto\" pu\u00f2 essere implementato per qualsiasi strumento di analisi statica, senza dipendere da plugin e strumenti esterni. Ogni analizzatore produce il proprio rapporto in formato testo semplice o XML, facilmente analizzabile. Resta solo da scrivere la logica necessaria nello script CI. \u00c8 possibile vedere come \u00e8 implementato nei nostri progetti open source basati su Jenkins e Artifactory <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/2bass\/blob\/dev\/Jenkinsfile\">qui<\/a><\/noindex> o <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\/blob\/dev\/Jenkinsfile\">qui<\/a><\/noindex>. Entrambi gli esempi dipendono dalla libreria <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/inponomarev\/ratchetlib\">ratchetlib<\/a><\/noindex>: il metodo <code>countWarnings()<\/code> conta normalmente i tag xml nei file generati da Checkstyle e Spotbugs, mentre <code>compareWarningMaps()<\/code> implementa proprio quel cricchetto, lanciando un errore nel caso in cui il numero di avvisi in una delle categorie aumenti.<\/p>\n<p>Un'interessante variante di implementazione del \u00abriavvio\u00bb \u00e8 possibile per l'analisi dell'ortografia dei commenti, dei letterali testuali e della documentazione utilizzando aspell. Come \u00e8 noto, durante il controllo ortografico non tutte le parole sconosciute al dizionario standard sono errate; possono essere aggiunte al dizionario personale. Se si fa del dizionario personale parte del codice sorgente del progetto, allora il quality gate per l'ortografia pu\u00f2 essere formulato in questo modo: eseguire aspell con il dizionario standard e quello personale. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/CourseOrchestra\/celesta\/blob\/271dcfc8dc3ad65ac2d1dcaa39b7fd3ea8fb5891\/Jenkinsfile#L36\">non deve<\/a><\/noindex> trovare errori di ortografia.<\/p>\n<h2>Sull'importanza di fissare la versione dell'analizzatore<\/h2>\n<p>\nIn conclusione, \u00e8 importante notare quanto segue: qualunque sia il modo in cui introducete l'analisi nel vostro pipeline di distribuzione, la versione dell'analizzatore deve essere fissata. Se si permette un aggiornamento spontaneo dell'analizzatore, durante la costruzione di una nuova pull request possono \u00abemergere\u00bb nuovi difetti, non legati a modifiche nel codice, ma al fatto che il nuovo analizzatore \u00e8 semplicemente in grado di trovare pi\u00f9 difetti, e questo interromper\u00e0 il vostro processo di accettazione delle pull request. L'aggiornamento dell'analizzatore deve essere un'azione consapevole. Comunque, la fissazione rigida della versione di ciascun componente della build \u00e8 un requisito necessario e un tema per una conversazione separata.<\/p>\n<h2>Conclusioni<\/h2>\n<p><\/p>\n<ul>\n<li>L'analisi statica non trover\u00e0 bug e non migliorer\u00e0 la qualit\u00e0 del vostro prodotto come risultato di un'applicazione occasionale. Un effetto positivo sulla qualit\u00e0 \u00e8 dato solo dalla sua applicazione costante nel processo di distribuzione.<\/li>\n<li>La ricerca di bug non \u00e8 affatto l'obiettivo principale dell'analisi; la stragrande maggioranza delle funzioni utili \u00e8 disponibile in strumenti open source.<\/li>\n<li>Implementate quality gates in base ai risultati dell'analisi statica sin dal primo stadio del pipeline di distribuzione, utilizzando il \u00abriavvio\u00bb per il codice legacy.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Link<\/h2>\n<p><\/p>\n<ol>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.amazon.com\/Continuous-Delivery-Deployment-Automation-Addison-Wesley\/dp\/0321601912\">Continuous Delivery<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=8Cx3LHNjI24\">A. Kudrjavcev: Analisi dei programmi: come capire se sei un buon programmatore<\/a><\/noindex> relazione su diversi metodi di analisi del codice (non solo statici!)<\/li>\n<\/ol>\n<p>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/436868\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u044d\u0442\u043e \u0431\u043b\u043e\u0433 PVS-studio, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0434\u0432\u0438\u0433\u0430\u0435\u0442 \u0441\u0435\u0431\u044f \u043d\u0430 \u0425\u0430\u0431\u0440\u0435 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u0431\u0437\u043e\u0440\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a, \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u041d\u0435\u0434\u0430\u0432\u043d\u043e PVS-studio \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Java, \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 IntelliJ IDEA, \u0447\u0435\u0439 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24622,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32848","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0412\u043d\u0435\u0434\u0440\u044f\u0439\u0442\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0430 \u043d\u0435 \u0438\u0449\u0438\u0442\u0435 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0430\u0433\u0438 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:49:16+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:49:16+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Implementate l'analisi statica nel processo, non cercate bug con essa | ProHoster","description":"La scrittura di questo articolo \u00e8 stata ispirata da una grande quantit\u00e0 di materiali sull'analisi statica, sempre pi\u00f9 frequentemente sott'occhio.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0412\u043d\u0435\u0434\u0440\u044f\u0439\u0442\u0435 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0430 \u043d\u0435 \u0438\u0449\u0438\u0442\u0435 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0430\u0433\u0438 | ProHoster","og:description":"\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e \u043c\u0435\u043d\u044f \u0441\u043f\u043e\u0434\u0432\u0438\u0433\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0430\u043d\u0430\u043b\u0438\u0437\u0435, \u0432\u0441\u0451 \u0447\u0430\u0449\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043d\u0430 \u0433\u043b\u0430\u0437\u0430.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/vnedryajte-staticheskij-analiz-v-protsess-a-ne-ishhite-s-ego-pomoshhyu-bagi","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:49:16+00:00","article:modified_time":"2019-10-31T18:49:16+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32848","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 12:50:20","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:51:27","updated":"2026-01-21 12:50:20","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/32848","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=32848"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/32848\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/24622"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=32848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=32848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=32848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}