デザインの「悪い方がよい」原則

The Rise of "Worse is Better"

rpg@lucid.com
日本語訳:
daiti-m@is.aist-nara.ac.jp

私や Common LispCLOS のデザイナーのほとんどは、MIT/Stanford 方式の設計に親しんでいる。 この方式の核心は、「正しい」やり方をせよ、という ことにつきる。デザイナーにとっては、以下の点をすべて正しく満たすことが 重要である。

ほとんどの人がこの条件に同意されることと思う。このデザイン哲学を、以下 「MITアプローチ」と呼ぶことにしたい。Common Lisp (とCLOS) や Scheme はこのデザイン哲学を体現している。

"悪い方がよい"原則はこれと少しだけ異なる:

初期の Unix と C 言語はこのデザイン流派の例である。以下、このデザイン戦略を 「New Jersey アプローチ」と呼びたい。私はわざと「悪い方がよい」原則を 悪く書き、これが明らかに悪い哲学であり、New Jersey アプローチが悪い アプローチであることを信じるようにした。

しかし、私は「悪い方がよい」原則のほうが単純な場合でも 「正しい」ことより生き残る哲学であり、ソフトウェア開発については New Jersey アプローチの方が MIT アプローチよりもよいアプローチだと信じている。

まず、MIT/New Jerseyアプローチの区別が妥当なものであり、それぞれの側が 自分の方が優れていると信じていることを示すことから始めよう。

あるとき、MIT 出身と Berkeley 出身(ただし、Unix開発に携わっていた)の二人の有名人が OSの問題を話し合うために集まった。 MITの彼は ITS (MIT 人工知能研究所のOS) に精通しており、 Unix のソースコードを読んでいた。彼は Unix がどのように「PC loser-ing」問題を 解決できるかに興味を持った。「PC loser-ing」問題は ユーザプログラムがI/Oバッファのような状態を内部に持つ、時間のかかる操作を システムに要求したときに起こる。もし実行中の操作が中止されると、 ユーザプログラムの状態は保存される必要がある。しかしシステムの提供する そうしたルーチンは通常1つの命令であるため、ユーザプログラムの 現在の命令の実行位置を示すプログラムカウンタ (PC) はプロセスが中止を 受けたことを把握することができない。そこでシステムはその命令が実行される 前に戻るか、そのまま命令を実行したことにして先に進むかしなければならない。 「正しい」やり方はもちろん、命令の実行前まで戻ってプログラムカウンタを もとの位置に戻し、ユーザプログラムがその後システムルーチンの再実行などが できるようにすることである。
プログラムカウンタがユーザモード (MITではユーザ(user)のことを皮肉をこめて敗者 (loser)と呼ぶ) に強制的に戻されることから、このことを 「PC loser-ing」と呼ぶ。

MITの彼は読んでいた Unix のソースの中にこの問題に対処するコードを見つけられ なかったので、New Jersey 側の彼にどうやってこの問題に対処しているのか 尋ねた。New Jersey の彼は、Unix を使っている人はこの問題に気付いているが、 解決はシステムルーチンを中止を受けてもつねに終了させ、かわりに そのシステムルーチンが実行されなかったことを示すエラーを返すように することだと答えた。したがって、正しいユーザのプログラムは エラーがあるかをチェックしてそのシステムルーチンを再実行するかどうか 自分で決めるものだと彼は言った。
MITの彼はこの解決は気に入らなかったが、それはもちろんこの解決が 「正しい」やり方ではないからだった。

New Jerseyの彼は、このUnixの解決は正しい、なぜならUnixの設計哲学は 単純さにあるのであって、「正しい」ことをするのは複雑過ぎるからだと言った。 それだけでなく、プログラマがここにこの余分なテストとループのコードを 入れることは簡単なことだと。
MITの彼はそれに対して、実装は簡単だが使用法が複雑すぎることを指摘した。 New Jerseyの彼は、ここではUnixの設計哲学に従って適切なトレードオフが 行われていると答えた。すなわち、実装の簡単さの方が使用法の簡単さより 重要なのだと。

MITの彼はそれを聞いて「屈強な男がやわらかい鶏料理を作ることも 時にはあるものなのに」と嘆息したが、New Jerseyの男には理解できない ようだった[筆者もよくわからない]。

ここで私は、「悪い方がよい」原則の方がよりよい原則であると主張したい。 CはUnixを書くためにデザインされたものであり、New Jerseyアプローチに従って デザインされている。従ってCはそれなりに動くコンパイラが書きやすい言語だが、 同時にそれはプログラマがコンパイラに読みやすいようにコードを書くことを 要求する。Cのことを素敵なアセンブラだと呼んだ人もいるほどである。 初期のUnixとCコンパイラはどちらも単純な構造を持っており、ハード的資源の 少ないマシンにも容易に移植することができ、OSとプログラミング言語に対して 望む働きの50%―80%程度を満たすことができた。

