静的分析をバグの発芋に䜿甚するのではなく、プロセスに実装したす。

この蚘事を曞くきっかけずなったのは、静的解析に関する倧量の資料がたすたす私の泚目を集めるようになったこずでした。 たず、これ PVS スタゞオのブログは、オヌプン゜ヌス プロゞェクトでツヌルによっお芋぀かった゚ラヌのレビュヌを利甚しお、Habré で積極的に宣䌝しおいたす。 最近 PVS-studio が実装されたした Javaのサポヌトそしおもちろん、IntelliJ IDEA の開発者たち (その組み蟌みアナラむザはおそらく今日の Java にずっお最も先進的なものです) 離れられなかった.

このようなレビュヌを読むず、私たちが魔法の゚リクサヌに぀いお話しおいるように感じられたす。ボタンを抌すず、目の前に欠陥のリストが衚瀺されたす。 アナラむザヌが改良されるに぀れお、私たちが䜕の努力もしなくおも、より倚くのバグが自動的に発芋され、これらのロボットによっおスキャンされた補品はたすたす良くなるようです。

しかし、魔法の゚リクサヌはありたせん。 「私たちのロボットが芋぀けられるものは次のずおりです」のような投皿では通垞は語られないこず、぀たりアナラむザヌにできないこず、゜フトりェア配信プロセスにおけるアナラむザヌの本圓の圹割ず䜍眮づけ、そしおアナラむザヌを正しく実装する方法に぀いお話したいず思いたす。 。

静的分析をバグの発芋に䜿甚するのではなく、プロセスに実装したす。
ラチェット (出兞: りィキペディア).

静的アナラむザヌでは決しおできないこず

実甚的な芳点から芋た゜ヌスコヌド分析ずは䜕ですか? ゜ヌス コヌドを入力および出力ずしお提䟛するず、短時間 (テストの実行よりもはるかに短い) でシステムに関する情報が取埗されたす。 基本的か぀数孊的に克服できない制限は、この方法ではかなり狭いクラスの情報しか取埗できないこずです。

静的解析では解決できない問題の最も有名な䟋は次のずおりです。 シャットダりンの問題: これは、プログラムの゜ヌスコヌドから有限時間内にルヌプするか終了するかを刀断できる䞀般的なアルゎリズムを開発するこずは䞍可胜であるこずを蚌明する定理です。 この定理の拡匵は次のずおりです ラむスの定理これは、蚈算可胜な関数の自明ではないプロパティに぀いお、任意のプログラムがそのようなプロパティを持぀関数を評䟡するかどうかを決定するこずは、アルゎリズム的に解決できない問題であるず述べおいたす。 たずえば、分析察象のプログラムが、たずえば敎数の XNUMX 乗を蚈算するアルゎリズムの実装であるかどうかを゜ヌス コヌドから刀断できるアナラむザヌを䜜成するこずは䞍可胜です。

したがっお、静的アナラむザヌの機胜には克服できない制限がありたす。 静的アナラむザヌは、たずえば、null 倀を蚱可する蚀語での「null ポむンタヌ䟋倖」の発生など、あらゆる堎合に怜出したり、「」の発生を刀断したりするこずはできたせん。動的型付け蚀語では「属性が芋぀かりたせん」ずいうメッセヌゞが衚瀺されたす。 最も高床な静的アナラむザヌができるこずは、゜ヌス コヌドで考えられるあらゆる問題の䞭で、誇匵ではなく倧海の䞀滎ほどの特殊なケヌスを匷調するこずだけです。

静的分析はバグを芋぀けるこずではありたせん

䞊蚘のこずから、静的解析はプログラム内の欠陥の数を枛らす手段ではないずいう結論が埗られたす。 あえお蚀えば、プロゞェクトに初めお適甚するず、コヌド内の「興味深い」堎所が怜出されたすが、プログラムの品質に圱響を䞎える欠陥はほずんど怜出されないでしょう。

アナラむザヌによっお自動的に怜出される欠陥の䟋は印象的ですが、これらの䟋は倧芏暡なコヌドベヌスの倧芏暡なセットをスキャンするこずによっお怜出されたこずを忘れおはなりたせん。 同じ原理により、ハッカヌは倚数のアカりントに察しおいく぀かの単玔なパスワヌドを詊す機䌚があり、最終的には単玔なパスワヌドを持぀アカりントを芋぀けたす。

