[雑談] オブジェクト指向を考える

オブジェクト指向の3大要素というのをよく見かけますが、なんか少し違和感があるのが正直なところです。

オブジェクト指向の3大要素

オブジェクト指向の解説などを見るとオブジェクト指向の3大要素として以下が挙げられています。

  • カプセル化 - メソッドなどの公開された外部仕様のみを外部からアクセス可能とすることでオブジェクトを使用するシステムがオブジェクトの内部動作に依存できなくすること
  • 継承 - 新たな機能が必要となった際に既存のオブジェクトから新たなオブジェクトを派生することで既存オブジェクトの外部仕様や動作の一部を再利用を行うこと
  • ポリモーフィズム - 新たな環境、要件に対応したオブジェクトを既存オブジェクトあるいはインターフェースから派生させることでシステムの対応範囲を拡大すること

カプセル化

まず、カプセル化について考えます。

例えばデータを保存し、必要な時点で読み出すとを可能とするデータ保存オブジェクトがあるとします。データ保存オブジェクトがファイルにデータを保存し、保存しているファイル名がわかってしまうと、システムはデータ保存オブジェクトを使用せずにファイルに直接アクセスしに行くかもしれません。

何らかの理由でデータ保存オブジェクトをファイルにデータを保存するのではなくデータベースを使用するように変更した場合、このようにデータ保存オブジェクトがファイルにデータを保存することを前提にしていたシステムは動作しなくなります。

データの保存方法といった内部動作を隠ぺいすることでオブジェクトの内部動作に依存するシステムを作成できなくし、局所的な変更に対する強靭性を確保するのが「カプセル化」の効果です。

継承

次に継承についてです。

最近、セルフレジというものが普及し始めています。買い物客が商品に貼られているバーコードをバーコードリーダーで読み取らせて、全部の商品の読み取りが終わったら現金、あるいはクレジットカードで精算するという機械です。

これを一つのオブジェクトとして実現することは通常ないのですが、ここではセルフレジというオブジェクトがあるとします。

こちらも最近普及し始めた○○ペイといったQRコード決済に対応する新型を作ることを考えると、細かいところをざっくりと省略してしまえば商品バーコードの読み取りや現金、クレジットカードの決済機能はそのまま残して、QRコード決済機能を追加すればいいだけです。

この場合、セルフレジオブジェクトからQRコード決済対応セルフレジオブジェクトを派生させれば従来機能は元のセルフレジオブジェクトから継承されるため、QRコード決済機能だけを追加すればよいことになります (実際には決済手段が増えるので決済関係の修正は必要になるかもしれません)。

このように従来機能を活かしたまま、新しい機能の追加などが可能になる点が「継承」の効果になります。

ポリモーフィズム

最後にポリモーフィズムについてです。

文字・図形の描画、編集を行うアプリケーションはキャンバスというオブジェクトを用意して、キャンバスに文字や図形の描画命令を発行することで画面表示を更新するといった構成をとる場合があります。

このような場合、キャンバスオブジェクトを描画命令を受け取る抽象的なキャンバスオブジェクト (あるいはインタフェース) として作成し、画面への表示を行うディスプレイキャンバスオブジェクトを抽象キャンバスオブジェクトから派生させるやり方がとられることがあります。

印刷機能が必要な場合には抽象キャンバスオブジェクトからプリンタへの出力を行うプリンタキャンバスオブジェクトを派生します。

このような構成にすることでアプリケーションは出力先を意識せずに同じキャンバス描画命令を使用した画面表示とプリンタ出力がキャンバスオブジェクトの切り替えだけで可能になります。

これが「ポリモーフィズム」の効果になります。

オブジェクト指向型言語について

ここまでオブジェクト指向の3大要素について考えてきましたが、ここでオブジェクト指向とは何かということを考察したいと思います。

コンピュータのCPUは数値として表現されたデータに対して演算や比較などの命令を所定の手順で実行することで計算を行います。

計算に必要な手順に合わせてCPU命令を1個1個組み合わせて命令列を作成し、プログラムを作るのは非常に面倒なため、例えば数式を対応するCPU命令列に変換するプログラムが作られ、計算手順をより分かりやすい形式で記述できるプログラミング言語になりました。

その後、作成するプログラムが高度化するのに合わせてプログラミング言語も高度化していきましたが、基本的には計算手順、あるいはプロセスを記述するものが主流でした。

ソフトウエアが扱う対象が拡大し、ソフトウエアが複雑化、大規模化していくとこういったプロセスをベースにしたソフトウエア開発は困難になってきました。

例えば営業であれば商談ごとに受注、出荷、請求、領収のプロセスが流れ、それとは別に商品ごとに発注、入荷、検収、支払いの仕入れプロセスが流れ、さらに人事の採用、配置、査定、給与支払いのプロセスが流れと、多数のプロセスが相互に関係を持ちながら流れていきます。

このような情報、モノ、金の流れをプロセス単位で追っていくとプロセス間の相互作用が複雑になり、管理できない状態になってしまいました。

