ホームページ  >  記事  >  運用・保守  >  静的コード分析ツールの構築に関する Google のケーススタディ

静的コード分析ツールの構築に関する Google のケーススタディ

WBOY
WBOY転載
2023-06-05 22:22:591322ブラウズ

ソフトウェアのバグは、開発者やソフトウェア会社に多大な時間と費用を要します。 2014 年を例に挙げると、広く使用されている SSL プロトコル実装の (「goto 失敗」) バグにより、無効な SSL 証明書が受け入れられ、日付の形式に関連する別のバグにより、Twitter で広範なサービス停止が発生しました。このようなエラーは、多くの場合、静的分析によって検出できます。実際、コードやドキュメントを読んでいるときにすぐに特定できますが、最終的には、その状況が実稼働環境でも依然として発生しているのが現実です。

これまでの研究では、ソフトウェア開発にバグ検出ツールを適用した経験がよく報告されています。ただし、開発者が静的解析ツールを使用して成功した例は非常に多くありますが、エンジニアが必ずしも静的解析ツールを積極的に使用しようとしない、またはツールによって生成される警告情報を積極的に無視するわけではない次の理由がまだあります。

    正しく統合されていません。ツールが開発者のワークフローに統合されていないか、プログラムの実行に時間がかかりすぎます。
  • 無効な警告です。アラーム情報の実現可能性は低く、
  • は信頼できません。誤検知のため、ユーザーは結果を信頼できなくなりました。
  • 欠陥の実際の利用シナリオは不明です。報告されたバグは理論的には実現可能ですが、実際の利用シナリオでは欠陥が明確ではありません;
  • 修理コストが高すぎます。検出されたコードの欠陥を修正するにはコストがかかりすぎるか、リスクが高くなります。
  • アラートを理解するのは困難です。ユーザーはアラーム情報の具体的な内容や原理を理解していません。
  • 次の記事では、Java 言語分析と学術文献に FindBug を使用した Google のこれまでの経験と教訓からどのように学び、最終的に Google でソフトウェア エンジニアを育成することに成功したかについて説明します。日常的に使用。 Google のツールは、エンジニアからの意見を利用して、問題のあるコードが全社的なコード リポジトリにマージされる前に、エンジニアが毎日修正する何千もの問題を検出できます。

ツールの範囲に関しては、静的分析を Google の中核的な開発プロセスに統合し、大多数の Google 開発者にサービスを提供することに重点を置いています。多くの静的コード分析ツールは、Google で展開されている 20 億行のコードに比べれば小さく見えてしまうため、大規模なシナリオで複雑な分析を実行するテクノロジーは優先度が高くありません。

もちろん、専門分野 (航空宇宙や医療機器分野など) で働く Google の外部開発者が特定の静的解析ツールやワークフローを使用する可能性があることを考慮する必要があります。また、開発プロジェクトに特定の種類 (カーネル コードやデバイス ドライバーなど) が含まれる開発者は、特定の分析方法を必要とする場合があります。静的分析では多くの優れた結果が得られています。私たちが報告した経験や洞察が唯一のものであるとは考えていませんが、Google のコード品質と開発経験を向上させるために私たちの取り組みを整理して共有することが有益であると強く信じています。 。 ######用語の定義。この用語の定義は次のとおりです。 分析ツールは、ソース コードに対して 1 つ以上の「チェッカー」を実行し、ソフトウェアの障害を引き起こす可能性のある「欠陥」を特定します。開発者が問題を発見した後に積極的な行動をとらなかった場合、開発者が特定された欠陥に遭遇し、適切な修正を行わなかった場合、それは「実際の誤検知」であると考えられます。静的分析では報告された欠陥を正確に特定できなかったが、開発者が読みやすさと保守性を向上させるためにコードを修正する措置を積極的に講じた場合、これは有効な「誤検知」ではありません。分析によって実際のコード エラーが報告されたが、開発者がコードの問題を理解せず、何もアクションを起こさなかった場合、これは「実際の誤検知」とみなされます。私たちはこの概念的な区別を利用して、研究開発の観点の重要性を強調しています。ツールの作成者ではなく開発者がツールの誤検知率を認識し、直接影響を与えます。

Google がソフトウェアをコンパイルして構築する方法

以下では、Google のソフトウェア開発プロセスの重要なポイントを概説します。 Google では、ほぼすべての開発ツール (開発環境を除く) が集中化され、標準化されています。インフラストラクチャの多くは内部チームが所有する Scratch を使用して構築されており、実験的な柔軟性が保たれています。

ソース コードの管理とコードの所有権。 Google は単一ソース コード管理システムを開発し、使用しています。そして、(ほぼ)すべての Google 独自のコードを 1 つのブランチに保存して実験してみます。開発者は、ブランチを制限する「トランクベース」の開発アプローチを使用し、多くの場合、機能ではなくリリースごとに分割されます。コード所有者の承認があれば、エンジニアは誰でもコードを変更できます。コードの所有権はパスに基づいており、ディレクトリの所有者はサブディレクトリに対しても同じ権限を持っています。