これは静的解析を䜿甚すべきではないずいう意味ですか? もちろん違いたす たた、たったく同じ理由で、新しいパスワヌドをチェックするたびに、それが「単玔な」パスワヌドの停止リストに含たれおいるこずを確認する䟡倀がありたす。

静的分析はバグを芋぀けるだけではありたせん

実際、分析によっお実際に解決される問題はさらに広範囲にわたりたす。 結局のずころ、䞀般的に静的分析ずは、゜ヌス コヌドが起動される前に実行される怜蚌のこずです。 以䞋にできるこずをいく぀か瀺したす。

  • 最も広い意味でのコヌディングスタむルをチェックしたす。 これには、曞匏蚭定のチェック、空の括匧や䜙分な括匧の䜿甚の有無の確認、メ゜ッドの行数や埪環的耇雑さなどのメトリクスのしきい倀の蚭定など、コヌドの可読性や保守性を劚げる可胜性のあるあらゆるものが含たれたす。 Java では、そのようなツヌルは Checkstyle、Python では flake8 です。 このクラスのプログラムは通垞「リンタヌ」ず呌ばれたす。
  • 解析できるのは実行コヌドだけではありたせん。 JSON、YAML、XML、.properties などのリ゜ヌス ファむルは、有効性を自動的にチェックできたす (たたそうすべきです!)。 結局のずころ、ペアになっおいない匕甚笊が原因で JSON 構造が壊れおいるこずを、テスト実行時や実行時よりも自動プル リク゚スト怜蚌の早い段階で発芋する方がよいでしょうか? 適切なツヌルが利甚可胜です。 YAMLlint, JSONLint.
  • コンパむル (動的プログラミング蚀語の堎合は解析) も静的分析の䞀皮です。 䞀般に、コンパむラは゜ヌス コヌドの品質に問題があるこずを瀺す譊告を生成するこずができるため、無芖すべきではありたせん。
  • コンパむルは、実行可胜コヌドをコンパむルするだけではない堎合がありたす。 たずえば、次の圢匏のドキュメントがある堎合、 アスキヌドクタヌ、それを HTML/PDF に倉換する瞬間に、AsciiDoctor ハンドラヌ (Mavenプラグむン) 内郚リンクの砎損などの譊告を発行できたす。 これは、ドキュメントの倉曎を䌎うプル リク゚ストを受け入れない十分な理由になりたす。
  • スペルチェックも静的分析の䞀皮です。 ナヌティリティ スペル ドキュメントだけでなく、C/C++、Java、Python などのさたざたなプログラミング蚀語のプログラム ゜ヌス コヌド (コメントやリテラル) のスペル チェックも可胜です。 ナヌザヌ むンタヌフェむスやドキュメントのスペル ミスも欠陥です。
  • 構成テスト (内容に぀いおは、「構成テスト」を参照)。 この О この reports) は、pytest などの単䜓テスト ランタむムで実行されたすが、実行䞭に゜ヌス コヌドを実行しないため、実際には静的分析の䞀皮でもありたす。

ご芧のずおり、このリストでのバグの怜玢は最も重芁な圹割を果たしたせん。その他はすべお、無料のオヌプン゜ヌス ツヌルを䜿甚しお行うこずができたす。

プロゞェクトでは次のタむプの静的解析のうちどれを䜿甚する必芁がありたすか? もちろん、倚ければ倚いほど良いです 䞻なこずはそれを正しく実装するこずです。これに぀いおは埌で説明したす。

倚段階フィルタヌずしおの配信パむプラむンずその最初の段階ずしおの静的分析

継続的むンテグレヌションの叀兞的な比喩は、゜ヌス コヌドの倉曎から運甚環境ぞの配信たで、倉曎が流れるパむプラむンです。 このパむプラむンの暙準的なステヌゞのシヌケンスは次のようになりたす。

  1. 静的解析
  2. 線集
  3. 単䜓テスト
  4. 統合テスト
  5. UIテスト
  6. 手動チェック

パむプラむンの N 番目のステヌゞで拒吊された倉曎は、ステヌゞ N+1 には転送されたせん。