そこで、プロセス基準でのシステム理解をやめて、システムの構成要素を基準にして、構成要素間の相互作用によりシステムを理解したほうがよいのではという考え方が広まったのではないかと私は考えています。

オブジェクト指向は、システムを構成する個々の要素をオブジェクトとしてモデル化し、オブジェクトの受け取るメッセージと受け取ったメッセージに対するオブジェクトのふるまいを定義することで、システムをオブジェクト間のメッセージ受け渡しとして実現しようという考え方で、オブジェクト指向型言語はその考え方を実現するためのツールとして開発されたものと思います。

しかし、このように考えていくとオブジェクト指向の3大要素が果たしてオブジェクト指向に必須のものであるかというと、疑問が残ります。

「カプセル化」はシステム要素をオブジェクトとしてモデル化し、オブジェクト間の相互作用でシステムを記述するという観点から必要と考えられますが、「継承」と「ポリモーフィズム」は上に書いたオブジェクト指向の考え方には登場してきません。

そこが最初に挙げたオブジェクト指向の3大要素に対する違和感です。

オブジェクト指向型言語に対するもう一つの視点

しかし、オブジェクト指向型言語を考えた場合、オブジェクト指向にもとづいたプログラムの記述だけを目標としているわけではなく、オブジェクト指向の要素を導入することで従来の手続き型プログラミング言語を改良することも目標にしていると考えられます。

プログラミング言語の歴史を見ていくと、まず手続き型言語としてのFORTRANが開発されました。

FORTRANのようなシンプルな手続き型言語、自分が80年代初めに最初に学習したプログラミング言語であるBASICも同じですが、は複雑なプロセスになると処理フローを追いかけることが難しく、何らかの改善が必要と認識されるようになりました。

こういった処理フローの複雑化に対応するため、新しいプログラミングの考え方として構造化プログラミングとそれをサポートするALGOLが登場します。

処理フローを構造という枠組みで整理することで設計段階から処理フローの複雑化を抑制するというのが構造化プログラミングの考え方で、ALGOL自体は普及しなかったものの、同じく構造化プログラミングの概念を導入したpascalはそれなりに普及し、構造化プログラミングはCをはじめとする手続き型言語に引き継がれています。

ソフトウエアの規模が拡大していくと1個の独立したプログラムとして開発することは難しくなり、ソフトウエアを分割して、分割したそれぞれを独立に開発する枠組みが求められるようになりました。

このようなソフトウエアを分割して開発する枠組みとしてモジュールが提案され、Modula-2やAdaなどがモジュールをサポートするプログラミング言語として登場します。

これらの言語は普及こそしませんでしたが、Adaは米国防総省がバックアップして開発したという鳴り物入りで登場したのですけど、モジュールの枠組みは有用と認識され、例えばC言語においてヘッダーファイルに記述された関数、変数以外は他のプログラムファイルからは使用しないといった運用規則を設けることにより疑似的にモジュールを実現するといった形で普及してきました。

そしてそのあとに登場するのがC++やjavaなどのオブジェクト指向型言語です。

モジュールによるプログラミングはソフトウエアを構成する要素をモジュールとして独立に開発することで大規模ソフトウエアの開発を容易にすることを目的としていました。

しかし、開発するソフトウエアの数が増えてくると単に分割して開発するだけでは手に負えなくなり、作成したモジュールの再利用といった開発工数の低減が求められてくるようになりました。

ここにオブジェクト指向型言語がうまくはまったことがオブジェクト指向型言語が普及した要因ではないかと考えています。

オブジェクトの概念はある意味モジュールの概念を強化したもので、ソフトウエアを分割して独立に開発するといったモジュール的な要素に加えて継承やポリモーフィズムによるオブジェクトの再利用性が強化されました。

それまでは様々なソフトウエアで使用できる汎用モジュールは汎用的に設計され、個々のソフトウエアに適用する際には汎用モジュールごとに決まる手順や事前作業が必要でしたが、オブジェクト指向型言語を使用することで何らかのソフトウエア向けに専用設計されたオブジェクトを継承とポリモーフィズムを使用して他のソフトウエアにも再利用できる可能性が広がったということです。

こう考えるとオブジェクト指向の3大要素はオブジェクト指向プログラミングの3大要素というのが適切なのではないでしょうかね。

まとめ

以上、オブジェクト指向の3大要素といわれるものを考えてみました。

「カプセル化」、「継承」、「ポリモーフィズム」はオブジェクト指向の3大要素とは言えないものの、オブジェクト指向プログラミングが目標とする大規模で複雑なソフトウエアの開発において開発作業を容易にし開発工数を提言する重要な役割を持ったものというのが妥当なところだと思います。

システムのモデル化や設計などの上流工程でもオブジェクト指向が使用されている現状を考えると、オブジェクト指向という大きな言葉を使うのは少し考えたほうがいいのかもしれません。


bewise.jp

Be Wise: 賢くなろうということ

0コメント

  • 1000 / 1000