システム構築。 Google コードベース内のすべてのコードは、コンパイルに依存しないバージョンの Bazel を使用してコンパイルされます。つまり、ビルドの配布と並列化を容易にするために、すべての入力を明示的に宣言してソース管理に保存する必要があります。 Google のビルド システムの Java ルールは JDK とソース管理された Java コンパイラに依存しており、これらのバイナリは新しいバージョンをすぐに導入することですべてのユーザーに対して更新できます。通常、ビルドはソース (ヘッド経由) から取得され、バイナリ コンポーネントがブランチにチェックインされることはほとんどありません。すべての開発者が同じビルド システムを使用しているため、どのコードもエラーなく正常にコンパイルできます。

分析ツール。 Google が使用する静的分析ツールは通常、複雑ではありません。 Google インフラストラクチャは、このレベルのシステム上でのプロシージャ間またはプログラムベースの整合性分析の実行をサポートしていません。また、高度な静的分析技術 (分離ロジック テクノロジーなど) を大規模に使用することもできません。単純なチェッカーであっても、ワークフローへの統合をサポートする分析インフラストラクチャが必要です。一般的な開発プロセスの一部として導入されているアナライザー タイプには、次のものが含まれます:

  • スタイル チェッカー (Checkstyle、Pylint、Golint など);

  • 拡張バグ発見コンパイラ (Error Prone、ClangTidy、Clang Thread SafetyAnaracy、Govet、CheckerFramework など)。抽象構文ツリー パターン マッチング ツール、型ベースのチェッカー、および呼び出されていない変数を検出するアナライザーが含まれますが、これらに限定されません。

  • 運用サービスのプロファイラーを呼び出します (例: コード コメントで言及されている従業員がまだ Google で働いているかどうかを確認します);

  • プロパティを確認しますビルド出力のサイズ (出力バイナリのサイズなど)。

Google の C リンターは、if ステートメントの後に括弧があるかどうかをチェックすることで、「goto failed」の脆弱性を検出できます。パターン マッチング ベースのチェッカーは日付形式のエラーを特定するため、Twitter をクラッシュさせたコードは Google ではコンパイルできません。 Google の開発者は、バッファの脆弱性を見つけるために AddressSanitizer などの動的分析ツールを使用したり、データ競合の問題を見つけるために ThreadSanitizer などの動的分析ツールも使用します。これらのツールはテスト中に実行され、場合によっては運用トラフィックのある環境でも実行されます。

統合開発環境 (IDE)。開発プロセスの初期における静的解析の問題のエントリ ポイントは、IDE に統合されることです。しかし、Google 開発者はさまざまなエディタを使用しているため、ビルド ツールを呼び出す前にすべての開発者からのエラーを一貫して検出することは困難です。 Google では、一般的な社内 IDE と統合された分析を使用していますが、分析できる特定の IDE が必要になるのは長くて困難な道のりです。 ######テスト。ほぼすべての Google コードには、単体テストから大規模な統合テストまで、対応するテスト リンクが含まれています。テスト活動は、システム構築に統合する必要がある最初の概念であり、コンパイル プロセスと同様に、独立して分散されています。ほとんどのプロジェクトでは、開発者がコードのテスト ケースを作成および保守します。通常、プロジェクトには個別のテスト グループや QA グループがありません。

Google の継続的なビルドおよびテスト システムは、コードが送信されるたびにテストを実行し、ビルドの失敗や、開発者のコ​​ード変更によって失敗したテスト ケースに関するフィードバックをタイムリーに提供します。また、プロジェクトの依存関係が壊れることを避けるために、コミットする前に変更をテストすることもサポートされています。

コードレビュー。 Google に送信されたすべてのコードは、まずコード レビューに合格します。開発者は誰でも Google のコードのどの部分にも変更を加えることができますが、コードの所有者は、マージのために送信される前に、変更を確認して承認する必要があります。さらに、コード所有者であっても、変更をコミットする前にコードをレビューする必要があります。コード レビューは、他の開発インフラストラクチャと緊密に統合された一元化された Web ベースのツールを通じて実行されます。静的解析結果はコードレビューに表示できます。

コードリリース。 Google チームはリリースを頻繁にリリースし、リリースの検証と導入プロセスのほとんどは「プッシュ オン グリーン」方式によって自動化されています。これは、手間のかかる手動のリリース検証プロセスに依存することが難しいことを意味します。 Google のエンジニアが本番環境でバグを発見した場合、サービスを中断するよりも比較的低コストで、新しいバージョンをロールバックして本番サーバーにデプロイできます。

FindBugs から学ぶ

2008 年から 2010 年の初期の探索的研究段階では、Google の静的分析テクノロジーは、Java 分析に FindBug を使用することに重点を置いていました。主導者はメリーランド大学ペンシルバニア大学の William Pugh An 氏でした。ヨーク州立大学の David Hovemeyer によって作成された独立したツール。原則は、コンパイルされた Java クラス ファイルを分析し、バグの原因となる可能性のあるコード構造モデルを抽出することです。 2018 年 1 月の時点では、FindBugs は Google のごく少数のエンジニアによって使用されているコマンド ライン ツールにすぎません。 「BugBot」と呼ばれる小さな Google チームは、原作者の Pugh と協力し、FindBugs を Google 開発プロセスに統合する 3 つの主要な試みを行いました。

試行を通じて次の点を学びました:

