ボトムアッププログラミング
Original1993年1月
(このエッセイはOn Lispの序文からの抜粋です。)
プログラムの機能要素は大きすぎないようにするというのが、プログラミング スタイルの長年の原則です。プログラムの一部のコンポーネントが、容易に理解できる段階を超えて大きくなると、大都市が逃亡者を隠すのと同じくらい簡単にエラーを隠す複雑な塊になります。そのようなソフトウェアは、読みにくく、テストが難しく、デバッグが難しくなります。
この原則に従って、大きなプログラムはいくつかの部分に分割する必要があり、プログラムが大きいほど、分割する必要のある部分も多くなります。プログラムはどのように分割するのでしょうか。従来のアプローチは*トップダウン設計と呼ばれています。*つまり、「プログラムの目的は、これら 7 つのことを実行することなので、7 つの主要なサブルーチンに分割します。最初のサブルーチンは、これら 4 つのことを実行する必要があるので、そのサブルーチンも 4 つのサブルーチンを持つことになります」というように分割していきます。このプロセスは、プログラム全体が適切な粒度レベル (各部分が重要なことを実行するのに十分な大きさでありながら、単一のユニットとして理解できるほど小さい) になるまで続きます。
経験豊富な Lisp プログラマーは、プログラムを異なる方法で分割します。トップダウン設計だけでなく、ボトムアップ設計とも言える原則、つまり問題に合わせて言語を変更する原則に従います。Lisp では、プログラムを言語に合わせて記述するだけでなく、プログラムに合わせて言語を構築します。プログラムを作成しているときに、「Lisp にこのような演算子があればいいのに」と思うかもしれません。それで、実際に記述します。その後、新しい演算子を使用するとプログラムの別の部分の設計が簡素化されることに気付くなどします。言語とプログラムは一緒に進化します。2 つの戦争状態の間の境界線のように、言語とプログラムの境界は何度も描かれ、最終的には問題の自然な境界である山や川に沿って落ち着きます。最終的に、プログラムは言語がプログラム用に設計されたかのように見えます。そして、言語とプログラムが互いにうまく適合すると、明確で小さく効率的なコードになります。
ボトムアップ設計は、単に同じプログラムを異なる順序で記述するだけではないということを強調しておく価値があります。ボトムアップで作業すると、通常は異なるプログラムになります。単一のモノリシック プログラムの代わりに、より抽象的な演算子を持つより大きな言語と、その言語で記述されたより小さなプログラムが得られます。リンテルの代わりに、アーチが得られます。
一般的なコードでは、単に記録する部分を抽象化すると、残る部分はずっと短くなります。言語を上位に構築するほど、上位から下位までの移動距離が短くなります。これにより、次のようないくつかの利点がもたらされます。
ボトムアップ設計では、言語に多くの作業を行わせることで、プログラムがより小さく、より機敏になります。プログラムが短いと、それほど多くのコンポーネントに分割する必要がなくなり、コンポーネントが少ないほど、プログラムの読み取りや変更が容易になります。コンポーネントが少ないということは、コンポーネント間の接続も少なくなるため、エラーが発生する可能性も低くなります。工業デザイナーが機械の可動部品の数を減らそうと努力するのと同様に、経験豊富な Lisp プログラマーは、ボトムアップ設計を使用してプログラムのサイズと複雑さを軽減します。
ボトムアップ設計はコードの再利用を促進します。2 つ以上のプログラムを作成する場合、最初のプログラム用に作成したユーティリティの多くは、後続のプログラムでも役立ちます。ユーティリティの大規模な基盤を取得したら、新しいプログラムを作成するのに必要な労力は、生の Lisp から始める場合のほんの一部で済みます。
ボトムアップ設計により、プログラムが読みやすくなります。
このタイプの抽象化のインスタンスは、読者に汎用演算子の理解を求めます。一方、機能的抽象化のインスタンスは、読者に特殊目的のサブルーチンの理解を求めます。[1]
ボトムアップで作業すると、常にコード内のパターンに注意を払うことになるため、プログラムの設計に関するアイデアを明確にするのに役立ちます。プログラムの 2 つの離れたコンポーネントが形式的に類似している場合、類似性に気づき、おそらくプログラムをより簡単な方法で再設計することになるでしょう。
Lisp 以外の言語でも、ある程度はボトムアップ設計が可能です。ライブラリ関数を見ると、ボトムアップ設計が行われています。ただし、Lisp ではこの分野ではるかに幅広い権限が与えられており、言語の拡張は Lisp スタイルにおいて比例して大きな役割を果たします。そのため、Lisp は単なる異なる言語ではなく、まったく異なるプログラミング方法なのです。
この開発スタイルは、少人数のグループで作成できるプログラムに適しているのは事実です。しかし、同時に、少人数のグループで実行できることの限界を広げます。 *『人月の神話』*で、フレデリック・ブルックスは、プログラマーのグループの生産性はその規模に比例しては伸びないと主張しました。グループの規模が大きくなると、個々のプログラマーの生産性は低下します。Lisp プログラミングの経験から、この法則をもっと明るい言い方で表現することができます。つまり、グループの規模が小さくなると、個々のプログラマーの生産性は上昇するということです。相対的に言えば、少人数のグループが勝つのは、単に規模が小さいからです。少人数のグループが Lisp で可能になるテクニックも活用すれば、完全に勝つことができます。
新機能: On Lisp を無料でダウンロードしてください。
[1] 「しかし、新しいユーティリティをすべて理解せずにプログラムを読む人はいないでしょう。」このような記述がなぜ間違いなのかについては、セクション4.8を参照してください。