静的解析とは
静的解析とは、アプリケーションを実行せずにソースコードを自動的に分析することです。
プログラムの実行中に分析が実行される場合、動的分析と呼ばれます。
スタティック解析は次のものを検出するために頻繁に使用されます。
- セキュリティ上の脆弱性。
- パフォーマンスの問題。
- 標準への違反。
- 時代遅れのプログラミング構成体の使用。
静的解析ツールはどのように機能しますか?
すべての静的解析ツールに共通する基本概念は、ソースコードを検索し、何らかの警告や情報が関連付けられている特定のコーディングパターンを特定することです。
これは、「JUnit 5のテストクラスは「公開」である必要はない」といった単純なものかもしれません。あるいは、「信頼できない文字列入力が SQL 実行文で使用されている」など、見分けが難しいものもあります。
静的解析ツールは、この機能の実装方法が異なります。
- 抽象構文木 (AST) を作成するためのソースコード解析技術
- テキスト正規表現マッチング、
- 上記の組み合わせ。
テキストでの正規表現マッチングは非常に柔軟で、一致させるルールを簡単に記述できますが、多くの場合、誤検出が多数発生する可能性があり、マッチングルールは周囲のコードコンテキストを認識しません。
AST照合では、ソースコードを単なるテキストで埋め尽くされたファイルではなく、プログラムコードとして扱います。これにより、より具体的かつ状況に応じた照合が可能になり、コードに対して報告される誤検出の数を減らすことができます。
継続的インテグレーションにおける静的解析
多くの場合、静的解析は継続的インテグレーション(CI)プロセス中に実行され、コンプライアンス問題のレポートを生成します。このレポートをレビューすることで、時間の経過とともにコードベースを客観的に把握できます。
静的解析ツールを特定のコード部分のみを測定し、ルールのサブセットのみを報告するように構成することで、静的解析をコード品質の客観的な尺度として利用する人もいます。
客観性は、使用されるルールによって決まります。これらのルールは、時間の経過とともにコードの評価において変化しないためです。明らかに、使用されるルールの組み合わせとその構成は主観的な決定であり、異なるチームは異なるタイミングで異なるルールを使用することを選択しています。
CIで静的解析を実行することは便利ですが、プログラマーへのフィードバックが遅れる可能性があります。プログラマーはコーディング時にフィードバックを受け取らず、後で静的解析ツールでコードを実行したときにフィードバックを受け取ります。CIで静的解析を実行することによるもう1つの副作用は、結果を無視しやすくなることです。
チームが静的解析の結果に注目しやすくするために、通常、ビルドプロセスでしきい値メトリクスを設定し、メトリクスを超えた場合にビルドが失敗するように設定できます。例えば、多数のルールがトリガーされた場合などです。
IDE での静的解析
フィードバックをより早く受け取るために、IDE の静的分析ルールをオンデマンドで、またはコードが変更されたときに定期的に実行する IDE プラグインが多数用意されています。
プログラマがコードを記述している際に、IDEでルール違反を確認できるようにし、ルールを無視しにくくするため、エディタで下線付きのコードとしてレンダリングされるように違反を設定できることがよくあります。
個人的には、これはコーディングを改善するのに便利な方法だと思います。特に、静的解析ツールでカバーされている新しいライブラリを使用する場合は特にそうです。ただし、誤検出や興味のないルールがあると「ノイズが多い」場合があります。しかし、特定のルールを無視するように静的解析ツールを設定するという追加の手順を踏むことで、この問題を解決できます。
静的解析ルールに基づくコードの修正
ほとんどの静的解析ツールでは、ルールの修正はプログラマーに任されているため、プログラマーはルール違反の原因と修正方法を理解する必要があります。
違反を修正する機能を備えた静的分析ツールはほとんどありません。修正は、多くの場合、チーム、使用するテクノロジー、および合意されたコーディングスタイルに合わせて行われるためです。
デフォルトルール
静的解析ツールにデフォルトのルールが用意されていると、ルールの品質に対する誤った信頼が生じる可能性があります。プログラマーが遭遇する可能性のある全ての問題と、そのルールが適用すべき全ての状況をカバーしていると信じ込んでしまうからです。ルールを適用すべき状況は微妙で、簡単に見分けることができない場合があります。
静的解析ツールを使用し、ルールと違反をより詳細に調査することで、プログラマーが特定のドメインの文脈において問題を検出し回避するスキルを身につけることが期待されます。
ドメインにコンテキストルールが必要な場合、静的解析ツールにはドメインまたはライブラリに一致するルールが存在しない可能性があり、さらにツールの構成や拡張が困難な場合があります。
煩わしさ
これらの「煩わしさ」はどれも乗り越えられないものではありません。
- 偽陽性
- 修正の欠如
- ルールを無視する設定
- コンテキスト固有の規則の追加
しかし、そもそも静的解析ツールの使用を避けるための言い訳としてよく使われます。静的解析は次のような方法として非常に役立つ場合があるため、残念です。
- 若手開発者へのより良いアプローチを強調
- 明確なコーディング違反に関するフィードバックを迅速に取得
- プログラマーがこれまで遭遇したことのない不明瞭な問題を特定する
- プログラマーが優れたコーディング手法を採用していることを強調する(違反が報告されていない場合)
IDEベースの静的解析ツール
プロジェクトへの個人寄稿者として、コードに関するフィードバックを迅速に受け取れるように、IDE内で実行される静的解析ツールを使用するのが好きです。
これにより、プルリクエストレビュープロセスや、プロジェクトが持つ可能性のあるCI統合が補完されます。
私は、自分に優位性をもたらし、個々のワークフローを改善してくれるツールを見つけるようにしています。
IDE でツールを実行する場合、基本的な GUI と構成アプローチは同じ傾向があるため、同じように表示したくなる場合があります。
ツールには重複する機能やルールセットがある場合がありますが、その利点を最大限に活用するために複数のツールをインストールしています。
コーディング時に私が積極的に使用している静的解析IDEツールは以下の通りです。
- 組み込みの IntelliJ インスペクション-一般的なコーディングパターン
- スポットバグ-よくあるエラー
- SonarLint-一般的な使用パターン
- チェックスタイル-一般的なスタイルパターン
- セキュア・コード・ウォリアーの先生-カスタムルール作成
私はそれらをすべて使用しています。なぜなら、それらは互いに補完し合ってうまく連携するからです。
IntelliJ インスペクション
IntelliJを使用している場合は、すでにそのインスペクションを使用していることになります。
これらは IDE でフラグが付けられた静的分析ルールです。その中には、問題に対処するためにコードを書き換える QuickFix オプションがあるものもあります。
ルールはオンとオフを設定でき、IDE で強調表示するエラーレベルも選択できます。
IntelliJの優れたインスペクションは数多く存在します。これを書いている間にそれらを確認したので、そのことは承知しています。私はIntelliJのインスペクションをデフォルトで使用していますが、まだ設定は行っていません。インスペクションを最大限に活用するには、インスペクションを確認し、自身のコーディングスタイルに関連するものを特定し、コード内で気づけるよう警告レベルを設定する必要があります。
IntelliJのインスペクションの素晴らしい点は、IDEに無料で付属していることと、次のような筋肉の記憶を構築するのに役立つことです。
- コードを書いているときにソース内の警告やエラーに気づく
- フラグが設定されたコードにカーソルを合わせると、ルール違反がわかります
- Alt+Enter キーを使用して問題のクイックフィックスを適用する
スポットバグ
SpotBugIntelliJプラグインは、静的解析を使用してコードのバグを警告します。
SpotBugs は IntelliJ の環境設定からコードをスキャンするように設定できます。実際に使用されるルールは Detector タブにあります。
私はコードを書いてレビューした後、SpotBugsを使う傾向があり、その後「テストソースを含むプロジェクトファイルの分析」を実行します。
これは、バグ、デッドコード、明らかな最適化を特定するのに役立ちます。また、何をすべきかを判断するために、フラグが立てられた違反のいくつかを調査する必要があります。
SpotBugs は問題を検出しますが、問題を解決するためのクイックフィックスアクションは提供しません。
SpotBugs は設定が簡単で、IDE 内で参照する客観的なセカンドオピニオンとして役立つと思います。
ソナーリント
ザのソナーリントプラグイン。
SonarLintは、IntelliJの設定から設定し、コードの検証対象となるルールを選択できます。
デフォルトでは、SonarLint はリアルタイムで実行され、編集中の現在のコードの問題を表示します。
SonarLintは迅速な解決策を提供していませんが、違反報告に関連する文書は通常明確で十分に文書化されています。
SonarLint は、これまで Java の新しいバージョンで認識していた新しい Java 機能について警告してくれるので便利でした。
チェックスタイル
ザのチェックスタイルプラグインは、フォーマットとコード品質ルールを組み合わせて提供しています。
CheckStyleプラグインには、「サンチェック」と「Googleチェック」がバンドルされています。
これらの定義は簡単に見つけることができます。
CheckStyleは、プロジェクトが時間をかけて独自のルールセットを作成した場合に最大の価値をもたらします。そうすれば、IDEプラグインがそのルールセットを使用するように設定でき、プログラマーはコードをCIにコミットする前にスキャンを実行できます。
CheckStyle は、CheckStyle 違反の数がしきい値を超えた場合に CI プロセスのビルド失敗プラグインとしてよく使用されます。
先生
先生、コードの照合とクイックフィックスの作成には、抽象構文木(AST)に基づく静的解析を使用します。これにより、問題のあるコードを非常に具体的に特定できます。
ASTを使用すると、レシピに関連するQuickFixが周囲のコードを理解できます。例えば、コードに新しいクラスを追加する場合、そのクラスのインポートはソースファイルに一度だけ追加され、置換のたびに追加されることはありません。
Senseiは、他のツールには存在しない場合や設定が難しいカスタムマッチングルールを簡単に構築できるようにするために作成されました。
設定ファイルを修正する代わりに、すべての設定をGUIで実行できます。新しいレシピを作成する場合、GUIではレシピがどのコードと一致するかを簡単に確認できます。また、QuickFixを定義すると、コードの前後の状態をすぐに比較できます。これにより、チームやテクノロジー、さらには個々のプログラマーに固有のレシピなど、非常に文脈に沿ったレシピを簡単に作成できます。
私はSenseiを他の静的解析ツールと組み合わせて使用しています。例えば、ほとんどの静的解析ツールは問題を検出しますが、修正はしません。Senseiの一般的な使用例は、他のツールの一致検索をSenseiで複製し、クイックフィックスで拡張することです。これには、適用されたカスタムフィックスがプロジェクトのコーディング標準を既に満たしているという利点があります。
Intensionレポートが作成したコンテキストと完全に一致しないか、IntelliJが提供するQuickFixが使用したいコードパターンと一致しないことが原因で、IntelliJのIntensionsセットに既に存在するSenseiレシピを定期的に作成しています。
既存のツールを完全に置き換えようとするのではなく、既存のツールを補強します。
Senseiは、共通ルールのコンテキストバリアントを特定する場合にも非常に役立ちます。例えば、静的解析ツールでサポートされていないSQLライブラリを使用している場合でも、静的解析エンジンの共通SQLルールが引き続き適用される場合、Senseiを使用してそれらのルールのライブラリ固有のバリアントを作成できます。
Senseiは、前述の静的解析ツールのように一般的なレシピをすぐに提供しているわけではありません。その強みは、特定のコーディングスタイルやユースケースに合わせて構成されたQuickFixを使用して、新しいレシピを簡単に作成できることです。
注:現在、一般的なユースケースに対応するために、レシピの公開リポジトリを作成中です。 こちらで見つけることができます。
サマリー
私は、連携して動作し、設定可能で、特定のコンテキストに合わせて簡単に拡張できるツールを選ぶ傾向があります。問題を特定したり、使用しているプログラミング言語やライブラリについて理解を深めたりするために、IDE の静的解析ツールを長年使用してきました。
上記のすべてのツールを組み合わせて使用します。
- IntelliJ Intentionsは、よくあるコードの問題をすぐに報告するのに役立ちます。多くの場合、関連するクイックフィックスを使用します。
- SpotBugs は見逃したかもしれない単純なバグを見つけ、パフォーマンスの問題を知らせてくれます。
- SonarLint は、私が気づいていなかった Java の機能を特定し、コードをモデル化する他の方法を教えてくれます。
- CheckStyleは、CI中にも適用される合意されたコーディングスタイルに準拠するのに役立ちます。
- 先生は、静的解析ツールで見られる一般的なシナリオを補強したり、別のツールでは構成が難しい特定のプロジェクトや技術レシピを作成したりするためのクイックフィックスの作成をお手伝いします。
---
「環境設定\ プラグイン」(Mac) または「設定\ プラグイン」(Windows) を使用してIntelliJ内からSenseiをインストールし、「senseiセキュアコード」を検索してください。
一般的なユースケースのサンプルコードとレシピのリポジトリは、Secure Code Warrior アカウントの「sensei」プロジェクトにあります。
https://github.com/securecodewarrior/sensei-blog-examples
先生についてもっと知る