試行 1: バグ ダッシュボード。 2006 年に初めて FindBugs が集中ツールに統合され、Google コードベース全体を毎晩スキャンし、エンジニアがダッシュボードから確認できるように結果を記録しました。 FindBugs は Google の Java コード ベースで数百のエラーを発見しましたが、エラー メッセージ ダッシュボードは日常の開発プロセスから切り離されており、他の既存の静的分析結果と統合できなかったため、ダッシュボードの効果はほとんどありませんでした。

試み 2: バグの改善に重点を置きます。

次に、BugBot チームは、毎晩見つかった新しい問題を手動で分類し、比較的重要なバグ レポートを特定して処理し始めました。 2009 年 5 月、数百人の Google エンジニアが FindBugs アラートの解決に焦点を当てた全社規模の「Fix it」週間に参加しました。合計 3,954 件のアラート (合計 9,473 件中 42%) が確認されましたが、修正されたのはわずか 16% (640 件) でした。実際、報告された結果の 44% (1746) がバグ フィードバック追跡のために送信されました。 Fixit キャンペーンでは、FindBugs によって発見された問題の多くが実際のコードの欠陥であることが確認されましたが、多くは実際の修正を保証するほど重要ではありませんでした。大規模な環境では、手動で問題を分類し、バグ レポートを送信することを継続するのは困難です。

試み 3: コード レビューに統合します。次に、BugBot チームは、レビューが保留中であることがレビュー担当者に通知されると、FindBugs が自動的に実行され、スキャン結果がコード レビューのコメントとして表示されるシステムを統合して実装しました。上記のコード レビュー チームはすでにこれを実装しています。コーディング標準/スタイルの問題については、終了します。 Google 開発者は、誤検知を無視し、信頼性を高めるために FindBugs の結果をフィルタリングできます。さらに、このツールは新しい FindBugs アラートのみを表示しようとしますが、分類が間違っているため、アラートが新しい問題として扱われる場合があります。 2011 年にコード レビュー ツールが置き換えられたとき、この統合は 2 つの理由で終了しました。1 つは実際の誤検知率が高く、開発者がツールに対する信頼を失ったこと、もう 1 つは開発者がフィルタリングを自由にカスタマイズできるため、すべての関係者が分析に疑問を抱いたことです。結果に一貫性がありません。

コンパイル プロセスへの組み込み

FindBugs の実験と同時に、Google の C 開発プロセスは、Clang コンパイラに新しいチェック ルールを追加することで改善され続けました。 Clang チームは、修正推奨情報を含む新しいコンパイラ チェッカーを実装し、ClangMR を使用して分散アプローチで Google コードベース全体にわたって最新のコンパイラ最適化チェックを実行し、コードベースの既存のバグを修正するコード実装を行いました。コードベースに修正済みの問題がマークされると、Clang チームは新しいチェッカーを適用して、新しい問題をコンパイラ エラー (Clang チームは Google 開発者が無視すると判断した警告ではなく) としてフラグを立て、対処する必要があるビルドを中止します。合格。 Clang チームは、この戦略を通じてコードベースの品質を向上させることに非常に成功しています。

私たちはこの考えに従い、javac コンパイラーをベースにした Error Prone と呼ばれる、パターン分析に基づくシンプルで使いやすい Java 静的分析ツールを構築しました。導入された最初のチェック ルールは PreconditionsCheckNotNull と呼ばれ、プログラム実行の開始時にメソッド検出入力パラメータが空かどうかを検出するために使用されます。たとえば、checkNotNull (uid, "uid) ではなく checkNotNull ("uid is null", uid) です。 null でした」)。

連続したビルドを中断することなく PreconditionsCheckNotNull のようなチェッカーを開始するために、Error Prone チームはこれを使用して、ClangMR に似た javac ベースの MapReduce プログラムを使用してコード ベース全体でそのようなチェックを実行します。ビルド呼び出し JavacFlume です。 JavacFlume は一連の修正提案を生成し、相違点を比較して、これらの修正をコード ベース全体に適用します。 Error Prone チームは、内部ツール Rosie を使用して、大規模なコード変更を小さな変更に分割します。各変更は 1 つのプロジェクトにのみ影響し、これらの変更をテストして、コード レビューのために適切なチームに送信します。チームはコードに適用される修正のみをレビューし、追加が承認された場合にのみ、Rosie が実際の変更をコミットします。最終的に、既存の問題に対するすべての修理と変更が承認され、既存の欠陥はすべて解決されました。チームはコンパイラエラーメソッドを正式にオープンしました。

これらのパッチを受け取った開発者にフィードバックを求めて調査したところ、コードに組み込まれた修正を受け取った開発者の 57% はそのような情報を喜んで受け取り、41% は中立でした。否定的な反応を示し、「作業負荷が増えるだけだ」と言ったのはわずか 2% でした。

コンパイラ チェックの価値

コンパイル エラーは開発プロセスの初期段階で表示され、開発プロセスに統合されています。開発者のワークフロー。 Google では、コンパイル チェッカーを拡張することでコードの品質が効果的に向上することがわかりました。 Error Prone のチェックは (FindBugs とは異なり) バイトコードではなく javac の抽象構文ツリーに対して内部的に記述されるため、チーム外の開発者は比較的簡単にチェックを行うことができます。これらの外部貢献を活用することは、Error Prone の全体的な影響を高めるために重要です。 2018 年 1 月の時点で、162 人の著者が 733 人のチェッカーに貢献しました。

問題を報告するのは早ければ早いほど良いです

Google の一元的なビルド システムでは、すべてのビルド プロセスとビルド結果が記録されるため、指定された時間枠内ですべてのユーザーがエラー メッセージを確認できるようになります。最近コンパイラ エラーが発生した開発者と、同じ問題の修正に関する推奨事項を受け取った開発者にアンケートのフィードバックを送信しました。 Google 開発者は、(コードにマージされたパッチとは対照的に) コンパイル時にフラグが付けられた問題の方が、より重要なバグを捕捉できると信じています。たとえば、調査参加者は、コンパイル時に「実際の問題」としてフラグが付けられた問題は 74% であると信じていましたが、マージされたコードに問題が見つかりました。さらに、調査参加者はコンパイル時に見つかった問題の 6% (マージ段階では 0%) を「重大」と評価しました。この結果は、「生存者バイアス効果」によって説明できます。つまり、コードの提出時に、より高価な手段 (テストやコード レビューなど) によってバグが発見される可能性が高くなります。できるだけ多くのチェックをコンパイラに強制的に組み込むことが、これらのコストを回避する確実な方法です。

コンパイラ チェックの標準

コンパイルの中断はより大きなアクションとなるため、作業をスケールするために、コンパイラでのチェックを有効にするための標準を定義し、厳密な高注釈モードを設定しました。 Google のコンパイラ チェックは、読みやすく、実用的で、修正が簡単である必要があります (可能であれば、エラー メッセージには一般的に実装可能な修正提案が含まれている必要があります)。有効な誤検知が生成されない (分析アクションによって実際に正しいビルドが中断されるべきではありません)。コード); スタイルやコーディング規約の問題ではなく、本物のバグのみを報告します。これらの基準を満たすアナライザーを測定する主な目的は、単に問題を検出するだけではなく、コード ベース全体でこれらのコンパイラー エラーを自動的に修正することです。しかし、これらの標準は、コードのコンパイル時にエラー傾向チームが有効にできるチェックの範囲も制限しており、正確に検出できない、または普遍的に修正できない多くの問題が依然として私たちの前に問題となっています。

