表紙へ  次の記事


プログラム言語と抽象化

中田 育男


 プログラム言語の歴史は抽象化の歴史であるともいわれる.コンピュータというものが出現してから現在に至るまでのプログラム言語の歴史を,主として抽象化の観点から考えてみたい.
 最初のプログラミングは機械語の命令の列を8進法や10進法の数字を並べて書くものであった.これがプログラム言語の第1世代と呼ばれる.数字ではなくアルファベット文字を使って命令語や番地を表現できるようにしたのがアセンブリ言語であり,第2世代言語と呼ばれる.アセンブリ言語でのプログラムでは番地は具体的な数字で表される番地ではなく,文字を使ったより抽象的な表現になる.アセンブリ言語からFortranのような高級言語(機械語のレベルより高級な言語という意味)へは大きな進歩であった.それらは第3世代言語と呼ばれる.1960年ころ,最初にFortranという言語(とそのコンパイラ)を開発した人は,この言語でプログラムを書けばデバッグは必要なくなるはずだと考えたほどである.高級言語を使うことによってプログラムは飛躍的に書きやすくなったが,多くの巨大なソフトウェア開発が行われるようになり,そのデバッグや保守の困難さからくるソフトウェアの危機が認識されてソフトウェア工学の必要が叫ばれだしたのは1968年ころからである.
 ソフトウェア工学における最も重要な考え方は「分割し統治せよ(divide and conquer)」である.大きな複雑なソフトウエアを間違い少なく作っていくためには,それをいくつかの構成要素に分割して,それらを組み合わせて全体を構成するしかいい方法がない.大きなソフトウェアを人間が理解するためには,人間が理解できるような大きさに分割するしかないということである.分割の手がかりは抽象化である.分割された単位は,モジュールと呼ばれた.
 ソフトウェア工学における最初の重要な提唱は構造化プログラミング(structured programming)であった.その当時はプログラムはまだ手続き主体で考えられていた.モジュールは通常はサブルーチンであり,プログラムはサブルーチンを組み合わせて作られており,実行時のプログラムの制御の流れをまず理解することが重要であった.その場合に理解の妨げになるのはgoto文の存在であるということで,goto文よりも抽象化された制御文(1f-then-else文やwhile文など)だけで表現すべきであるとされた. Pascalはそのような機能を備えた言語として使われた.Fortran 66にはそれが不足していたのでFortran77となった.最近のJava言語にはgoto文はない.
 分割統治を効果的にするためには,分割されたモジュールの機能が明確であり,各モジュールの独立性が高くなければならない.手続き主体で考えれば, 1つのモジュールが1つの関数サブルーチンであるのが良い.また,独立性を高めるためには,パラメータは参照渡し(番地渡し)でなく,値渡しが良い.
 もう一つ大事な提唱としては,情報隠蔽(Information hiding)がある.これは,手続きの実現のために必要なものはその手続きを使う人から隠せということで,仕様と実現の間の壁で分割を効果的にするものである.仕様は実現を抽象化したものであり,これは手続き単位の抽象化と言える.これらは1970年ころの話である.
 プログラムを理解する,あるいは設計する時は制御の流れだけでなく,データの流れを考えることも重要であるが,それまでは,プログラム構造については手続きを中心に考えられてきた(ジャクソン法はデータ構造からプログラム構造を導きだすものであったが).その後,プログラム構造についてもデータを中心に考えるべきであるといわれるようになった.まず,データとそのデータに対する基本的な操作をする手続き群とを一まとめにして考えることで,今までの手続きよりももっと大きな単位で抽象化をすることになる.これは抽象データ型(abstract datatype)と呼ばれる.このための機能を備えた言語には1980年前後のCIu,Ada,Modula-2,1990年のFortran 90などがある.
 抽象データ型ではデータが中心であったが,まだプログラムは手続きが主体であり,データは手続きの対象であった.1980年のSmalltalk 80以来のオブジェクト指向言語(object‐oriented language)では,発想の転換をして,データが主体となり,手続きはデータ(オブジェクト)が持っているものとなった.抽象データ型に相当するものはクラス(class)と呼ばれ,抽象化の単位は抽象データ型よりさらに大きくなって,一群のクラス(抽象データ型)を階層構造で表現することが出来るようになった.階層構造の上位がより抽象化されたものであり,下位がそれを特殊化したものである.オブジェクト指向言語としてはCをベースにしたC++(1986(Release l.1),1990(2.1)),インターネットとの関連もあって急速に広まったJava(1995)などがある.
 抽象化のレベルが上がったことによって,それを使ってうまい抽象化を行えば,プログラムは分かりやすくなり,その修正や機能拡張も比較的簡単になる.しかし,うまい抽象化を行うのは必ずしも簡単ではない.プログラムは一般には複数の階層構造を含んだ形で表現されることになるが,それらの間で,機能的にどのような関連を付けたいときにどのような構造にすればよいかは簡単ではなく,試行錯誤を繰り返していい形を見つけることになる.いい形が見つかったら,それを出来るだけ一般的な形で表現したものがデザイン・パターンと呼ばれるものである.Javaの基本ライブラリにはデザイン・パターンが多く使われている.それらのデザイン・パターンを理解していればライブラリを理解するのは容易になる.
 オブジェクト指向言語をうまく使うことによって,多くのプログラムが以前よりもすっきりと表現できるようになるが,すべてがそうなるわけではない.従来のような手続き指向のプログラムの方が素直な表現になる場合もある.Visitorと呼ばれるデザイン・パターンは,オブジェクト指向のプログラムの中で,ある種のデータ構造に関する手続き指向のプログラムを表現するためのものということも出来る.
 プログラムを設計するときはいろんな側面を考える必要があるから,ある側面だけを考えて抽象化してもいいプログラムになるとはかぎらない.たとえば,基本的な機能面だけを考えて,データの論理的な流れを抽象化してプログラム構造を設計してから,性能を考慮してデータの流れのショートカットを入れようとすると,もとのプログラムを大きく変更する必要が生ずることがある.この場合,性能という側面(アスペクト)は別に記述するというアスペクト指向プログラミング(aspect‐oriented program‐ming)も提案されている(それからプログラムを生成するのはコンパイラの仕事であろう).
 最近は,Java Beansのように,出来上がっているコンポーネントを組み合わせて所要のプログラムを作っていくという考え方もある.そのためには各コンポーネントの仕様が一定のルールにしたがって作られている必要がある.
 これらのプログラム設計の新しい考え方は,うまく抽象化されれば,今後のプログラム言語に取り入れられて行くと思われる.しかし,いずれにしても,大きな複雑なソフトウェアを人間はどう把握すればよいのかという苦闘はいつまでたっても終わりそうにない.


Programming Language and Abstraction, by Ikuo NAKATA
本学教授