ある時点で存在するコンピュータの半分は標準的なコンピュータより 遅いかメモリが少ないが、UnixとCはそういう機械でも問題なく動く。 「悪い方がよい」という原則は実装の簡単さに何よりの重きを置くもので あるから、それはUnixとCがそういう機械にも容易に移植できることを保証する わけである。従って、望まれることの50%の機能を持つ Unix と C で 充分なのであれば、それらは至るところに広まることになる。 そして実際そうなってきた。

Unix と C は究極のコンピュータウイルスである。

「悪い方がよい」アプローチのさらなる利点は、プログラマが安全性や便利さを 犠牲にし、かわりに、速く、システム資源をあまり消費しないプログラムを書くように 強いられることである。New Jersey アプローチを使って書かれたプログラムは 小さいコンピュータでも大きなコンピュータでも同様に動き、プログラムは 容易に移植が可能なものとなる─なぜならそれはウイルスの上に書かれて いるのだから!。

ただし、最初の「ウイルス」が基本的にはよいものでなければならないことは 覚えておかなければならない。もしそうであれば、移植できるかぎり そのウイルスが広まっていくことは保証される。 一度ウイルスが広まってしまえば、それをよりよいものにしようという動きが 生まれ、そしてその機能は望まれる90%まで達していくだろう。 しかしユーザは正しいものより悪いものを使い続けるようにすでに運命付けられて しまっているのだ。従って,「悪い方がよい」原則によるソフトウェアは最初に 多くの人に受け入れられ、次にユーザがそれに多くを望まない状況に追い込み、 最後に「正しい」プログラムとほとんど同じ機能を持つ所まで改善が続けられる ことになるのである。
具体例を挙げるなら、1987年の時点ではまだLispコンパイラはCコンパイラと 同等の性能を持っていたが,その後では C コンパイラを改善しようとする人々の方が Lispコンパイラを改善しようとする人々よりずっと多かったのだ。

1995年に実現するだろう幸せは我々がよいOSとよいプログラミング言語を持つ ことであり、不幸はそれが Unix と C++ となるだろうことである。

「悪い方がよい」原則にはまだ最後によい点がある。New Jersey アプローチによる 言語とシステムは単一の複雑なソフトウェアを構築するには力不足であるため、 大きなシステムはそれを構成要素に分けて再利用を図る設計にならざるを 得ないのである。そこで、要素を統合してシステムを作る伝統が作られることになる。

では、「正しい」アプローチはどうしてしまったのだろうか? そのたどるシナリオは2つある:『複雑巨大システム』に至るシナリオと 『ダイヤモンドのような貴石』となるシナリオとである。

『複雑巨大システム』となるシナリオはこうなる:

まず最初に、正しいものごとはデザインされなければならない。それから、 その実装もデザインされなければならない。ついに、それは実装される。 それは正しいものだから、もちろん望まれる機能のほとんど100%を果たす。 実装の単純さは決して考慮に入れられることはない、なぜなら正しいものを 実装するには長い時間が必要だからである。それは大きく、複雑なものになる。 それをうまく使うには,複雑な道具が必要になる。実装の最後の20%が努力の 80%を費やし、リリースするには長い時間が必要となる。そしてそれは もっとも進んだハードの上だけで満足に動作する。

『ダイヤモンドの輝きを放つ貴石』となるシナリオはこうなる:

「正しい」ものをデザインするには無限の時間がかかるが、その途中では それはいつもきわめて小さなものになる。 それを速く走るように実装するのは不可能か、ほとんどの実装者の能力を超えている。

この2つのシナリオはそれぞれ Common Lisp と Scheme のたどった道である。
また、最初のシナリオは古典的な人工知能プログラムのたどった道でもある。

「正しい」ソフトウェアはよく単一のモジュールからなるが、これは 「正しい」ことがよく単一の視点で設計されるというだけのことである。 これは偶然にすぎない。

このことから学ぶべき教訓は、最初に「正しい」方法をとることはしばしば 望ましくないということである。とりあえず「正しい」ことの半分はできるものを 作り、ウイルスのように広める方がよい。いったん人々がそれに騙されれば、 「正しい」ことの90%までできるように改善が行われるだろう。

間違った教訓はこの寓話を文字通りにとって、人工知能プログラムにとって C が正しい言語だと早合点することである。50%の機能は正しいものでなければ ならなかったが、この場合はそうではない。 しかし、Lisp コミュニティは Lisp デザインにおけるその地位を 考え直さねばならないということはいえよう。このことについてはもう少し後で 述べようと思う。


daiti-m@is.aist-nara.ac.jp
$Id: worse-is-better-ja.html,v 0.4 2000-01-08 19:06:04+09 daiti-m Exp $