コード レビュー中にアラートを表示する

Error Prone チームがコンパイル時に問題を検出するために必要なインフラストラクチャを構築し、アプローチが機能することを証明したら、さらに多くのことを確認したいと考えています。影響の大きいバグは、当社が行うコンパイラ エラー チェックや、Java や C 以外の言語で提供される解析結果に限定されません。静的分析結果の 2 番目の統合エントリ ポイントは、Google のコード レビュー ツールである Critique です。静的分析結果は、Tricorder を使用して Google のプログラム分析プラットフォームである Critique に表示されます。 2018 年 1 月の時点で、Google の C バージョンと Java バージョンにはコンパイラ エラーはなく、すべての分析結果はコンパイラ エラーまたはコード レビュー フェーズ中に表示されます。

コード レビュー チェックの基準

コンパイル時チェックとは異なり、コード レビュー中に表示される分析結果には、最大 10% の有効偽陽性率が含まれることが許可されます。コードレビュー中に期待されるフィードバックは必ずしも完璧であるとは限らず、開発者は実際に採用する前に、対応する修正提案を評価する必要があります。コード監査フェーズにおける Google のチェッカーは、次の基準を満たしている必要があります:

わかりやすい。これはエンジニアにとって明確で理解しやすいものであり、

ソリューションは実現可能であり、修復も簡単です。修正にはコンパイラ チェック フェーズよりも多くの時間、思考、労力が必要になる可能性があり、チェックの結果には問題を定義する方法に関するガイダンスが含まれている必要があります。

の実効誤検知率は 10% 未満です。 。開発者は、チェッカーが少なくとも 90% の確率で実際のバグを検出することを実感する必要があります。

はコードの品質に大きな影響を与えます。見つかった問題によってプログラムの正常な実行が妨げられるわけではありませんが、開発者は問題を真剣に受け止め、修正することを選択する必要があります。

一部の問題は、コンパイラでフラグが立てられるほど深刻ですが、それらに対処したり、自動修正を軽減したり開発したりすることは現実的ではありません。たとえば、一部の問題を修正するには、コードのリファクタリングが必要になる場合があります。これらのチェックをコンパイラ エラーとして有効にするには、既存の実装を手動でクリーンアップする必要がありますが、Google ほど大規模なコード ベースではそれは実現できません。コードレビューでこれらのチェックを示す分析ツールは、新たな問題の発生を回避し、開発者が適切な修正を行うための措置を講じるかどうかを決定できるようにします。コード レビューは、仕様の問題や最適化されたコードの簡略化など、比較的重要ではない問題を報告するのにも適した機会です。私たちの経験では、コンパイル中のレポートは開発者にとって常に受け入れがたく、迅速な反復とデバッグをより困難にします。たとえば、到達不能なコード パスの検出器がコード ブロックのデバッグを妨げる可能性があります。しかし、コード レビュー中、開発者はコードを完成させるための準備を慎重に行っており、読みやすさやスタイルの詳細に関する問題をより受け入れやすく、受容的な考え方を持っています。

Tricorder

