職人的デバッグと科学的デバッグ
千葉 滋
Feature 私のデバッグ、 bit、vol.29、no.1、pp. 24-25、共立出版、January, 1997.
私はここ数年デバッグなんてしたことがない。 と、こう書くと、いや、おまえがデバッグしているのを何度も見たことがある、とか、彼にバグレポートを送ったことがある、とかいう声がたくさん返ってくることだろう。 そんなタワケタことを書いている暇があったら、あのバグを早く直せ、とお怒りの方ももしかしたらいるかもしれない(すみません)。 それでも私は最近デバッグなんてしたことがないのだ。 少なくとも、この場で経験談を披露するほどデバッグで苦労したことはない。
デバッグというのは、もちろんプログラムのムシを取ることなのだが、ムシにもいろいろある。見つかる場所で分類すると次のようになるだろう。
(1) コンパイル時:文法エラーや型エラーなどの形でみつかるバグ。取るのは簡単。
(2) 実行時:プログラムが思ったとうり動かなくてみつかるバグ。すぐそこにいるのはわかっても、なかなか取れないことも多い。
(3) 配布時:ユーザからのバグ報告でみつかるバグ。仕様と呼ばれることが多い。
私だってもちろん毎日何千行ものエラーメッセージをコンパイラからもらうし、コンパイル一発完動などということも滅多にない。 でも大抵の場合、コンパイルエラーをてきぱきと直して、テスト実行で思ったとうりに正しく動いているのを確認して終わりである。 (3) のバグも少しはあるが、ほとんどは「仕様です」「次のリリースまでに直します」といってごまかせる程度のものだ。
私は(2)のバグに悪戦苦闘などということは滅多にない。 仮に(2)のバグがあっても、デバッガでちょっと追いかければ、問題の所在はすぐ明らかになる。 そもそもプログラムの挙動を見ただけで、どのあたりがおかしいか予想が立つことも少なくない。 時には(2)のバグに悩まされることもあるけれど、そういう場合は、プログラム自体の誤りというよりは、OSなどの下位システムの仕様を私が誤解しているのが原因だったりする。
その代わり、正直に言うと、私はプログラムを書くのがとても遅い。 いつもプログラムを書き始める前に、全体のモジュール構成や主要なデータ構造について、長いこと考えこんでしまい、なかなかプログラムを書き始められない。 書き始めてもなかなか前へ進まない。 とくに既に動いているプログラムに機能追加するときが遅い。 だいたいの当たりをつけてさっさと修正を始めればよいものを、頭の中で必要な修正をプログラムにほどこしてみて、これで絶対まちがいなく動くという確信がもてるまでは、プログラムを直し始められない。 確信がもてないときは、確信がもてるように修正方法を変えるか、あるいは修正そのものを止めてしまったりする。
ずっと以前パートタイムのプログラマをやっていたとき、私はプログラムにこれこれの機能を追加して、と言われて、「構成上できません」と答えたことがある。 (ああなんて怖いもの知らず。) 作り始めたときには、その機能のことなど想像だにしなかったので、追加するためにはプログラムの基本構成をあちこち直さなければいけなかったからだ。 もちろん、東大にある、ある建物のように、3階の上に後から4階を追加したようなプログラムを書けばよかったわけだが、そういう事はやりたくなかったのだ。 (実際、その建物はひどい雨漏りがする。)
一方、世間でハッカーと呼ばれるような人達は、違ったやり方でプログラミングするようである。 アメリカにいたある日、私はある筋金入の Lisp ハッカーと一緒にモニタの前に座って私のつたないプログラムについて検討していた。 彼いわく、
彼「ここの部分は、もっとましなやり方で書ける。ちょっと貸してみて。(カチャカチャ…)」
私「ああ… でもそうすると、あっちが…」
彼「いいか、ちゃんとしたプログラミングというのはこういう風に書くんだ…」
私「でもあっちも一緒に直さないと…」
彼「それは後で自分でやっといて…(カチャカチャ…)
よしこれで動くはずだ… あれ、くそ、間違った。
(カチャカチャ…)あちこち直したからバグってるけど、だいたいこんな感じだ。
後はやって。」
彼が去った後、彼が残していった無数の小さなバグを取るのに、私がその日の午後を費やしたことは言うまでもない。
一般にハッカー達は、自らの職人的直感を大切にしてプログラムを書く。 彼らのプログラミング・スタイルでは、だいたいの構成が浮かんだら、とにかくプログラムを書き始める。 そして素早く書き上げたら、時間をかけて山ほどあるバグを取る。 バグも行き当たりばったりに取っていくので、プログラムはどんどん複雑になっていく。 だからハッカーのコードはたいてい、汚くて書いた本人しか意味がわからない。 (なお前述の Lisp ハッカー氏は潔癖症的にきれいなコードを書く。) だが、彼らの偉大なプログラミング能力と驚異的な体力が、結局は、数々の素晴しいソフトウェアを生み出すのだ。
なんのかんの言っても、素晴しいソフトウェアは皆ハッカーの手によるものなので、適当に書いてしっかりバグを取るハッカーのデバッグ・スタイルが世間ではもてはやされるようである。 これを職人的デバッグと呼ぼう。 だが私は、最初からバグが出にくいプログラムを時間をかけて書き、デバッグでは苦労しない、という私のスタイルも悪くないと思うのである。 職人的デバッグの向こうをはって、これを科学的デバッグと呼びたい。
科学的デバッグとは、これすなわちソフトウェア科学を駆使したプログラミングである。 ここでは、オブジェクト指向や、デザインパターンも、学者の空論ではなくて、現実的で強力な武器である。 結局、バグはプログラムが複雑になりすぎて、プログラマの理解の範囲を超えるから発生するのだ。 だからバグが入りこむ余地のないよう、わかりやすい、きれいなプログラムを書けばよい。 もちろん、オブジェクト指向、オブジェクト指向、と唱えるだけでは、きれいなプログラムは書けないが、正しい境界でオブジェクトに切り分けられたプログラムは、自然ときれいになっているものだ。 正しい境界の見分け方を教えるのも、またソフトウェア科学の役目である。
科学的デバッグでは、プログラマがソフトウェア科学についてよく知っていなければならないし、職人的デバッグに比べてプログラムを書くのが遅くなるので、あまり魅力的ではないかもしれない。 とくに産業界では、長い時間をかけて、最初からバグのないプログラムを書くよりも、素早く書き上げたプログラムを、大勢のテスターを動員して、徹底的にバグを検査、プログラムを修正した方が、能率がよいかもしれない。 でも私のように、大学に籍をおいていて、いつも一人かあるいは小人数で開発をする者にとっては、科学的デバッグは、実際に動くソフトウェアを開発する唯一の方法である。 正直なところ、配布前の徹底的なバグ検査など、とてもでないが実行できない。 それに長い目でみれば、読みやすいプログラムは、保守しやすい。
ソフトウェア科学者のはしくれである私は、できたら科学的デバッグをこうして応援するだけでなく、科学的デバッグに貢献するような手法を自分でも開発してみたいと思っている。 だから、私が現在やっているリフレクションの研究も、そういう手法のひとつを生み出すことを目標にやっているつもりだ。
リフレクションというと、オブジェクト指向よりもっと曖昧模糊としていて、実用的には何の意味ももたない、と思っている向きもあるかもしれない。 しかし、例えば私の OpenC++ では、リフレクションを使って、普通の C++ では作成できない速くて便利なクラスライブラリを作成することができる。 そういうライブラリを活用してプログラムを書けば、プログラマが新たに書かねばならないコードの量が減り、バグの入る余地が小さくなる。 リフレクションが、科学的デバッグの一助になっている、ひとつの例である。
(終)