「ねぇ先輩。改めて思ったんですが,『オブジェクト』ってそんなすごいことなんですか」
「自分だって使ってるじゃない。この間なんて,『クラスがないなんて,考えもつかない』とか言ってたのはどこの誰だよ」
「でも,そのどこがすごいのかわかんないです」
「ふーむ。じゃあ簡単に。大きくは二つあるかな。分割統治と,モデルの作りやすさ」
「分割統治?」
「影響の範囲はとにかく絞り込め,さ」

 1981年に米BYTE誌がSmalltalk-80を紹介したのが,おそらくオブジェクト指向が研究室を飛び出した最初だろう注1)。それ以来,20年以上の月日が流れた。ようやくここ数年,「オブジェクト指向」という概念が当たり前に使われる存在となってきた。しかしここまで普及するにはかなりの時間がかかった。

 当初オブジェクト指向の“メリット”として強調されていたのは,再利用に伴う生産性の高さである。オブジェクト指向の三つの礎石は,(1)カプセル化(encapsulation),(2)継承(inheritance),(3)多義性(polymorphism)である注2)。これらによって「モジュール化が進み再利用性が向上する」というのが当時の宣伝文句だった。つまり「再利用性」がオブジェクト指向の第1のメリットとして挙げられていた注3)。例えば継承によって,「元のクラス定義を再利用して差分を追加する」といった具合だ。

 しかし実際には,再利用は簡単にできることではなかった。再利用性が強調されすぎたあまり,オブジェクト指向プログラミングは導入しても大したメリットがないという評価さえ受けた。事実,プログラミング・レベルでクラスを単位として再利用するのは難しい。例えば一つのクラスを再利用しようとしたときに,上位クラスがどう存在し,またほかのクラスのオブジェクトをいかに利用しているか把握していないと再利用できないからだ。さらに設計段階でも,再利用性はそれを相当考慮しなければうまく実現できない。むしろ「再利用性はボーナスと考えるべき」(米Rational社のJames Rumbaugh氏)ものだったのである注4)

 先に挙げた三つの礎石自体は間違ってない。ただそこから導き出されるべきメリットは再利用ではないのだ。オブジェクト指向の「本質」は,あくまでも独立したモジュールを作り出すことなのである。カプセル化と情報隠蔽による他からの影響の排除。プログラミングのレベルで考えたときには,オブジェクト指向最大のメリットはここにある。

分割統治がプログラミングの基本

リスト1●構造化制御構文の例
ロジックをブロックに分割できる。ブロック単位で手続きを考えられるようになる。

 言い替えればこれは,モジュールのように独立した要素に分割できることに価値があるということだ。オブジェクト指向プログラミングも構造化プログラミングも,いかにプログラムを「分割して統治するか」を考えたパラダイムなのである。

 構造化パラダイムにおける分割統治のための仕組みは二つある。構造を表すための制御構文と,ローカル変数を持つサブルーチンである注5)。構造を表した制御構文とは,無条件gotoを使わずに表現した繰り返し構造や条件分岐のことである(リスト1[拡大表示] )。このようにすることで,ロジックの流れをブロックに分割し,ロジックの構造を明確にしている。また見かけをよくするため,インデントによってブロックの存在を明示的に表現している。gotoを使わなければ,このブロック内部で突然流れが変わることがないので,ブロックの独立性が高まる。副次的なメリットとしては,ソースコードを構造単位で取り出して,再利用し得ることが挙げられる。

 無条件gotoは,ブロック内部に不意に飛び込んだり,突然ブロックから脱出したりしてしまう。ただ深いブロックからの脱出など,gotoは適切に使えばプログラムの見通しや保守性を高めることにも寄与する。いかにgotoを使わず,しかも見通しよくするかバランスを取る必要があるのだ。

ローカル変数がモジュールを生んだ

 ただこのように「流れ」を構造化しただけでは,モジュール化は不十分である。そのための仕組みがローカル変数を持つサブルーチンである。サブルーチンの概念は最初のFORTRANにもあったが,組み込み済みの関数を呼び出すことしかできなかった。またパソコンにOS代わりに組み込まれたMicrosoft Basicは,ローカル変数が存在しないサブルーチンしか定義できなかった。

 ローカル変数の登場は,プログラミングを大きく変えた。モジュールとしての独立性が飛躍的に高まるからだ(図1[拡大表示])。ALGOL 60や1963年に登場したFORTRAN IIで導入された。ある意味,FORTRANの普及を決定づけた仕組みと言える。ライブラリを実現する仕組みだからだ。結果としてさまざまな数値計算ライブラリが誕生し,FORTRANの普及を促進した。

 制御構造はロジックの流れを明確にできるが,ロジック全体をモジュール化できるわけではない。ロジック全体を一つのルーチンにまとめて独立させたものがサブルーチンである。しかしローカル変数がなければ,本来そのルーチンで使うべき変数が勝手に書き換えられてしまったり,サブルーチンが妙な副作用を起こして予想外の変数を書き換えるなどの問題が発生し得る。

 逆に言えば,グローバル変数というのは意外とやっかいな存在である。グローバル変数はうまく使えばとても便利な存在だ。複数のルーチンで横断的に共通の情報を持ちたいことは,決して少なくないからだ。しかし安易に使ってしまうと,モジュールの独立性を損なってしまう(図2[拡大表示])。

図1●ローカル変数が手続きを独立させる
変数が他のところで書き換えられることがなく,その手続き内だけを関知すればよい。したがって複数の異なる場面でこの手続きが呼び出されても,適切に反応を返すことができる。
 
図2●グローバル変数の功罪
複数の異なる手続きでデータを共有したい場合,便利なのがグローバル変数である。しかしグローバル変数を使うと手続きの独立性が損なわれる。

(北郷 達郎、八木 玲子)