再録:Scott Trappeに聞く、コード品質についての10の質問

DevChannelでは、過去にOSDNに掲載された開発関連の優れたトピックを折に触れて再掲している。今回は、 Slashdot.org に昨年掲載された、コード品質についてのエキスパートScott Trappeへのインタビューを取り上げる。初出時に見逃した方はぜひお読みいただきたい。
Reasoning のCEOでコード品質のエキスパートであるScott Trappeに聞きたい質問を募集し、そのうち10の質問を実際に尋ねてみた。彼は質問に対する回答の中で、コード品質を向上させるためのいくつかのポイントと、彼がいかにして、もはや有名になった「LinuxのTCP/IPスタックは、商用ソフトの TCP/IPスタックより優れている」という結論に至ったかについて語ってくれた。

1)サンプルのサイズと結論
tim_maroneyからの質問

1つのサンプルから数百万ものコンポーネントを取り出せるような領域において、TCP/IPスタックという小さな変則的コンポーネントを取り上げただけで、2つの開発手法の相対的価値について結論を出すことができるものでしょうか?

Scott:

いいポイントをついた質問ですね。この質問に答えるには少々長くなりますが、おつきあいください。

ご指摘のとおり、この結論は、オープンソース開発の方が商用開発より優れていることを証明するものではありませんし、どちらの開発プロセスの方が優れているかを証明しようとしているわけでもありません。しかしこれは、「オープンソースソフトウェアは正式な開発プロセスではなく、包括的なテスト計画やインフラストラクチャもなく、アフターサポートや保守を担当する専門的リソースもないため、どうしても品質的に劣る」と主張する数々の記事や研究へのアンチテーゼです。我々の研究は、こうした主張に疑問を投げかける唯一の反例です。我々は目下、この結論が例外的なものにすぎないのかどうかを確認するために、他のオープンソースプロジェクトについても調査を進めているところです。調査結果についてはいずれご報告します。

我々がTCP/IPスタックを検討対象に選んだのは、その「変則的」なところが比較にちょうど適していたからです。TCP/IPスタックの一連の要件は綿密に定義され、正式に公表されており、何年も変わっていません。また、どの実装においても、公表された標準を厳守することが必須になっています。さらに、代替設計、パフォーマンス計測、サンプル実装について記した書籍や記事が数多くあり、一般的に利用できるコンフォーマンステストがいくつもあります。

したがって、大部分のソフトウェアプロジェクトとは異なり、我々が調べた実装はいずれも、遵守すべき共通の要件セットが確立され、高パフォーマンスできちんと動作する実装を設計するための情報が豊富にあるという状態にありました。しかも、これらの実装はいずれも発表後数年を経過したものでした。そのため、これらの実装を比較するに当たり、要件ドキュメントの品質、設計の一意性、検証用リソースの入手といったことについて悩む必要はありませんでした。

つまり、どの実装についても、非常に高品質の構成要素が揃っていたわけです。商用の実装は、他の研究で指摘されているとおり、包括的なテストを行うためのリソースが十分にある、バグについてのレスポンスがある、といった点で大いに有利です。我々が調べた5つの商用実装は、高品質の製品を開発することに定評があり、品質保証のために多大なリソースを投資している大企業が開発したものです。コード品質の良し悪しは、開発者のスキルだけの問題ではないと思います。これらの企業はいずれも優秀で有能で経験豊富なエンジニアを抱えているからです。

オープンソース実装を商用実装に対して好意的に比較したところ、驚くような結果になり、この結果には他の人も興味を持つだろうと我々は考えました。ただ問題は、オープンソース開発プロセスのどの部分の違いが、少なくともこのケースで認められたような品質の違いとして現れたのかという点です。オープンソース開発プロジェクトと商用開発プロジェクトの最も大きな違いの1つは、ピアレビュー(コード調査)のプロセスです。主要なオープンソースプロジェクトではピアレビューが徹底的に行われますが、ほとんどの商用プロジェクトでは、リソースと時間の制約からピアレビューが十分に行われていません。

2)オープンソース化の推進には何が必要か
argmanahからの質問