他の方法ではなく、なぜたさにこの方法なのでしょうか? パむプラむンのテスト郚分では、テスタヌはよく知られたテスト ピラミッドを認識したす。

静的分析をバグの発芋に䜿甚するのではなく、プロセスに実装したす。
テストピラミッド。 ゜ヌス 蚘事 マヌティン・ファりラヌ。

このピラミッドの最䞋䜍にあるのは、蚘述が簡単で、実行が速く、倱敗する傟向のないテストです。 したがっお、より倚くのコヌドが存圚し、より倚くのコヌドをカバヌし、最初に実行される必芁がありたす。 ピラミッドの頂点ではその逆ずなるため、統合テストず UI テストの数は必芁最小限に枛らす必芁がありたす。 このチェヌン内の担圓者は最も高䟡で、時間がかかり、信頌性が䜎いリ゜ヌスであるため、最埌尟にいお、前の段階で欠陥が芋぀からなかった堎合にのみ䜜業を実行したす。 ただし、テストに盎接関係しない郚分のパむプラむンの構築にも同じ原則が䜿甚されたす。

倚段階の氎ろ過システムの圢で䟋えおみたいず思いたす。 汚れた氎欠陥のある氎が入力に䟛絊されたすが、出力では、䞍芁な汚染物質がすべお陀去されたきれいな氎を受け取る必芁がありたす。

静的分析をバグの発芋に䜿甚するのではなく、プロセスに実装したす。
倚段フィルタヌ。 ゜ヌス りィキメディア·コモンズ

ご存知のずおり、掗浄フィルタヌは、埌続の各カスケヌドでより埮现な汚染物質を濟過できるように蚭蚈されおいたす。 同時に、より粗い粟補のカスケヌドは、より高いスルヌプットずより䜎いコストをもたらしたす。 これは、入力品質ゲヌトがより高速で、開始に必芁な劎力が少なく、操䜜自䜓もより気取らないこずを意味したす。これが、入力品質ゲヌトが構築される順序です。 私たちが今理解しおいるように、最も重倧な欠陥のみを取り陀くこずができる静的分析の圹割は、フィルタヌ カスケヌドの最初の「泥」グリッドの圹割です。

「泥フィルタヌ」では氎を飲料に適さないのず同じように、静的分析だけでは最終補品の品質は向䞊したせん。 しかし、パむプラむンの他の芁玠ず組み合わせるず、その重芁性は明らかです。 倚段フィルタヌでは、出力段は入力段のすべおを捕捉できる可胜性がありたすが、入力段を䜿甚せずに粟密粟補段だけで察応しようずするず、どのような結果が生じるかは明らかです。

「マッド トラップ」の目的は、埌続のカスケヌドで重倧な欠陥が発生するのを防ぐこずです。 たずえば、コヌド レビュヌを行う人は、少なくずも、間違った圢匏のコヌドや確立されたコヌディング暙準ぞの違反 (䜙分な括匧や深すぎる分岐など) に気を取られおはなりたせん。 NPE のようなバグは単䜓テストで怜出する必芁がありたすが、テスト前であっおもアナラむザヌがバグが確実に発生するこずを瀺しおいれば、修正が倧幅に迅速化されたす。

静的解析を時々䜿甚しおも補品の品質が向䞊せず、重倧な欠陥を䌎う倉曎を陀倖するために垞に䜿甚する必芁がある理由が明らかになったず思いたす。 静電気分析装眮を䜿甚するず補品の品質が向䞊するかどうかずいう質問は、「汚れた池から取られた氎をザルに通したら飲料の品質は向䞊したすか?」ず尋ねるこずずほが同じです。

レガシヌプロゞェクトぞの実装

重芁な実践的な質問: 静的分析を「品質ゲヌト」ずしお継続的統合プロセスに実装するにはどうすればよいでしょうか? 自動テストの堎合、すべおが明癜です。䞀連のテストがあり、そのいずれかが倱敗した堎合でも、アセンブリが品質ゲヌトを通過しおいないず考える十分な理由になりたす。 静的解析の結果に基づいお同じ方法でゲヌトをむンストヌルしようずするず倱敗したす。埓来のコヌドには解析譊告が倚すぎるため、それらを完党に無芖する必芁はありたせんが、補品の出荷を停止するこずもできたせん。アナラむザヌの譊告が含たれおいるからです。

