混沌の廃墟にて -149-

アマチュアとプロのあいだ (2)

1991-04-18 (最終更新: 1996-03-05)

[↑一覧] [新着] [ホームページ]


Cマガジン4月号の「最新デバッグ学入門」という特集の中、「デバッグ学概 論」で三田典玄氏が、デバッグのノウハウについてプロなりのご意見を述べてい る。文の内容から、氏はお金を取って仕事をするという意味ではプロなのではな いかと、私は勝手に想像している。

さて、プロという言葉には、金銭的な意味合いだけでなく、アマチュアよりも 当然優れた仕事をする、といった意味もある。ところで、三田氏は同誌3月号で、 ものすごいことを書いている。これがC言語フォーラムであまり話題にならなか ったのがどう考えても不思議だ。暇があるなら、C言語の経験のある方には評価 してもらいたいので、三田氏の主張を紹介しておきたい。まず、

    if (fp = fopen("filename", "r") == NULL) ... /* (1) */
という書き方…こんな書き方が実際あるかどうかはともかく…は三田氏いわく アマチュアで、プロになると、
    if ((FILE *) NULL == (fp = fopen("filename", "r"))) ... /* (2) */
のように書く、と言うのである。しかも、三田氏は、カッコの優先順位を知っ ていれば、これを
    if ((FILE *) NULL == fp = fopen("filename", "r")) ... /* (3) */
「というようにカッコ数はひとつ少なくてすむはず」と述べている。

さて、まさかそんな人はいないとは思うが、もしこれを読んで「なるほど、そ うか」と思う人がいては紹介した私が申し訳ないので、念のために書いておくと、 (3) は全く問題外であって、コンパイルすらできない。仮にこれを読んだ人が試 しに (3) のように書いてみて、おかしいな、コンパイルできない、と悩んだりし た場合、その貴重な時間を損失したことに対する責任の所在と補償は、誰がどの ように行うのだろうか。:-) というのは joke であるから本気になってはいけな い、が、実際にそう質問された人がいたそうである。

もちろん (3) のような間違いをする人は、相当の初心者でなければまずいない。 いわんやプロフェッショナルをや。C使いを自称するプロならたとえ読まなくて も持っていなければ格好が付かないという K&R 2nd. ed に至っては、「やさしい 入門」の章で、

>   while ((c = getchar()) != EOF)
>       putchar(c);
に対して、
>   条件式の中の代入文を囲むカッコは必要である。!= の優先順位は = より高
>   いから、カッコがないと、関係 != の吟味が代入の = より先に行なわれてし
>   まうのである。
        p.21、石田晴久訳、共立出版「プログラミング言語C第2版」より
と書いてある。

と考えると、C言語の入門書まで書いている三田氏のことである。こんな間違 いをするわけがない。だから、実は (3) もジョークに違いないと考えた方がいい。 「ふんふん、そうか」と流し読みする自称「Cがちょっとできる人間」をからか ったつもりなのだろう。たぶん。

さて、これは些細なことである。本題に戻ろう。私の主張はこうである、(1) を (2) のように書くのはかえってアマチュアである。というのは、(2) の記述は、 解釈の方向が通常のパターンとは逆なので、わかりにくくなるからである。また、 私ならば (1) のようにも書かない。

    fp = fopen("filename", "r");
    if (fp == NULL) ..
のように、2行に分けて書く。この書き方がプロの本質だと思う(*1)。なぜ2行で なければならないのか、と疑問を持つ人もいるだろう。これに対する答えは、簡 単に言葉にできる問題ではないので、実に不明瞭にならざるを得ない。強いて言 うならば、こちらの方が味がいい、といった感じの答えになる。でも、プロなら こう書いて欲しいものであると思う。私はこの味がわかるようになるまで、何年 もかかっているが、これは真理だという自信はある。

もちろん特別な条件がある場合は別である。2行に分けて書くことに対する最 も説得力のある批判は、このように分けると悪いコードを生成するコンパイラが ある、というものだ。この指摘は全く正しい。逆に、分けて書いた方がいいコー ドを生成するコンパイラは見たことがない。にもかかわらずこのように書く理由 は、仮に分けて書いた方が悪いコードになるリスクがあるとしても、ファイルを オープンするという処理は、ほとんどの場合、とるに足らない微々たるものなの で、他にメリットがあれば妥協できるという経験に基づいている。

