プログラマが知るべき97のこと/コード分析ツールを利用する


プログラマの中には、「テストがいかに重要か」を、プログラミングを始めた頃から頭にたたき込まれてきた人が多いでしょう。近年では、ユニットテストやテスト駆動開発、アジャイル開発などが広く行われるようになり、開発サイクルのあらゆるフェーズでテストを最大限活用するという考え方を受け入れる人も増えました。しかし、テストがいかに重要と言っても、それがコードの品質を高める唯一の方法というわけではありません。他にも方法は数多くあるのです。

はるかな昔、まだCが「新しい言語」だった頃、CPU時間と記憶容量はとても貴重なものでした。このため最初期のCコンパイラでは、コードを読み取る回数を減らすためにセマンティクス分析の一部が省略されていました。つまり、コンパイル時にはバグの検出があまりできなかったのです。その埋め合わせとして、Stephen Johnsonはlintというツールを書きましたにこれは、初期のCコンパイラでは行われなかった静的解析のためのツールで、バグを減らすのに非常に役立ちました。ただ、静的解析ツールには問題もありました。バグの誤検出が多かったのです。実際には問題がないところで警告を出してしまうことも多く、必ずしも守らなくてよいコーディングスタイル上の規約についての警告も多く出してしまっていました。

現在、言語やコンパイラ、静的解析ツールをめぐる状況は当時とは大きく異なっています。メモリやCPU時間は相対的に「安い」ものになり、コンパイラ自身がチェックできるエラーも大幅に増えました。ほほ全ての言語で、必ず1つは、スタイルガイドの違反や、よく見られるバグを検出するためのツールが用意されるようになっています。中には、ヌルポインタ逆参照など、かなり見つけにくいバグを検出できるツールまであります。

C向けのSplint、Python向けのPylintなどは、設定変更も可能な高度なツールです。「設定変更ができる」というのは、この場合、検出するエラーや警告の種類を選ぶことができるということです。設定変更には、設定ファイルや、コマンドライン引数などを使用する他、IDEでの設定変更ができる場合もあります。Splintには、プログラムの処理がよりわかりやすくなるよう、注釈をコメントのかたちで入れる機能もあります。

簡単なバグやちょっとした規則違反が、コンパイラでもIDEでも、lintツールでも検出できないということはあります。その検出のために、独自の静的チェッカーを作ることもできます。そういうと何やら難しそうですが、実際にはそうでもありません。ほとんどの言語、特に「動的」と言われる言語では、抽象構文ツリーやコンパイラツールが標準ライブラリの一部に含まれていて、誰でも使えるようになっているからです。開発に普段使用している言語の標準ライブラリにも、あまり使われないような片隅に、静的解析や動的テストに利用できる便利なものが隠れているかもしれません。よく調べてみる価値はあるでしょう。たとえばPythonの標準ライブラリには、「逆アセンブラ」が含まれています。コンパイル済みのコード、あるいはコードオプジェクトが、どのようなバイトコードから生成されたのかがそれでわかるのです。逆アセンブラなどと言われると、Python言語の開発チームのコンパイラ担当者のみが使うような難解なツールなのではとも思えますが、しかし実際には、一般のプログラマの作業にも驚くほど役立つのです。たとえば、逆アセンブルできるものの中には、最新のスタックトレースなども含まれます。これにより、直近の(捕まえられなかった)例外を投げたのが、どのようなバイトコードだったのかを正確に知ることができます。

コードの品質向上にあたっては、テストだけに頼るのではなく、解析ツールも積極的に利用すべきでしょう。自らツールを作ることにも、恐れることなくぜひ挑戦してみてください。