オープンソースが品質向上に直接的に寄与するものであるならば、企業はなぜいまだに自社のソースをオープンにしないのでしょうか? 我々はソースコードをあらゆるケースでオープンにするよう各社に働きかけるべきでしょうか? もしそうならば、企業を説得するために何をする必要がありますか?

Scott:

1番目の質問の回答で述べたとおり、我々はまだオープンソースの方が常に優れていると証明したわけではなく、その可能性について示唆しただけです。オープンソース開発プロジェクトの大きなメリットの1つは、時間に余裕があることです。オープンソース開発者は、自分の納得のいくところまで好きなだけ時間をかけることができます。商用プロジェクトでは、そのような機会はめったにありません。顧客からの要求や競争圧力によって厳しいスケジュールを強いられ、時間切れになることもしばしばあります。

仮に、オープンソースの方が常に高い品質を保証できるとしても、品質と利益は同義ではありません。大部分の商用ソフトウェアベンダがオープンソースに対して懐疑的な姿勢を取っているのは、それによって儲けを得る方法がわからないからです。Red Hatは、オープンソースに基づくビジネスモデルを採用している企業の中でおそらく最も大きな成功を収めている例ですが、昨年はわずかばかりの利益しか上げられませんでした。ソフトウェアをオープンソース化しても採算性や収益性の低下には結び付かないと経営陣を納得させられる状況にならなければ、オープンソース化の推進は難しいでしょう。

企業が持つすべてのコードをオープンソース化するよう働きかけても、おそらく失敗するでしょう。それよりも、一部のソフトウェアをオープンソース化し、残りは非公開のままにするというハイブリッド的なアプローチの方が有効です。たとえば、以前に弊社のエンジニアと営業スタッフ数人が、弊社のコード訂正ツールをオープンソース化することを私に提案してきました。彼らは、オープンソース化によって比較的低いコストで顧客にメリットを提供できると私を説得したのです。他の企業でも、少なくとも限られた範囲では、同じようにして経営陣を説得できる可能性があります。

3)プロジェクトサイズの影響
arvindnからの質問

LinuxカーネルやApacheのような知名度の高いプロジェクトの場合は、バグ修正を並列的に行うことは非常に効率的であり、そのメリットも明らかです。しかし、大部分のオープンソースプロジェクトでは開発者が1〜5人しかいません。ソースコードを公開することで大きなメリットを得られるのは、どのくらいの規模のプロジェクトからなのでしょうか?

Scott:

私は、どんな規模のプロジェクトでもピアレビューのメリットはあると考えています。開発者が1人しかいないプロジェクトでも、ピアレビューは重要な意味を持ちます。言うまでもありませんが、プロジェクトに携わる開発者の数が増えるほど、誤解や行き違いの可能性は格段に大きくなります。エラーの大部分は、2人以上の開発者がコード内の別々のパーツを、そのパーツ間のインタフェースのことをよく理解せずにいじった結果として発生します。

4)ソフトウェアの品質とバグの少なさ
gosandからの質問

私はソフトウェア品質保証チームで働いて10年になります。私の経験から言えば、純粋なソフトウェアバグはソフトウェア品質のごく一部にすぎません。ソフトウェア開発のライフサイクルではさまざまなものが見失われます。不明確な要件がライフサイクルをそのまま通過して、最終的に顧客側でバグとして現れることもあります。品質のもう1つの重要なポイントはユーザビリティです。たとえバグがまったくないソフトウェアでも、使い方が非常に難しかったり、顧客のニーズに合わなかったりすれば、役には立ちません。

あなたの会社では、知覚的なバグではなくコード的なバグを分析することに焦点を当てているようですが、この意見についてはどうお考えでしょうか? バグを見つけ出して排除することがソフトウェア品質保証の重要なプロセスであることは承知していますが、バグがなければ必ず高品質と言えるのでしょうか? バグのないオープンソースプロジェクトでも、実際には、技術的知識のない人にとっては使い方が難しすぎたり、理解できなかったりする可能性があります。

Scott:

ご意見はまったくの正論であり、我々も、弊社のIllumaが万能であるとは思っていません。ご指摘の2つの問題については、今日ではよい方法があります。アプリケーションが所定の要件を満たしているかどうかを確認するには従来のブラックボックステストが有効であり、顧客のニーズを本当に満たしているかを判定するには実際のユーザによるユーザビリティテストが重要です。我々が問題にしているのは、一般的なソフトウェアの中に「コード的なバグ」があまりにも多く、品質保証チームが作業時間の大半をそれに取られてしまうため、ソフトウェアが要件に合致しているかどうかを十分に確認する時間がないという点です。弊社はこの状況を改善するために、コード的なバグについての詳しいフィードバックを開発者に頻繁に返すようにして、堅牢でほぼ完全に機能する状態のアプリケーションを品質保証チームに渡せるようにすることを目指しています。

5)プログラミングの全体的な品質
pro-mpdからの質問

プログラミングの品質は、プログラマの住む地域によって左右されると思いますか? たとえば、オープンソースプログラムは世界中のさまざまな国の人々によってトラブルシューティングされたり調査されたりする可能性があります。それに対して、クローズドソースソフトウェアはそれを書いた国の人によってチェックされます。教育の質や重点箇所は国によって異なるということを考えると、同じ能力やバックグラウンドを共有する人々だけでソフトウェアをチェックするよりも、オープンソース化して世界各国の人にチェックしてもらった方が、プログラムをさまざまな角度から検討することができるでしょうか?

Scott:

質問のポイントは2つあります。つまり、(1)開発者の居住地域がソフトウェアの品質にどのような影響を与えるか、(2)開発チームを地理的に分散させると開発者の多様性によって品質向上が期待できるか、ということです。

1つ目の質問については、確かに教育の質は国によって大きく異なり、文化的な背景が何らかの影響を与えることもないとは言えません。しかし、プログラマの生産性と品質は、民族性と教育を同じくするグループの中でも大きな開きがあることが数々の研究で報告されています。したがって、ソフトウェアの品質は、チームの構成員の居住地域よりも、その人の個人的な能力によって左右されるものだと考えるべきでしょう。

2つ目の質問については、その前提になっている考え方に異議があります。オープンソースプロジェクトのチームは、バックグラウンドと教育を同じくする人々から構成されることがよくあります。一方、商用開発チームの多くは、地理的に集中しているか分散しているかに関係なく、きわめて多様な開発者から構成されます。この問題についても、最も大きな要因はプログラマ個人の能力であり、居住地域はごく小さな要因にすぎません。

6)商用プロジェクトとオープンソースプロジェクトのテストケースの問題
Tekmageからの質問

オープンソースプロジェクトと商用プロジェクトを比較するときの大きな問題の1つは、テストケースの機密性をどのように管理するかです。Red HatやXimianといった企業は、中核的な製品やプロジェクトを自分たちで管理しているので、これは大きな問題になりません。しかし、特定の問題を解決できる唯一の適格な人物が外部にいて、その人物が問題のテストケースを使用できないときには問題が生じます。

このテストケースの管理と機密性のトレードオフは、商用コード開発とオープンソースコード開発にどのように関係してくると思われますか?

Scott:

これはオープンソースにもクローズドソースにも共通する問題です。たとえば、ある半導体企業のデバイスシミュレーションプログラムで重大な欠陥が明らかになったとします。この企業は自分たちの「テストケース」(その企業が設計したチップ)を企業秘密と見なしていて、そのアプリケーションがオープンソースであろうとクローズドソースであろうと、テストケースを外部の人と共有したくないと考えています。そのアプリケーションについての外部のエキスパートを呼んできて、企業の構内でバグ修正の作業ができる場合には、オープンソースの方が有利かもしれません。このような状況には、ほとんどの商用開発環境よりも、オープンソースプロジェクト用のフレームワーク(SourceForge.netなど)の方が適しています。しかし、企業というものは、ライバルより少しでも優位に立つための方法を探しているものです。もしもこの企業がオープンソース方式を採用する場合は、自分たちを差別化するために別の手段を見つけなければなりません。Red HatやSuseなどは、(a)ディストリビューション内に含めるコンポーネント、(b)統合されたコンポーネントが協働することの証明、(c)サービスとサポートの品質、という点で差別化を図っています。したがって、たとえばRed Hatのような企業にとっては、自社のバージョンのLinuxを他のものから差別化するためにテストケースを公開せずにおくことは合理的な判断です。オープンソースに基づくビジネスではこのやり方が普通です。