特に、可読性が保守に必要な時間を左右することを忘れてはならない。もし可 読性のよいプログラムを書いたために保守の時間を節約できれば、その時間は別 の処理の最適化のために使うこともできるだろう。おそらく、ファイルをオープ ンする処理よりも、オープンしたファイルをどのように処理するかを考えた方が、 ソフトウェアの効率はずっとよくなる可能性が高い。

(2) の表現の解釈の方向が、逆だと書いたので、さらに議論したい。通常、C のプログラムを読む人は、上の行から下の行へ、一行の左から右に読む。逆の人 は異常だ(でも多分一人もいない)。これを前提にして、ファイルをオープンす る処理を呼び出して、それがエラーの値を戻してきたかどうかを処理するプログ ラムを書く場合、どうすれば最も自然かを考える。思考の流れはこうなるだろう。

まず、ファイルをオープンする処理を呼び出そう

その結果戻ってきた値は、エラーだろうか

私が先程「こう書く」と述べた記法が、まさにこのままの手順になっているの は偶然ではなく当然のことだ。つまり、ファイルをオープンするという処理の次 に、戻り値をエラーと比較するのなら、その順序に書いたのである。順序通りに 記述することは、理解を明瞭にするための最も基本的なテクニックである。

三田氏は、同じ記事の中で、見やすいプログラムについて議論されている (p.40 中段)。「見易さ」を測ることが難しく、個人の嗜好の問題になってしまう危 惧もわかる。だが、ヒューマン・インターフェイスを設計する時に心理学や人間 工学を応用するのと同じ様に、見やすいプログラムを書くことは可能だし、今述 べた思考の順序を乱さないような流れで記述する、というルールはその典型的な 例と言えるだろう。そして、見やすく書くことが、バグの少ないプログラムを作る ためには効果的である。

この記事では「デバッグのしやすいプログラムを書く」という視点が中心にな っている。あえて反論したい。プロならバグが極力でないようにプログラムを書 くべきである。格言にしておこう。(*2)

□□□ プロなら、バグのないプログラムを書け □□□
と書くと結局自分の首を絞めていることになってしまうが、本音と建前という ことで、ごまかすことにしたい。すなわち、これは心構えの話である。もちろん、 それでもバグが出ることを完全に阻止するのは難しいし、きっとバグはあるのだ。 避けられないバグというのは、よくある話だ。プロならレベルの高いものを目指 せという当然のことを言っているのだ。時間内に、仕様をそこそこ満たして仕上 げるのは当然で、その上品質にこだわってこそプロというものだ。(*3)

また、バグを防ぐような書き方をすれば、自然にデバッグのしやすいプログラ ムにもなるものである。

    *
処理の手順通りの記述が、いかに理解のしやすさと関係があるか、カップラー メンの作成手順を例にして考えてみるとよくわかる。次のマニュアルは、わざと 逆順に書いた。こんな手順説明の書いてあるラーメンは実在しない。
具を最後に入れてください。
お湯を入れて3分待ってください。
お湯を入れたら、すぐ蓋の上に具を乗せてあたためてください。
お湯はカップの内側の線まで注いでください。
カップの蓋は点線まで開けてください。
もしこのような手順を書いておくと、お湯を入れ3分待った後で、蓋の上に具 を置いておくべきだったことに気付くという失敗が後をたたないであろう。一行 に集約したらどうだろう。
お湯をカップの内側の線まで注ぐためにカップの蓋を点線まで開け、お湯を 入れて3分待ってから、あらかじめ蓋の上に乗せてあたためた具を入れてく ださい。
ま、わからなくはないのである。でも、一気に読んで頭の中でバッファリング しないと具を温める所を失敗するかもしれない。「3分待ってから、あらかじめ 蓋の上に乗せてあたためた具」という表現は、少しこじつけ過ぎかもしれないが、 まさに、
    if ((FILE *) NULL == (fp = fopen("filename", "r"))) ...
という書き方ではないだろうか。

ラーメンなら多少まずくなっても、食べられればよいかもしれないが、プロが プログラムを書く場合はそういうわけにはいかない。


補足

(*1) 予感通りというか、これについては議論になった。

(*2) 「極力バグが出ないように書け」というのは「細心の注意をもって集中して作業しろ」というのではない。例えばこのコラムに書いたような、バグが少なくなるための工夫を惜しむなという意味である。

(*3) しかし、バグは根絶できない、という意見が多い。これはFPROGの「一発完動」論争でもテーマになった。


    COMPUTING AT CHAOS RUINS -149-
    1991-04-18, NIFTY-Serve FPROG mes(3)-076
    FPROG SYSOP / SDI00344   フィンローダ
    (C) Phinloda 1991, 1996