Tricorder は、簡単に拡張できるように設計されており、静的および動的分析ツールを含むさまざまなタイプのプログラム分析ツールをサポートします。コンパイラ エラーとして有効にできない Tricorder のエラー傾向チェッカーをいくつか示します。 Error Prone は、ClangTidy と呼ばれる Tricorder と統合する新しい C 分析コンポーネントのセットも作成しました。 Tricorder アナライザーのレポートは 30 を超える言語での結果をサポートし、スタイル チェッカーなどの単純な構文分析をサポートし、Java、JavaScript、C のコンパイラー情報を活用し、運用データ (現在実行中のタスクやジョブなど) と直接統合できます。 Tricorder が Google で成功を収め続けているのは、アナライザー作成者向けのエコロジカル プラットフォームをサポートし、コード レビュー プロセス中に実行可能な修正を強調表示し、アナライザーを改善してアナライザー開発者が確実にアクションを起こすためのフィードバック チャネルを提供するプラグイン モデルであるためです。正のフィードバック。

ユーザーが投稿できるようにします。 2018 年 1 月の時点で、Tricorder には 146 のアナライザーが含まれており、そのうち 125 は Tricorder チームの外部からのものであり、数百もの追加チェック用の 7 つのプラグイン システム (ErrorProne や ClangTidy など) が含まれています (そのうちの 2 つ)。

レビュー担当者は、修正の提案を提供するために検討します。

Tricorder チェッカーは、コード レビュー担当者や開発者に表示される適切な修復提案を含むコード レビュー ツールを提供します。レビュー担当者は、分析結果の「修正してください」ボタンをクリックすることで、開発者に欠陥のあるコードの修正を依頼できます。通常、レビュー担当者は、すべてのコメント (手動および自動検出) が解決されるまで、コードの変更を含めることを承認しません。

ユーザーからのフィードバックを繰り返します。 Tricorder には、「修正してください」ボタンに加えて、レビュー担当者または提案者が分析結果に同意しないことを示すためにクリックできる「役に立たない」ボタンも用意されています。クリック アクションにより、バグ トラッカーにバグが自動的に送信され、アナライザーが属するチームにバグが示されます。 Tricorder チームは、これらの「無駄な」クリックを追跡調査し、「修正してください」クリックと「無駄な」クリックのクリック率を計算します。アナライザーの比率が 10% を超えた場合、Tricorder チームは作成者が改良するまでアナライザーを無効にします。 Tricorder チームがアナライザーを永続的に無効にすることはめったにありませんが、アナライザーの作成者が面倒で役に立たないことが判明したチェッカーを削除および変更するまで、一部のアナライザーを (いくつかのシナリオで) 無効にしました。

提出されたバグによってアナライザーのパフォーマンスが向上することが多く、それによってアナライザーに対する開発者の満足度が大幅に向上します。たとえば、Error Prone チームは 2014 年に、Guava が printf などの関数に多すぎる引数を渡している場合にフラグを立てるチェックを開発しました。 Printf のような関数は、実際にはすべての printf 指定子を受け入れるわけではなく、%S のみを受け入れます。エラー傾向チームは、分析が正しくなく、バグ一致コード内のフォーマット ワイルドカードの数が実際に渡された引数の数と実際に一致するという「愚かな」バグを週に 1 回程度受け取ります。ユーザーが %s 以外のワイルドカード プレースホルダーを渡そうとすると、パーサーは実際にはどのような場合でも正しくありません。そこでチームは、コード インスペクションの説明テキストを変更して、関数が %s プレースホルダーのみを受け入れることを直接述べ、そのチェックに関するエラーが発生しなくなりました。

Tricorder の使用規模。 2018 年 1 月の時点で、Tricorder は 1 日あたり約 50,000 件のコード レビューの変更を分析しました。分析はピーク時に 1 秒あたり 3 回実行されます。レビュー担当者は 1 日に 5,000 回以上「修正してください」をクリックし、著者は 1 日に約 3,000 回自動修復ソリューションを適用します。 Tricorder アナライザーは、1 日あたり 250 回の「無駄な」クリックのフィードバックを受け取ります。

コード レビュー分析の成功は、コード レビュー分析が Google の開発者ワークフローの「スイート スポット」を占めていることを示しています。コンパイル時に表示される分析結果は、重大な問題を特定し続けるためにアナライザーに依存することによっては満たせない相対的な品質と精度を備えている必要があります。レビューとコードがマージされた後、開発者は変更を行うことに対する抵抗が増大します。その結果、開発者は、すでにテストおよびリリースされたコードを変更するのに苦労しており、リスクが低く重要度の低い問題に対処する可能性が低くなります。ソフトウェア開発組織の他の多くの分析プロジェクト (Android/iOS アプリの Facebook Infer 分析など) も、分析結果をレポートするための重要なエントリ ポイントとしてコード レビューを重視しています。

拡張アナライザー

Google 開発者は、Tricorder アナライザーの結果を受け入れるにつれて、アナライザーのさらなる拡張を要求し続けています。 Tricorder は、プロジェクト レベルでのカスタマイズの許可と、開発プロセスの他の時点でのプレゼンテーション分析結果の追加の 2 つの方法でこの問題を解決します。このセクションでは、Google がより高度な分析を中核的な開発プロセスとしてまだ活用していない理由のいくつかについても説明します。

プロジェクト レベルのカスタマイズ