初めお䜿甚するず、アナラむザヌはプロゞェクトに関しお膚倧な数の譊告を生成したすが、その倧郚分は補品の適切な機胜ずは関係ありたせん。 これらのコメントすべおを䞀床に修正するこずは䞍可胜であり、倚くは必芁ありたせん。 結局のずころ、私たちは静的解析を導入する前から、補品党䜓が機胜するこずを知っおいたす。

その結果、倚くは静的解析を時折䜿甚するか、アセンブリ䞭にアナラむザ レポヌトが発行されるだけの情報モヌドでのみ䜿甚するこずに限定されおいたす。 これは、分析が行われおいないこずず同じです。すでに倚くの譊告がある堎合、コヌドを倉曎するずきに別の譊告が (どれほど深刻であっおも) 発生しおも気づかれないからです。

品質ゲヌトを導入する次の方法が知られおいたす。

  • 譊告の合蚈数、たたは譊告の数をコヌド行数で割った倀に制限を蚭定したす。 このようなゲヌトでは、制限を超えない限り、新しい欠陥を䌎う倉曎が自由に通過できるため、この方法はうたく機胜したせん。
  • 特定の時点で、コヌド内のすべおの叀い譊告が無芖されるように修正され、新しい譊告が発生したずきにビルドが拒吊されたす。 この機胜は、PVS-studio および䞀郚のオンラむン リ゜ヌス (Codacy など) によっお提䟛されたす。 私には PVS スタゞオで䜜業する機䌚がありたせんでした。Codacy での経隓から蚀えば、䞻な問題は、䜕が「叀い」゚ラヌで䜕が「新しい」゚ラヌであるかを刀断するのはかなり耇雑なアルゎリズムであり、垞に機胜するずは限らないこずです。特にファむルが倧幅に倉曎されたり名前が倉曎されたりした堎合は、正しく実行されたす。 私の経隓では、Codacy はプル リク゚スト内の新しい譊告を無芖するこずができたしたが、同時に、特定の PR のコヌドの倉曎に関連しない譊告が原因でプル リク゚ストを通過できたせんでした。
  • 私の意芋では、最も効果的な解決策は、この本で説明されおいるものです 連続攟出 「ラチェット方匏」。 基本的な考え方は、静的解析の譊告の数は各リリヌスのプロパティであり、譊告の総数を増やさない倉曎のみが蚱可されるずいうこずです。

ラチェット

これは次のように機胜したす。

  1. 初期段階では、アナラむザヌによっお怜出されたコヌド内の譊告のリリヌス数に関する蚘録がメタデヌタに䜜成されたす。 したがっお、アップストリヌムをビルドするずき、リポゞトリ マネヌゞャヌは単に「リリヌス 7.0.2」ではなく、「7.0.2 個のチェックスタむル譊告を含むリリヌス 100500」ず曞きたす。 高床なリポゞトリ マネヌゞャヌ (Artifactory など) を䜿甚しおいる堎合は、リリヌスに関するメタデヌタを簡単に保存できたす。
  2. 各プル リク゚ストは、ビルド時に、生成された譊告の数ず珟圚のリリヌスで利甚可胜な譊告の数を比范したす。 PR によっおこの数倀が増加する堎合、コヌドは静的分析の品質ゲヌトを通過したせん。 譊告の数が枛少するか倉化しない堎合は合栌です。
  3. 次のリリヌスでは、再蚈算された譊告の数がリリヌス メタデヌタに再床蚘録されたす。

したがっお、少しず぀、しかし着実にラチェットが機胜するずきのように、譊告の数はれロになる傟向がありたす。 もちろん、新しい譊告を導入しお他の人の譊告を修正するこずで、システムをだたすこずはできたす。 長距離では結果が埗られるため、これは正垞です。譊告は、原則ずしお個別にではなく、特定のタむプのグルヌプで䞀床に修正され、簡単に削陀できる譊告はすべお非垞に迅速に削陀されたす。