7)中立性の証明
arvindnからの質問

あなたと同様の研究を行った(そして最終的にクローズドソースの方が優れていると結論付けた)「独立機関」の多くは、実はクローズドソース側(microsoft.com)の後援を受けていたという事実が明らかになっています。このような情勢で、あなたは自分の中立性をどのようにして証明しているのでしょうか? あなたの会社(reasoning.com)は製品ではなくサービスを販売しているので、ビジネス的な観点からすれば、あなたの独立性についての顧客の信頼は非常に重要な意味を持つと想像されます。その信頼をどうやって獲得し、維持しているのでしょうか? 記事によれば、あなたはESRのオープンソース推進意見に賛同しています。オープンソースソフトウェア寄りであるという認識は避けたいところなのではないでしょうか?

Scott:

1番目の質問に対する回答で述べたとおり、我々はオープンソースの方が商用ソフトウェアより優れているとか劣っているということを証明しようとは考えていません。我々の目的は、開発プロセスを効率化し、時間と経費を節約することで、顧客が優れたソフトウェアを開発できるように支援し、顧客の競争力を向上させることです。欠陥を排除するにはコード調査が唯一かつ最も効果的な方法であることが立証されており、我々は徹底的な調査を低コストで迅速に行うための手段を提供します。我々が比較検証を始めたときには、どのような結果になるかはまったくわかりませんでしたが、最終的に得られた結果は、「コード調査はソフトウェアの品質に大きな影響を与える」という我々の信条を裏付けるものでした。そして、そのコード調査という手法が、たまたま主要なオープンソースアプリケーションで一般的に採用されていたというだけの話です。

8)オープンソースがそんなにいいものならば…
anthony_dipierroからの質問

その自動調査ツールのソースコードはどこで手に入りますか?

Scott:

おいくらで買っていただけますか? :-)

真面目な話、2番目の質問に対する回答でも述べたとおり、ソースコードをオープンにしつつ、株主たちに相応の(あるいはそれ以上の)見返りを提供するための方法というものはまだ見つかっていません。この問題は、オープンソース擁護派が取り組まなければならない最も難しい課題の1つです。

9)自動コード調査の将来像
phamlenからの質問

記事によれば、その自動調査ツールはバッファオーバーフロー、メモリの早期解放、その他のメモリ問題を見つけてくれるということですね。

現在は自動的に検出できなくても、将来的に検出できるようになると予想されるエラーにはどんなものがありますか? 今後の自動コード調査で検出しようと研究を進めているエラーのカテゴリはどんなものですか?

たとえばこんなものを検出できると嬉しいのですが。

  • リファクタリングされていないコード – 重複が多く、クリーンアップが必要なコード
  • テストされていないコード – まだユニットテストが行われていないコード(またはコード内の分岐)
  • プログラマの意図と異なるエラー – プログラマの意図どおりに動かないエラー

Scott:

私はいつも、エディタに”DWIM”(Do What I Mean:私の考えているとおりのことを書け)というコマンドがあればいいのにと思っています。そうすれば、コーディングのときも、ただ手紙を書くときも、こんなに頭を悩ませなくても済むのですが。:-)

真面目にお答えすれば、4番目の質問に対する回答で述べたとおり、自動調査で検出できるのは「コード的なエラー」だけであり、「意図と異なるエラー」は検出できません。つまり、アプリケーションが要件ドキュメントの内容に従っているかどうかを検証することはできません。たとえば、あるルーチンで「数値リストの幾何平均を計算する」という要件に反して相加平均を計算していた場合に、そのエラーを検出することはできません。現時点で検出できるのは、NULLポインタの参照解除(dereference)、初期化されていない変数の参照、配列境界の違反(バッファオーバーフローのスーパーセット)、メモリリーク、不正な解放です。