要求されたすべてのアナライザーが Google コード ベース全体にとって同等の価値を持つわけではありません。たとえば、一部のアナライザーは誤検知率が高く、それに応じて、誤検知率チェッカーを有効にするには、特定のプロジェクトで構成する必要がある場合があります。これらのプロファイラーは、適切なチームにのみ役立ちます。

これらのニーズを達成するために、私たちの目標は Tricorder をカスタマイズ可能にすることです。 FindBugs のカスタマイズに関するこれまでの経験はそれほど効果的ではありませんでした。ユーザーレベルのカスタマイズにより、チーム内およびチーム間の差別化が図られ、ツールの使用量が減少しました。ユーザーごとに問題の異なるビューが表示されるため、同じプロジェクトに取り組んでいる全員が特定の問題を確実に参照できるようにする方法はありません。開発者がチームのコードから未使用のインポートをすべて削除した場合、他の開発者の 1 人が未使用のインポートの削除に関して一貫性を持たなかったとしても、その変更はロールバックによってすぐに拒否されます。

このような問題を回避するために、Tricorder ではプロジェクト レベルでの構成のみを許可し、特定のプロジェクトに変更を加える人には、そのプロジェクトに関連する分析結果の一貫したビューが表示されるようにします。結果ビューの一貫性を維持することで、いくつかのタイプのアナライザーが次のアクションを実行できるようになります。

バイナリ結果を生成します。たとえば、Tricorder には、下位互換性のない変更を識別するプロトコル バッファー定義のパーサーが含まれています。これは、開発者チームがシリアル化された形式でプロトコル バッファーに永続的な情報を確保するために使用されますが、この形式でデータを保存しないチームにとっては煩わしいものです。もう 1 つの例は、アナライザーに Guava または Java コード実装の使用を推奨させることですが、これらのライブラリや言語機能を使用できないプロジェクトには意味がありません (

には特定のセットアップやコード内注釈が必要です)。たとえば、チームは、コードに適切にアノテーションが付けられているかどうかを分析するために、Checker Framework の null のみを使用できます。適切に構成されている場合、バイナリ サイズの増加と特定の Android バイナリの関数呼び出し数をチェックし、増加が予想されるか、それとも制限範囲に近づいているかを開発者に警告するもう 1 つのアナライザーです。

特定地域言語 (DSL) とチーム固有のコーディング ガイドラインをサポートします。 Google ソフトウェア開発チームの中には、いくつかの小規模な DSL を開発し、関連するチェッカーを実行したいと考えている人もいます。他のチームは、可読性と保守性のベスト プラクティスを実装しており、リソースを大量に消費しながらこれらのチェックを引き続き実施したいと考えています。付属の動的解析の結果に基づくハイブリッド解析の事例。このような分析は一部のチームにとっては高い価値をもたらしますが、誰にとってもコストや時間がかかりすぎます。

2018 年 1 月の時点で、Google には約 70 のオプション分析があり、2,500 のプロジェクトで少なくとも 1 つが有効になっています。社内の数十のチームが新しいアナライザーの開発を積極的に行っており、そのほとんどは開発ツール グループ外に所属しています。

その他のワークフロー統合ポイント

これらのツールに対する開発者の信頼が高まるにつれて、ワークフローへのさらなる統合も求められています。 Tricorder は、コマンド ライン ツール、継続的統合システム、コード レビュー ツールを提供することで、分析結果を提供できるようになりました。

コマンドラインのサポート。 Tricorder チームは、本質的にコード マネージャーであり、チームのコード ベース内のさまざまなアラート分析を頻繁に参照してクリーンアップする開発者向けにコマンド ライン サポートを追加しました。これらの開発者は、各アナライザーが生成する修正の種類にも精通しており、特定のアナライザーに対して高いレベルの信頼を持っています。そのため、開発者はコマンド ライン ツールを使用して、特定の分析にすべての修正を自動的に適用し、クリーンな変更を加えることができます。

コード コミットしきい値。一部のチームは、コード レビュー ツールに表示されるだけでなく、特定のアナライザーがコードのコミットをブロックすることを望んでいます。通常、コミットをブロックする機能のリクエストは、多くの場合カスタム DSL またはライブラリで、誤検知がないことを保証する高度にカスタマイズされたチェッカーを備えたチームによって行われます。

コードは結果を示しています。コードのプレゼンテーションは、大規模なプロジェクト (またはコードベース全体) の問題の規模を示すのに最適です。たとえば、非推奨の API のコードを参照するときの分析結果には、移行に必要な作業量が示されます。また、一部のセキュリティおよびプライバシー分析はグローバルであり、問​​題があるかどうかを判断する前に専門チームが結果をレビューする必要があります。デフォルトでは分析結果が表示されないため、コード ブラウザーを使用すると、特定のチームが分析ビューを有効にして、他の開発者の注意をこれらのアナライザーからそらすことなく、コード ベース全体をスキャンして結果を確認できます。分析結果に関連する修正がある場合、開発者はコード参照ツールをクリックするだけで修正を適用できます。コード ブラウザーは、コードがコミットされて実行されるまでこのデータを利用できないため、実稼働データの利用状況の分析結果を表示するのにも最適です。

複雑な分析