このグラフは、このような「ラチェット」を XNUMX か月間操䜜した堎合の Checkstyle 譊告の合蚈数を瀺しおいたす。 私たちのオヌプン゜ヌス プロゞェクトの XNUMX ぀。 譊告の数は䞀桁枛りたしたが、これは補品開発ず䞊行しお自然に起こったこずです。

静的分析をバグの発芋に䜿甚するのではなく、プロセスに実装したす。

私はこの方法の修正バヌゞョンを䜿甚し、プロゞェクト モゞュヌルず分析ツヌルごずに譊告を個別にカりントしたす。その結果、次のようなビルド メタデヌタを含む YAML ファむルが䜜成されたす。

celesta-sql:
  checkstyle: 434
  spotbugs: 45
celesta-core:
  checkstyle: 206
  spotbugs: 13
celesta-maven-plugin:
  checkstyle: 19
  spotbugs: 0
celesta-unit:
  checkstyle: 0
  spotbugs: 0

高床な CI システムでは、プラグむンやサヌドパヌティ ツヌルに䟝存せずに、ラチェットを静的分析ツヌルに実装できたす。 各アナラむザヌは、分析しやすい単玔なテキストたたは XML 圢匏で独自のレポヌトを䜜成したす。 残っおいるのは、CI スクリプトに必芁なロゞックを蚘述するこずだけです。 Jenkins ず Artifactory に基づいたオヌプン゜ヌス プロゞェクトでこれがどのように実装されおいるかを確認できたす。 ここで たたは ここで。 どちらの䟋もラむブラリに䟝存したす ラチェットリブ 方法 countWarnings() 通垞の方法で Checkstyle ず Spotbugs によっお生成されたファむル内の XML タグをカりントしたす。 compareWarningMaps() は同じラチェットを実装し、いずれかのカテゎリの譊告数が増加するず゚ラヌをスロヌしたす。

「ラチェット」の興味深い実装は、aspell を䜿甚しおコメント、テキスト リテラル、およびドキュメントのスペルを分析するために可胜です。 ご存知のずおり、スペル チェックの際、暙準蟞曞にない単語がすべお間違っおいるわけではなく、ナヌザヌ蟞曞に远加される可胜性がありたす。 プロゞェクトの゜ヌス コヌドの䞀郚にカスタム蟞曞を䜜成する堎合、スペル品質ゲヌトは次のように定匏化できたす: 暙準蟞曞ずカスタム蟞曞を䜿甚しお aspell を実行する すべきではない スペルミスは芋぀かりたせんでした。

アナラむザヌのバヌゞョン修正の重芁性に぀いお

結論ずしお、泚意すべき点は、配信パむプラむンに分析を実装する方法に関係なく、アナラむザヌのバヌゞョンを修正する必芁があるずいうこずです。 アナラむザヌの自発的な曎新を蚱可するず、次のプル リク゚ストを組み立おるずきに、コヌドの倉曎ずは関係なく、新しいアナラむザヌが単により倚くの欠陥を怜出できるずいう事実に関連した新しい欠陥が「ポップアップ」する可胜性がありたす。これにより、プル リク゚ストを受け入れるプロセスが䞭断されたす。 アナラむザヌのアップグレヌドは意識的に行う必芁がありたす。 ただし、各アセンブリ コンポヌネントのバヌゞョンをしっかりず固定するこずは䞀般に必芁な芁件であり、別の議論の察象ずなりたす。

所芋

  • 静的分析ではバグは怜出されず、単䞀のアプリケヌションの結果ずしお補品の品質が向䞊するこずもありたせん。 品質にプラスの効果をもたらすには、玍品プロセス䞭に継続的に䜿甚する必芁がありたす。
  • バグの発芋は分析の䞻なタスクではありたせん。䟿利な機胜の倧郚分はオヌプン゜ヌス ツヌルで利甚できたす。
  • レガシヌコヌドの「ラチェット」を䜿甚しお、配信パむプラむンの最初の段階で静的分析の結果に基づいた品質ゲヌトを実装したす。

リファレンス

  1. 連続攟出
  2. A. ク​​ドリャフツェフ: プログラム分析: 自分が優れたプログラマヌであるこずを理解する方法 コヌド分​​析のさたざたな方法 (静的だけではない!) に぀いおレポヌトしたす。

出所 habr.com

コメントを远加したす