プログラミングのボトムアップ
Original1993年1月
(この論文はOn Lispの序文からのものです。)
プログラミングスタイルの長年の原則として、プログラムの機能要素は大きすぎてはいけないということがあります。ある部分が理解しやすい範囲を超えてしまうと、大都市が逃亡者を隠すのと同じように、複雑さの塊となり、エラーを隠してしまいます。そのようなソフトウェアは読みづらく、テストしづらく、デバッグしづらいものになります。
この原則に従って、大きなプログラムは部分に分割されなければなりません。プログラムが大きいほど、より細かく分割する必要があります。プログラムをどのように分割するのでしょうか。従来の方法はトップダウン設計と呼ばれるものです。つまり、「プログラムの目的はこの7つのことを行うことだ」と言い、7つの主要なサブルーチンに分割します。最初のサブルーチンはさらに4つのことをする必要があるので、4つの自分のサブルーチンを持つ、というように続けていきます。このプロセスは、プログラム全体が適切な粒度になるまで続けられます。つまり、それぞれの部分が十分な機能を持ちつつ、単一の単位として理解できるようになるのです。
経験豊富なLispプログラマーは、プログラムを別の方法で分割します。トップダウン設計に加えて、ボトムアップ設計と呼べる原則に従います。つまり、問題に合わせて言語を変更するのです。Lispでは、単にプログラムを言語に向かって書くだけでなく、プログラムに向けて言語を構築することもします。プログラムを書いていると、「Lispにこのような演算子があればいいのに」と思うことがあります。そこで、その演算子を自分で書いてしまいます。その後、その新しい演算子を使うことで別のプログラムの設計が簡単になることに気づき、というように続きます。言語とプログラムが一緒に進化していくのです。2つの敵対する国家の国境のように、言語とプログラムの境界線は引かれ、書き換えられ、最終的には問題の自然な境界線である山や川に沿って落ち着きます。最終的にはプログラムが、まるでその言語のために設計されたかのように見えるようになります。言語とプログラムがうまくフィットすれば、明確で小さく、効率的なコードが得られます。
ボトムアップ設計は、単に同じプログラムを別の順序で書くということではないことを強調しておく必要があります。ボトムアップで作業すると、通常、まったく異なるプログラムが得られます。単一の大規模なプログラムではなく、より抽象的な演算子を持つ大きな言語と、それを使って書かれた小さなプログラムが得られます。リンテルではなく、アーチが得られるのです。
一般的なコードでは、単なる事務処理の部分を抽象化すると、残りの部分はかなり短くなります。言語を高い抽象度まで構築すれば、トップダウンでそこまで到達する距離が短くなります。これにはいくつかの利点があります。
ボトムアップ設計では、言語にもっと多くの仕事をさせることで、プログラムがより小さく機敏になります。短いプログラムは、多くの部品に分割する必要がなく、部品が少ないほどプログラムの読解や修正が容易になります。部品が少ないということは、部品間の接続も少なくなり、そこでのエラーの可能性も低くなります。産業デザイナーが機械の可動部品の数を減らすように、経験豊富なLispプログラマーはボトムアップ設計を使ってプログラムのサイズと複雑さを減らします。
ボトムアップ設計はコードの再利用を促進します。最初のプログラムのためにいくつかのユーティリティを書いた場合、それらは後続のプログラムでも役立つことが多いでしょう。一度大きな基盤のユーティリティを持つようになれば、新しいプログラムを書くのに必要な労力は、ゼロからLispを使って書く場合に比べて大幅に減ります。
ボトムアップ設計はプログラムを読みやすくします。
この種の抽象化の例では、読者に汎用的な演算子を理解してもらう必要があります。機能的な抽象化の例では、読者に特殊な目的のサブルーチンを理解してもらう必要があります。[1]
常にコードのパターンを探し続けるようになるため、ボトムアップで作業することで、プログラムの設計に関する自分の考えが明確になります。プログラムの離れた2つの部分が形式的に似ていることに気づけば、プログラムをより単純な方法で再設計することができるかもしれません。
ボトムアップ設計は、Lisp以外の言語でも一定の程度まで可能です。ライブラリ関数を見かけるたびに、ボトムアップ設計が行われています。しかし、Lispではこの手法をずっと広範に使うことができ、言語の拡張がLispスタイルの中で比較的大きな役割を果たします。そのため、Lispは単なる別の言語ではなく、プログラミングの全く別の方法なのです。
この開発スタイルは、小規模なグループで書けるプログラムに適していると言えます。しかし同時に、小規模なグループでできることの範囲を広げることもできます。The Mythical Man-Monthで、フレデリック・ブルックスは、プログラマーグループの規模が大きくなるほど、個々のプログラマーの生産性が下がると提案しました。Lispプログラミングの経験から、より前向きな言い方をすれば、グループの規模が小さくなるほど、個々のプログラマーの生産性が上がるということです。小さなグループは、単に小さいというだけで相対的に有利になります。小さなグループがLispの手法を活用すれば、圧倒的に有利になる可能性があります。
新着情報: On Lispを無料でダウンロード
[1] 「しかし、新しいユーティリティをすべて理解しなければ、プログラムを読むことはできません。」 なぜそのような主張は通常間違っているかを理解するには、4.8節を参照してください。