Google で広く導入されているすべての静的分析は比較的単純ですが、一部のチームは特定のドメイン (Android アプリなど) を対象としたプロジェクト固有の分析フレームワークを使用して手続き間分析を行っています。 Google 規模のプロセス分析は技術的に実現可能です。しかし、このような分析を実装するのは非常に困難です。前述したように、すべての Google コードは個別の全体的なソース コード リポジトリに保存されるため、概念的には、コード リポジトリ内のすべてのコードはバイナリ ファイルの一部になることができます。したがって、特定のコードレビューの分析結果からコードリポジトリ全体の分析が必要になる状況が想像されます。 Facebook の Infer はプロシージャ間分析に焦点を当てており、スプリット ロジック ベースのアナライザーを数百万行のコード ベースに拡張しますが、そのようなアナライザーを Google の数十億行のコード リポジトリに拡張するには、依然として多大なエンジニアリング作業が必要です。 2018 年 1 月の時点では、より高度な分析システムの実装は Google にとって優先事項ではありませんでした。

には多額の投資が必要です。インフラへの先行投資は法外な額になるため、誤警報率を減らす努力が必要になります。分析チームは、多くのアナライザーの誤検知率を大幅に削減する技術を開発したり、FigureInfer のように表示されるエラー メッセージを厳密に制限したりする技術を開発する必要があり、実装すべきことはまだたくさんあります。分析チームには、実装および統合するための「シンプルな」アナライザーがまだ多くあり、

高額な初期費用がかかります。この「シンプルな」アナライザーは非常に費用対効果が高いと考えており、これが FindBugs の中心的な動機となっています。比較すると、より高度なチェッカーのコスト ROI を決定する場合でも、初期費用は高くなります。

この ROI は、専門分野 (航空宇宙や医療機器など) や特定のプロジェクト (デバイス ドライバやモバイル アプリケーションなど) に取り組む Google 以外の開発者にとっては重要な差となる可能性があることに注意してください。

思考

静的分析を Google ワークフローに統合しようとした経験から、次の貴重な教訓が得られました。

バグを見つけるのは簡単です。コード ベースが十分に大きい場合は、想像できるほぼすべてのコード パターンが含まれます。完全なテスト カバレッジと厳格なコード レビュー プロセスを備えた成熟したコード ベースであっても、大きなバグが存在します。ローカルの検査では問題が明らかでない場合もありますし、一見無害なリファクタリングによってエラーが発生する場合もあります。たとえば、long 型のフィールド f を使用した次のコード スニペットを考えてみましょう。

result =

31 * result


(int) (f ^ ( f >>> 32));

  • 開発者が f の型を int に変更した場合に何が起こるかを想像してみてください。コードのコンパイルは続行されますが、右オフセット 32 は演算なしとなり、フィールドはそれ自体と XOR 演算され、変数のハッシュ値は定数 0 になります。その結果、 f は、によって生成された値に影響を与えなくなります。 hashCodeメソッド。 f の型を計算できるツールであれば、31 を超える正しいオフセットを正しく検出できます。このエラーを含む Google のコード ベースの 31 コードを修正し、Error Pone Server エラーのコンパイルのチェックも組み込みました。
エラーを見つけるのは簡単なので、Google はシンプルなツールを使用してエラーの種類を検出します。次に、分析作成者は Google コードを実行した結果に基づいて微調整を行います。

ほとんどの開発者は、自分たちが思っているほど静的分析ツールを使用していません。多くの商用ツールの開発と同様に、Google は当初 FindBugs の実装に依存していました。エンジニアはプロジェクト内で見つかった問題を表示するために集中管理されたダッシュボードにアクセスすることを選択しましたが、実際にそのように認識している人はほとんどいませんでした。コードに組み込まれたバグを見つけるには遅すぎます (ユーザーが問題に気付かずにデプロイされ、実行されている可能性があります)。ほとんどまたはすべてのエンジニアに静的解析の警告が確実に表示されるようにするには、解析ツールをワークフローに統合し、全員に対してデフォルトで有効にする必要があります。 Error Prone などのプロジェクトはエラー ダッシュボードを提供しませんが、追加のチェッカーでコンパイラを拡張し、コード レビュー中に分析結果を表示します。

開発者の気持ちが重要です。私たちの経験と資料の蓄積では、静的分析をソフトウェア開発組織に統合しようとする多くの試みは失敗に終わりました。通常、エンジニアは静的分析ツールを使用することを Google 経営陣から許可されていません。静的解析に取り組むエンジニアは、有効な現実世界のデータを使用してその影響を実証する必要があります。静的解析プロジェクトを成功させるには、開発者は静的解析からメリットが得られることを認識し、静的解析を使用する価値を享受する必要があります。

成功する分析プラットフォームを構築するために、開発者に高い価値を提供するツールを構築します。 Tricorder チームは修正された問題を慎重にレビューし、実際の調査を実施して開発者がどのように感じているかを理解し、分析ツールを通じてバグの送信を容易にし、これらすべてのデータを継続的な改善に使用します。開発者は分析ツールに対する信頼を築く必要があります。ツールが誤検知や低レベルの問題に関するフィードバックで開発者の時間を無駄にすると、開発者は自信を失い、結果を無視することになります。

