コンピューター・プログラミング手法の転換 : 手
続き指向アプローチからオブジェクト指向アプロー
チへ
著者名(日)
関根 敏博
雑誌名
井上円了センター年報
号
4
ページ
190-177
発行年
1995-07-20
URL
http://id.nii.ac.jp/1060/00002621/
コンピュータ・フ廿グラミング手法の転換
手続き指向アプローチからオブジ1・.クト指向アプローチへ関根敏博・屹励働
(1)手続き指向アブti−一チの欠点 プログラムはデータ構造とアルゴリズムから構成されるということが しばしば言われるが、従来の手続き指向型のプログラム言語は実際には 極端にアルゴリズムを重視する形で構成されたきた。言い換えればデー タはあるアルゴリズムを達成するための補助手段として扱わてきたにす ぎない。ましてデータとそれに関わるアルゴリズムとの有機的関連性に 対しては改まって検討することもなくプログラムを組んだ。例えば初期 のFORTRANではデータ型と同種グループデータ(配列)が意識される だけでデータ構造に対する配慮はほとんどなされることがなかった。こ れに対してCOBOLではデータ構造に対しては遙かに慎重な用意がなさ れていたが、この場合のデータ構造の取り扱いは大変複雑である上に、 データと手続き(アルゴリズム)とは全く別のディビジョンで分離して取り 扱われることになっていた。PASCALやC言語になってようやく構造体 という形で異種データが構造的に取り扱うことができるようになったが、 ここでもデータとアルゴリズムの関係は有機的に結合されていなかった。 このようなアルゴリズムに重点を置いた手続き指向型言語において は、開発過程を合理化するための技法として、設計段階でのモジュール 化手法、トップ・ダウン設計、並びに実装段階での構造化プログラミン グなどが提案されてきた。 コンピュータが出現した初期の頃のプログラム開発過程での目標は、 専ら乏しいハードウェア資源を効率よく動かすことであったが、コンビ コンビ=一タ・プログラミング手法の転換 83(190)ユータが普及するにつれてむしろ段々過大になるソフトウェアの開発と 保守を如何にして効率よく行うかということが大きな課題になっていっ た。いわゆるソフトウェア危機の問題である。これに対処する手段の一 っがモジュール化手法の導入であった。例えばE.Yourdonは「モジュー ルが小さくなればなるほどそれは内部的に単純になる。それと同時にモ ジュールの数は増え、それに応じてモジュール間のエラーの問題は増大 するものと予想される。我々がおかすエラーの総数(=プログラムの開 発費用)はこの2つの相反する影響の和である。」として、適正な規模の モジュールに分割することが開発効率を高めるために重要であることを 指摘した。そしてこのモジュールの開発面での効率を高めるためには、 「モジュール内部の結合度」(module cohesion)を強化することと「モ ジュール間の結合度」(module coupling)をなるべく小さくすることが 重要であることが提案された。そしてそのモジュール結合度を高めるた めにはモジュールを機能単位にグループ化すること、またモジュール結 合度を小さくするためにはモジュールをなるべく少数の引数を持つ関数 として構成することが望ましいと考えられた。 更にトップダウン設計では、モジュールの階層構造を作成し上層から 下層に向かう形でプログラム開発を行うことが提案された。これにより 目的指向的な開発体制が取られ、また開発の後期段階での設計のやり直 しなどを防げるものと考えられた。 またプログラムの実装段階では、プログラムの作成や保守を簡易化す るために「読みやすいプログラム」をつくることが重要であり、そのた めにgoto文をできるかぎり使用しないように「構造化」することが指摘 された。しかしこれらの種々の「効果的プログラム技法」もその後のプ ログラム開発においてかならずしも大きな成果を収めることができなかった。 第1にこのような手続き(機能)を中心にした考え方は必ずしも世の 中の現象やモノの実体を率直に反映していないためにプログラムの構成
理論として不自然であることである。このことは具体的な例を挙げて後 述する。 第2にデータと手続きとが分離しているために両者の関連性が不明確 であった。特に同じデータを操作する複数の手続き同士がお互いに関連 し合っていることを示す手段がなかった。 第3にトップダウン設計手法は新しいプロジェクトに取り組む毎に上 層モジュールから設計し直すことを前提としており、目的指向的ではあ るがその反面下層モジュールの再利用などが考慮されていない。むしろ 下層モジュールを積み上げて行くボトムアップ設計の方がソフト資源の 再利用の面で現実的なアプローチであると思われる。 以上のことを今「レストラン」のサービスを例にとって説明しよう。 この仮想レストランのサービスの授受を行う主体として、「客」・「料理 人」・「ウェイトレス」・「会計係」という4者が存在するものとする。 このレストランで行われる営みを従来の手続き指向型プログラムのよ うに、機能(手続き)中心の考え方で表現すると次のようになる。(ここ で単線の下線部分が機能を行う主体であり、二重線の下線は機能を行う 上で必要なデータである。)
①②③④⑤⑥
客がメニューから希望献立を選択する。 ウェイトレスが注文を聞き伝票に記入する。 ウェイトレスが注文を料理人に伝える。 料理人がレシピーを基に料理をつくる。 ウェイトレスが料理を客に運ぶ。 客が料理を食べる。 ⑦査が伝票を会計係まで運ぶ。⑧⑨⑩
会計係が定価表を基に料金を計算する。 客が料金を払う。 会計係がレジへ入力する。 [図1]レストランの処理の流れ コンビ・Lタ’プ゜v−)ミング経の転換85(188)この例ですぐ気が付くことは、まず第一にこのような手続き指向アプ ローチでは機能の生起の順序だけを考慮して記述するために、それぞれ の機能を行う主体について目を付けるとまったくまとまりのない感じが することである。これは自然界や社会の実体が人やモノを単位にして構 成されているにも関わらず、従来のプログラムがこれを反映せずに機能 だけを中心にして記述していたからに他ならない。またこのようなプロ グラム記述では実体毎のまとまりがないために、もしプログラムの改訂 を行うときにはプログラムの一部を重点的に改訂することができず、プ ログラム全体に目を通さなければならない。例えば今メニュを改訂する とすれば、それは伝票にも料金表にも影響をもたらすために結局プログ ラム全体を訂正しなければならないことになる。 (2)オブジェクト指向アブb一チの考え方 これに対して、オブジェクト指向アプローチでは処理の主体またはモ ノを単位としてプログラムを構成する。この単位をオブジェクトといい、 上記のレストランの例では客・ウェイトレス・料理人・会計係がそれぞ れオブジェクトを構成することになる。このオブジェクトは通常その内 部にデータと機能(手続き)をもつ。このデータと機能は「属性」と「メ ソッド」という呼び方をすることもある。 実際には例えば客・オブジェクトは多数存在しそれぞれ違った属性を 備えている可能性があるが、ここで多数のオブジェクトの必要な属性・ 機能のみを取り出して抽象化したテンプレート(雛形)を「クラス」と 呼んでいる。すなわちプログラミングではオブジェクトの抽象的な型を 表現するものとしてまず「クラス」が存在し、実行時にクラスを実体化 して作られるのがオブジェクトである。言い換えればメモリーの静的記 憶領域に確保されるのがクラスで実行時に動的記憶領域に割り当てられ るのがオブジェクトである。
それ故手続き指向言語でのデータ型に相当するのがクラスであり、変 数に相当するものがオブジェクトである。ただ従来の変数におけるデー タの代入はすべて「値渡し」(reference by value:異なった領域間で のデータの授受)であるが、オブジェクトでの代入はすべてポインター の授受(領域アドレスの代入または領域の重複指定)になる。 レストランの例でのそれぞれのオブジェクトの属性とメソッドは次の ようになる。(点線の上部は属性、下部はメソッドである。) 客・オブジェクト ウェイトレス・オブジェクト メニユー 伝票 注文する 食べる 伝票を会計係に運ぶ 金を払う 料理人・オブジェクト 伝票 注文を伝票に記入する 注文を料理人に伝える 料理を客に運ぶ 会計係・オブジェクト レシピー 料理を作成する 定価表 レジ 料金表を基に料金を計算する レジへ入力する [図2]レストランのオブジェクト これらのオブジェクトに対して「メッセージ」(作業依頼)を送ること コンピュータ・プログラミング手法の転換 87(186)
でプログラム全体の作業は進められてゆく。したがってメッセージはか ならず「あるオブジェクトに対してあるメソッドを起動する」という形 で送られることになる。レストランの例での手続き指向型プログラムの 機能の流れはオブジェクト指向ではすべて次のようなメッセージに変わ ってくる。 メツセージ順序 オブジェクト データ 処 理 ① 客 メニユー 注文する ② ウェイトレス 伝票 注文の記入 ③ ウェイトレス 注文を料理人に伝える ④ 料理人 レシピー 料理の作成 ⑤ ウェイトレス 料理を客に運ぶ ⑥ 客 食べる ⑦ 客 伝票 伝票を会計係まで運ぶ ⑧ 会計係 伝票・定価表 料金の計算 ⑨ 客 金を払う ⑩ 会計係 レジ レジへ入力する [図3]レストランのメッセージの流れ このようにプログラムをオブジェクト化することによって生ずるメリ ットはいろいろある。 以下にその主なものを箇条書きしてみよう。 (a)モデルの抽象化(対象の明確化) プログラムの構成単位が現実の実体に即しているために対象が明確に なっている。そのため例えばメニューが改訂された場合でもそれが属し ているクラスに着目して改訂すればよいので保守管理が容易である。
また現実の中から分析に必要な要素だけを取り上げてモデル化し、その モデルの実装部分を抽象化したままインターフェイス部分(関数部分) でデータの授受を行うので、いったんオブジェクトが決まれば、より弾 力的なプログラミングを行うことができる。 (b)カプセル化または情報隠蔽(モジュール間結合度の最小化) 上の例で料金表は会計係だけがデータを変更することが可能であるよ うにして他のオブジェクトからは直接変更できないようにした方がよ い。こうすることによって前述したモジュール間結合度を小さくするこ とができる。すなわちこのことによってプログラムの改訂に際して改訂 部分の影響が他に及ぶのを最小限に押さえることができる。 このための装置としてオブジェクト指向言語ではクラスのメンバーを 非公開部と公開部とに分けて定義することができるようになっている。 公開部に属するメンバーは他のクラスから参照することができるが、非 公開部に属するメンバーはそれが属するクラスの外からは直接参照でき ないように約束されている。ただしフレンド関数と指定された関数に限 り外部からでも参照できることになる。一般的にはデータメンバーは非 公開部としメンバー関数は公開部として設定する。このようにメンバー を保護することをカプセル化または情報隠蔽と呼んでいる。カプセル化 によりクラスの実装はクラス提供者のみが心得ていればよく、使用者は その仕様(メソッド部)のみを承知していればよいのだから、アベイラ ビリティは遙かに大きくなる。 (c)継承(ソフトの再利用) レストランの例でもしもウェイトレスが飲み物を作る機能を新たに兼 担するとすれば、今まで存在したウェイトレス・クラスのメソッドに飲 み物を作る機能を付加すればよい。このように既成のソフトに機能を付 加して新しいクラスを作成することを継承という。 またウェイトレスが新たに会計係を兼ねることにすれば、ウェイトレ コンビ=一タ・プ・tグラミングr法の転換 89(184)
ス・クラスと会計係・クラスの両者を合わせた新しいクラスが定義され ることになる。このように複数のクラスの属性とメソッドを受け継ぐこ とを多重継承と言っている。 継承はオブジェクト指向アプローチでの重要な特性であり、これによっ て既成のソフトの再利用が可能になる。 継承関係にある2つのオブジェクトで、論理的に子オブジェクトは親 オブジェクトに対してpart−of関係(子は親の一部であるという関係)を 持つ。このため親オブジェクトから子オブジェクトを参照すること、す なわち親から子にメッセージを送ることが可能になり、ソフトの体系化 やダイナミックな運用に効果を上げることができる。 (d)多様性(polymorphism) すでに定義したウェイトレスのオブジェクトに対して、更に役割の追 加した2種類のウェイトレスを定義するとしよう。まず普通のウェイト レスの役割の上にジュースを作る役割りも持たせられたものをウェイト レス1とする。また普通の役割の上に会計係の機能を持たせられたもの をウェイトレス2とする。この時ウェイトレスクラスはスーパクラス、 ウェイトレス1とウェイトレス2はサブクラスになる。このような場合 にオブジェクト指向言語ではスーパークラスのオブジェクトにサブクラ スのポインタ(記憶領域の最前部のアドレス)を代入できることが可能 になっている。(逆にサブクラスのオブジェクトにスーパクラスのポイン タは代入できない。)言い換えればこのようなポインターの代入によって ウェイトレスがウェイトレス1やウェイトレス2に変身できることにな るので、このようなことを多様性と呼んでいる。 (3)オブジェクト指向言語 オブジェクト指向言語が新しい汎用言語として注目されるようになっ たのはこの数年のことであるが、クラスを構成単位とする考え方は1967
年のSimula67ですでに実現されていた。この言語はAlgol60をオブジェ クト指向的に拡張したもので特に待ち行列シミュレーションに適した機 能も備えていた。(待ち行列シミュレータでは当初からクラスに似た概念 を備えていた。)この言語ではクラスを基に起動されるオブジェクトはイ ンスタンスという概念で呼ばれている。また初期のバージョンでは情報 隠蔽はできなかったが、その後の改訂版ではそれが可能になっている。 ソフトを再利用するための継承はサポートされているが、多重継承は含 まれていない。Simula67で大変興味深いのはオブジェクトの実行に際し てコルーチン(coroutine)という考え方を導入している点である。これ は親プロセスが子プロセスを一方的に呼び出す関係でなく、2つのプロ セスが互いに対等に呼び出し合う関係であり、これはクラスのように独 自のロジックとデータを持っている場合には効率的な実行方法である。 1970年代の始めゼロックスの研究センターでA.Kay及びA.Goleberg らによってSmalltalkが開発された。現在はその普及版としてSmall− talk80が使用されている。これは現在ではC++に次いで多用されてい るオブジェクト指向言語である。この言語で強調されてよいのはそれが 豊富なクラス・ライブラリと便利な開発環境を備えていることである。 クラス・ライブラリにはカテゴリ毎に数百のクラスが含まれ、例えばcol− lectionsなどのように基本的なデータ構造を提供するライブラリ・クラ スもあるし、またPointなどのように画像などの作成を容易にするユー ザ・インタフェイス・クラスも含まれている。さらに開発環境としては クラス記述の定義や修正に利用することができるbrowse、デバッグに効 果を上げるdebugger、自動的にコンパイルと保存を行うsaveなどのツー ルが豊富に揃っている。Sma11talkは純粋なオブジェクト指向であるか ら、すべてのプログラム要素はクラスの射像であるインスタンス(オブ ジェクトをインスタンスと呼ぶ)として構成され、またすべての処理は インスタンスへのメッセージとして実行されることになる。クラスはイ コンピュータ・プログラミングf法の転換 91(182)
ンスタンス変数(データ)とメソッドから構成され、情報隠蔽も勿論可 能である。さらにクラスは継承機能を持って完全な階層構造をなしてい るが多重継承の機能は持っていない。メッセージは例えばabcというイ ンスタンスに対してpushというメソッドをを行わせる場合には空白を 空けてabc pushのように書く。メッセージには単項メッセージ、2項メ ッセージ、キーワードメッセージという3つのタイプがある。単項メッ セージ、2項メーッセージは対象となるインスタンスまたはオペランド が単項か2項かで決まり、キーワードメッセージはメソッドが引数を持 つ場合である。 次に現在最も高い頻度で使用されているのがC++である。C++は 1980年代初期にBjarne Stroustrupによって創始された。この言語は典 型的なハイブリッド言語で2つの側面と持っている。一つはC言語のス ーパーセットすなわちその上位言語としてC言語の足らざるところを補 っていることである。したがってC言語で書かれたプログラムはほとん どC++でもコンパイル・実行が可能であると同時に新しい機能を付加 することによってCより優れた言語になっている。 第2の側面はそれがオブジェクト指向言語として抽象データ型とオブ ジェクト指向プログラミングを実現していることである。抽象データ型 とは言語に既存の型以外にユーザがクラス概念を用いてデータ型を自由 に定義できることである。オブジェクト指向プログラミングではこのク ラスの変数としてのオブジェクトを定義し、すでに説明したカプセル化、 継承、多様性などの利点を用いて現実によりよく即応したプログラミン グを可能にしている。 以下にC++の言語としての主な特徴を列挙しておく。 (a)C++では種々の点でC言語の欠点が改良されていると書いたが、そ の代表的な例として、関数プロトタイプや関数の多様性などが挙げられ る。プログラムの初頭で関数の仕様宣言をするのにCではint func()の
ように書いてよかったが、C++ではint func(float,int)などのように 引数の型を書かねばならい。これを関数プロトタイプといい、これを義 務づけることにより引数の参照エラーがコンパイル時にチェックでき る。関数の引数の個数や型が異なれば、1つのプログラムに同じ名前の 関数を複数個置くことができる。これを関数の多様性と呼ぶ。これらの 改訂はC言語の改良であると同時にオブジェクト指向言語として発展さ せるための布石にもなっている。 (b)C言語には異種データの集合を取り扱うのに構造体という概念を導 入しているが、この構造体を更に発展させてその要素にデータのみでな く関数もつけ加えることができるという形でクラス(オブジェクトの雛 形)を定義している。このようにクラスは要素(メンバーと呼ぶ)とし てデータメンバーとメンバー関数を持つことができ、これによって現象 世界の実体またはモノを表現することができる。関数メンバーの中でオ ブジェクトの宣言と同時に実行される初期化用の関数をコンストラクタ ー、逆にオブジェクトのクローズで自動実行される関数をデストラクタ ーと呼ぶ。もちろんこれらのメンバーは非公開部(private:)と公開部 (public:)とに分けてカプセル化することができるが、通常はデータを プライベート、関数をパブリックとする。 (c)C++の優れた点の一つに演算子の多様化が挙げられる。すなわち 演算子を多様化することによってADTは組み込み型とほとんど同じよ うに使用できることになる。例えばa+bにおいて、変数aとbは演算 子+の引数になる。演算子を多様化するとはこのaとbを組み込み型に も使用者の定義するADTにも設定できるということなので、結局演算 子+を整数演算にもstring演算にもまたcomplex演算にも定義づけるこ とができることを意味している。 (d)例えば自動車という実体にある特殊な属性を付加すれば自家用車、 トラック、バスなどの実体が得られる。この時c++では自動車を表すク ’ンピ・一タ’プ゜グ7ミング{’ t}1の願93(180)
ラスを「基底クラス」(base class)、それを特殊化したクラスを「派生 クラス」(derived class)と呼んでいる。 このようなクラスの親子関係を継承と称することはすでに述べたとお りである。C++では単純な継承以外に、複数の親クラスの属性を受け継 いだ多重継承の機能も備えている。このような継承という概念を導入す ることは2つの意味で重要である。一つはクラス間の体系化が図れるこ とであり、さらに一層重要なことはこれがクラスの再利用に役立つこと である。従来の手続き型言語ではちょっとした変更でもプログラムを組 み直さなければならなかったが、C++ではプログラムの構成単位が現 実の実体と即応しているために以前作っておいたクラスを修正して新し いクラスを作ることが比較的に容易である。 以上述べた三つの言語はいつれも実際の処理系をもっているが、これ 以外にオブジェクト指向を説明するために工夫されたものもいくつかあ る。 例えばEiffelはB.Meyerがその著”Object−Oriented Software Con− struction”で説明するために創始した記述法であり、またObjective−Cは B.Coxが”Object−Oriented Programming:An Evolutionary Ap− proach”で紹介した言語である。これらももちろんオブジェクト指向言 語が備えている基本的条件すなわちクラスによるプログラム構成、メッ セージによるオブジェクト実行、情報隠蔽、多様性、継承などの機能を 備えている。 、 (4)結0( 本稿ではオブジェクト指向の考え方を専門外の人にも理解してもらう ためになるべく言語記述を用いないで説明してきたつもりである。すな わちオブジェクト指向的な考え方では世の中の個々の実体を情報と機能 の集まりとして捕らえ、その個々のモノの射像を単位としてプログラム
上に表現しようとするのである。この考え方が優れているのはそれが現 実のモノの実体をよりよく反映しているからであるが、同時にこの手法 を実際に適用するに際して次に述べるような大きな問題点も存在してい る。 一般にオブジェクト指向によるシステム構築では「オブジェクト指向 分析」(00A:問題状況の把握)、「オブジェクト指向設計」(OOD:問題 の解決方法の決定)「オブジェクト指向プログラミング」(00P:解決方 法の実装)の3段階を経て目的が達成されるが、中心になるのはOODで ある。というのはオブジェクト指向の性質から考えて00Aと00Dの差 は微妙であり、また設計ができれば比較的にプログラミングはやりやす いからである。 しかしこの設計段階において、オブジェクトを抽出することが意外に 難しい場合が多いのである。普通オブジェクトを見つけるにはシステム 要求書の中の名詞などを拾い出してゆく方法を取るが、そのオブジェク トには有形のオブジェクトの他にも、役割を表すオブジェクト、出来事 のオブジェクト、関係のオブジェクトなど様々な種類のオブジェクトを 想定することができる。例えば前述した仮想レストランの例では、各種 の人間のオブジェクトの他にメニューをオブジェクトに加えることも可 能であろうし、あるいはレストランの売り上げや利益という概念的なオ ブジェクトを付加することもできる。このようなモノとモノとの複合的 な関係の中で、ある目的に沿って適正なオブジェクトを選ぶことができ るかどうかがこのアプローチが成功するか否かの前提条件になる。言い 替えればこれらのオブジェクトの抽出が適正にできれば後はスムーズに 進むが、もしし損なうと設計とプログラムの間を空しく往復するだけに なってしまう。 ところが今のところこのようなオブジェクトの抽出を行うための十分 客観的な指針が与えられていない。そしてこのことが現在オブジェクト コンビ、_タ.プログラミングr法の転換 g5(178)
指向アプローチの普及を妨げる大きな原因になっているのである。 [参考文献】 ①Edward Yourdon and Larry Constantine:Structured Design: Fundamentals of a discipline of Computer Program and System Design,Prentice・Hall Internationa1,lnc,London,1979. ②Bjarne Stroustrup:The C++Programming Language, Addison. Wesley Publishing Co.,1986. ③Richard S. Wiener and Lewis J. Pinson:An lntroduction to Object− Oriented Programming and C斗十,Addison・Wesley Publishing Co.,1988. ④Bertrand Meyer:Object−Oriented Software Construction, Prentice Hal1,New York,1988. ⑤ Manoochehr Azmoodeh:Abstract Data Type and Algorithms, The Macmillan Press,1990. ⑥Dav{d Embley,Barry Kurtz,Scott Woodfield:Object−Oriented System Analysis;A Mode1−Driven Approach, Prentice−Hall,Inc,1992. ⑦Raimund Ege:Programming in an Object・Oriented Environment, AP Professional,1992. ⑧Edward Yourdon:Object−Oriented System Design:An Integrated Approach,Prentice−Hall,lnc,1994.