一般的に、静的分析アプローチで検出できる欠陥は、(a)内部的な矛盾(プログラムのある時点でNULLへの参照を設定したのに後でそのポインタを参照解除するなど)、(b)言語のセマンティクスまたは標準のライブラリ関数で規定された制約に対する違反、という2つの理由によるものだけに限られています。

そこで、この範囲内で次のエラーを検出するよう努めています。(a)同時実行に関するエラー:デッドロック、レース条件など(これらは検出が難しく、テストするのも困難なエラーとして有名です)、(b)リソースリーク(メモリリークに似ていますが、ファイル記述子やハンドルといった別の種類のリソースに適用される点が異なります)、(c)プロトコルの違反:APIの不正使用(ファイルを閉じた後に読み書きしようとするなど)、(d)デッドコード(絶対に実行されないコード)、(e)パフォーマンスのボトルネック:非効率的なアルゴリズム(バブルソートの使用など)やコード内の「渋滞地帯」。

ご提案いただいたアイデアも捨てがたいのですが、現在は「深刻な欠陥」、つまりアプリケーションを異常終了させたり、ハングさせたり、警告なしにデータを破壊したりするエラーについて研究を進めています。あなたの1つ目のアイデアは、どちらかと言えば「下手なプログラミング作法」のカテゴリに含まれるもので、将来的にはこのタイプの分析も組み込もうと考えています。なぜなら、複雑すぎるルーチンとバグは相関関係にあるからです。

10)テストファースト開発
neurojabからの質問

新しい「テストファースト」と呼ばれるソフトウェア開発手法についてはどうお考えですか? 聞いたことのない人のために簡単に説明しておくと、これは最初にプログラム用のテストケースを書き、失敗テストケースを通るコードを書くという手法です。この手法では、すべてのテストケースが自動化され、コード変更のたびに実行されます。あなたはオープンソースプロジェクトにおけるテストファースト開発を支持しますか? つまり、さまざまなコントリビュータが個々の新機能についてのテストケースを記述し、それをプロジェクトの共通テストケースリポジトリに追加し…というやり方をどう思いますか?

Scott:

私の経験から言って、プログラマが好きなのはコードを書くことにほかなりません。つまり、ドキュメントを書いたり、システムテストを書いたり、ユニットテストを書いたりすることは好みません。また、プログラマは楽観主義者です。そうでなければ、だれがあのような非常に複雑なシステムの開発に進んで取り組みたいと思うでしょうか。さらに、プログラマはすぐに満足が得られることを好みます(もっとも、そうでない人はいないでしょう)。彼らは問題の解決策を提案し、その解決策がすぐに実装されることを好みます。

プログラマは楽観主義者なので、彼らが作成するユニットテストにもその傾向が反映されます。私がこれまで何度も見てきたのは、開発者の作成したテストケースを使って機能がうまく動作することを証明できたとしても、それはそのテストケースが、機能の使い方についての開発者の考え方を反映していたからにすぎなかったという例です。コーナーケース、限界、あるいは「普通でない」状況(メモリやその他の有限リソースを使い果たすなど)のテストということに関しては、プログラマが有意義な仕事をすることはめったにありません。

さらに私は、テストファーストの手法はプログラマの動機付けにも反していると考えています。もしも、Linusが最初にネットワークに投稿したのがUNIX風のオペレーティングシステムのテストケースだったとしたら、Linuxは誕生していたでしょうか? 他の人々は、自分もテストケースを書いてみようという気持ちになったでしょうか? いったいどのくらいの反応があったでしょうか? もしも最初の1年間がユニットテストの作成に費やされていたとしたら、オープンソースのオペレーティングシステムを作成するのだという期待に胸を膨らませる人々はいったい何人いたでしょうか?

私は懐疑的すぎるかもしれませんが、テストファーストは、過去にいろいろあった、大きなメリットを約束するものとして華々しく登場しながら結局は実現できずに終わったソフトウェア開発手法の数々を思い出させます。私としては、それよりも、Extreme Programmingの「ペアプログラミング」といったいくつかの新しい手法に興味を惹かれます。