静的解析の役割は、バグを直接見つけることだけではありません。コードの可読性と保守性を損なう可能性のある、バグを招きやすい状況を特定することも含まれます。静的解析では、コードのほかの多くの特性も扱えます。
- コードメトリクス:たとえば、ループや if、else、switch、case 文が多すぎるメソッドは理解しにくくなり、その結果保守も難しくなります。循環的複雑度というコードメトリクスでこれらを数えることは、メソッドが複雑になりすぎたかどうかを評価する優れた方法です。
- 依存関係:プログラム内のクラスが複雑に絡み合っていると、コードを変更した場合の影響を予測できなくなります。静的解析を使えば、クラスやコンポーネントが絡み合っている状況を評価できます。
- 不変性:複数のスレッドから同時に使用される型は、不変であるべきです。そうでなければ、状態の読み書きを複雑なロック戦略で保護する必要があり、最終的に保守不能になります。静的解析により、特定のクラスが不変のまま保たれていることを確認できます。
- デッドコード:デッドコードとは、実行時にもはや呼び出されないため安全に削除できるコードです。このコードは削除 できます だけでなく、削除 しなければなりません 。なぜなら、この余分なコードはプログラムに不必要な複雑さを追加するからです。静的解析を使えば、プログラム内のほとんどのデッドコード(ただしすべてではありません)を検出できます。
- APIの破壊的変更:クライアントへAPIを提供している場合、公開メンバーを気づかずに削除し、クライアントのコードを壊してしまうことは容易に起こり得ます。静的解析では、プログラムの2つの状態を比較して、この落とし穴について警告できます。
- APIの使用法:慎重に使うことを意図したAPIもあります。たとえば、破棄可能なフィールドを保持するクラスは、通常、そのクラス自身も破棄可能であるべきです。ただし、破棄可能なフィールドの有効期間がクラスインスタンスの有効期間と一致しない場合は例外です。その場合は、設計上の問題の兆候と言えます。
Cppcheck、Clang、Visual Studio アナライザーなど、C++コードベースのバグを検出する便利なツールは多数あります。では、バグを招きやすい状況の特定についてはどうでしょうか。
静的解析ツールの開発者は、どの状況をバグと見なすかを決められますが、バグを招きやすい状況についてはそうはいきません。それらは開発チームの判断に依存します。たとえば、20行を超えるメソッドを複雑と見なすチームもあれば、上限を30行に設定するチームもあります。ツールがバグを招きやすい状況を検出するなら、関連するルールをカスタマイズする方法も提供しなければなりません。
Code as Data はバグを招きやすい状況を検出する最良の方法
静的解析とは、ソースコードをさまざまな特性について解析し、その結果を報告するという考え方です。しかし、哲学的には、コードをデータとして扱うという考え方でもあります。アプリケーション開発者である私たちは、ソースコードを命令、手続き、アルゴリズムとして考えることに慣れているため、これは非常に奇妙に感じられます。しかし、同時に非常に強力でもあります。
ソースファイルを解析した後、そのASTを抽出し、コードに関する有用な情報を豊富に含むモデルを生成できます。生成されたモデルには、SQLに似たコードクエリ言語を使って問い合わせられます。
CppDepend は、コードベースをデータベースのように照会できる強力なコードクエリ言語 CQLinq を提供しています。開発者、設計者、アーキテクトは、カスタムクエリを定義して、バグを招きやすい状況を簡単に特定できます。
CQLinqを使うと、コードメトリクス、依存関係、API使用状況、モデルのその他の情報を組み合わせて、特定のバグを招きやすい状況に一致する高度なクエリを定義できます。
最も複雑なメソッドに一致するCQLinqクエリの例を次に示します。

まとめ
コードベースの問題を検出するには、複数のC++ツールを組み合わせるのが望ましい方法です。バグを検出するツールもあれば、バグを招きやすい状況まで検出するツールもあります。CppDependでは、複数のツールの強みを組み合わせることを目指しています。カスタムクエリを簡単に定義できる手段を提供し、最近では、ほかの静的解析ツールの結果をインポートしてCQLinqで照会する機能も追加されました。