バグを見つけるだけでなく、修正しましょう。静的分析ツールを促進するための一般的なアプローチは、コード ベース内の多数の問題を列挙することです。その目的は、修正すべき潜在的なエラーを指摘したり、将来バグが発生するのを防ぐことで、アクションに影響を与えることです。しかし、開発者が行動を起こす動機がなければ、この潜在的に望ましい結果は実現されないままになります。これは根本的な欠陥です。分析ツールは、特定される問題の数によってその有用性を評価しますが、プロセスの統合は少数のバグ修正だけで失敗します。それどころか、Google の静的分析チームは、これを閉ループの成功基準として使用して、対応する修復作業とバグの発見を担当します。エラーの修正に重点を置くことで、ツールは実用的な推奨事項を提供し、誤検知を最小限に抑えます。多くの場合、エラーの修正は自動ツールを使用して見つけるのと同じくらい簡単です。過去 5 年間の研究では、解決が難しい問題であっても、静的解析の問題に対する修正を自動的に作成する新しい技術が明らかになりました。

アナライザーの開発には集合的な努力が必要です。特定の静的分析ツールでは専門の開発者が分析を作成する必要がありますが、どのチェックがより大きな影響因子を生み出すかを実際に知っている専門家はほとんどいないかもしれません。さらに、アナライザーの専門家は、多くの場合、ドメインの専門家 (API、言語、セキュリティを扱う専門家など) ではありません。 FindBugs による統合 新しいチェッカーの書き方を知っているのはほんの一握りの Google 従業員だけだったので、小規模な BugBot チームがすべての作業を自分たちで行う必要がありました。これにより、新しいチェックを追加する速度が制限され、他の人がドメイン知識の貢献から恩恵を受けることが事実上妨げられます。 Tricorder のようなチームは現在、事前の静的分析の経験を必要とせず、開発者が提供するチェックの基準を下げることに重点を置いています。たとえば、Google ツールの Refaster を使用すると、開発者はコード スニペットの前後に例を指定することでチェッカーを作成できます。寄稿者は多くの場合、誤ったコードを自分でデバッグした後に寄稿するようになるため、新しいチェックにより、開発者の時間は長期的に節約されます。

結論

私たちの経験では、開発プロセスに統合することが静的分析ツールの実装の鍵であると考えています。チェッカー ツールの作成者は、開発者は自分が作成したコードの欠陥リストに直面することを喜んでいるはずだと信じているかもしれませんが、実際にはそのようなリストが開発者にそれらの欠陥を修正するインセンティブを提供するかどうかはわかりません。分析ツールの開発者として、開発者に数値を与えるのではなく、実際に修正される欠陥という観点から測定の有効性を定義する必要があります。これは、私たちの責任が分析ツール自体をはるかに超えて及ぶことを意味します。

私たちは、ワークフローの統合をできるだけ早く推進することに重点を置いたシステムを提唱します。可能な限り、コンパイラ エラーとしてチェッカーを有効にします。破壊的なビルド ツール作成者が最初にコードベース内のすべての既存の問題を修正するという任務を負うことを回避し、Google のコードベースの品質を一度に 1 段階ずつ継続的に改善できるようにします。コンパイラでエラー警告が表示されるため、開発者はコードを書いた直後にエラー警告に対処し、タイムリーな変更を加えることができます。これを達成するために、Google は膨大な Google コード ベースにわたって分析を実行し、修正を生成するためのインフラストラクチャを開発しました。また、数百のファイルへの変更を可能にするコード レビューとコミットの自動化からも恩恵を受けています。また、当然のことながら、コードの改善が変更のリスクを避けることよりも重要であるため、レガシー コードに変更が組み込まれることを容認することが多いエンジニアリング文化からも恩恵を受けています。

コード レビューは、コードをコミットする前に分析警告を表示するための最良のエントリ ポイントです。開発者が分析結果を確実に受け入れるために、Tricorder は開発者が変更をコミットする前のコード変更フェーズでのみ問題を表示し、Tricorder チームは一連の基準を適用して表示するアラートを選択します。 Tricorder はさらに、コード レビュー ツールで統計を収集します。このツールは、アナライザーが多数の無効なアラートを生成する根本原因を検出するために使用されます。

無視される警告を克服するために、私たちは Google エンジニアの信頼を取り戻すために懸命に努力しました。その結果、Google 開発者には静的分析を無視する強い偏見があり、誤検知率が満足のいくものではないレポートはすべて彼らに悪影響を与えることがわかりました。何もしない理由。分析チームは、記述的な客観的基準に照らしてレビューされた後にのみ、検査結果をエラーまたは警告として表示することに非常に慎重であるため、開発者が分析結果に圧倒されたり、混乱したり、イライラしたりすることはほとんどありません。調査とフィードバック チャネルは、このプロセスの重要な品質管理方法です。開発者が分析結果に対する信頼を取り戻した現在、Tricorder チームは、より多くの分析を Google 開発者のワークフローにさらに関与させる必要性に取り組んでいます。

Google では、コンパイル時とコード レビュー中の両方で、毎日何百ものバグが Google コードベースに侵入するのを防ぐ静的分析インフラストラクチャを構築し、成功を収めてきました。私たちは、他の人が私たちの経験から恩恵を受け、静的分析を自分のワークフローにうまく統合できることを願っています。

以上が静的コード分析ツールの構築に関する Google のケーススタディの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。