トップページ

2011年1月11日

新説オブジェクト思考

 いろいろなブログでオブジェクト指向技術について解説しているが、なかなかわかりいやすい説明って難しいみたいですね。犬や猫のたとえが悪いといいながら、ピンとこない用語が羅列していて、やっぱりわかりにくい解説が多いです。私 はSEですからソフトウェアの専門家とは言えませんが、私なりに理解しているオブジェクト指向について解説してみましょう。

[直球勝負のオブジェクト指向]

もう何かの例えとか、哲学的な前置きなんてしません。

● クラスは単にプログラム全体のサブプログラムと考えればよい
● クラスはメンバー変数とメンバー関数(メソッド)により構成される。メンバー変数はクラス内に限定されたスコープでのグローバル変数である
● メンバー変数やメンバー関数をパブリック宣言することにより、他のクラスからメンバー変数に値の受け渡しができたり、メンバー関数を実行することができる
● インスタンスを生成することにより、インスタンスごとに違うメンバー変数値を保持することができる。インスタンスはつまり、クラスによって生成されるオブジェクトの識別子のようなポインタである。 これにより、同じクラスで違う状態値を持つオブジェクトを生成することができる。

 これらのことから、クラス生成されるインスタンスはステートマシンを実現し、メンバー変数の値は状態値となります。プログラム全体としては、複数のステートマシンが通信(メッセージパッシング)するシステムとして構成されます。

 オブジェクト思考とイベントドリブンは別の技術ですが、現代のGUIフレームワークでは、イベント制御を行うのに都合がよいシステムとなっているわけです。フレームワークの代表的なもには開発ツールです。フレームワークの定義はユーザーがクラスや関数の中にコードを書き込むものです。それに対しクラスライブラリは、クラスが多数用意されて、ユーザーがそのクラスを利用するものです。最近の.NET FRAMEWORK という言葉からフレームワークはクラスライブラリではないかと思っている方も多いと思いますが、フレームワークとクラスライブラリは違います。

 クラスをたくさん作ってクラスライブラリのようなものを作ると、自然に似たようなクラスは同じメンバー変数、同じメンバー関数を使うことが多くなってきます。そこでクラスの共通するメンバー変数やメンバー関数を基底クラスとして定義して、それを継承してクラスを作ったほうが冗長化されずに効率的なコードとなります。基底クラスを継承して作ったクラスは派生クラスと呼ばれます。

 同じ基底クラスから派生して作ったクラスで、似たようなメンバー関数がある場合、同じメソッド名にしてユーザーに扱いやすくなります。これが多態性です。基底クラスを使って派生クラスのインスタンスを生成することができるのが多態性の特徴です。

 オブジェクト指向言語では、関数の引数やリターン値またはコンストラクタの引数にオブジェクト(インスタンス)が使えます。関数のオブジェクト引き渡しに派生クラスをつかうとさらにバリエーションのあるプログラムが生まれます。この例がデザインパターンとも言えます。

 これがオブジェクト指向の要点です。現在でも論争の焦点となっているのは次の点です。

● メッセージバッシングの多用はプログラムの動作が追いにくい原因となる。関数でできるものは関数で実現するのがよいのではないか?
● デザインパターン本では派生クラスを多用しているサンプルプログラムが多いが、実際の開発でこのようなケースが有効につかえるのか?

クラスを使うメリットはメンバー変数に状態を保持することであり、そのような必要のない、引数から単純にリターン値が演繹されるものは関数が適しています。それに対し、ファイルを一行ずつ読むようなプログラムでは、何行までファイルを読んだか状態を保持する必要がありますので、ファイルを読むようなことをする場合、ファイルオブジェクトクラス使うことが適切であります。例えば、ボタンをクリックするごとにファイルを一行ずつ読むような動作も可能なようにするには、ファイルの読み出しに適したクラスを作る必要があります。

 しかし、状態保持としてメンバー変数を使わずに、データベースやセッション変数を使っている場合は、クラスではなく関数でプログラムを作成しても問題ありません。結果として業務ロジックではメッセージパッシングは使わないほうが、メンテナンス面で有利となります。

 デザインパターン本ではオブジェクト指向のメッセージパッシングよりも、多態性が強調されています。

   return(new 派生クラス()):

のような関数のリターン方法などデザパタでは「決めの一手」といった印象を受けます。現実の業務ロジックでは、綺麗なタイプ分類により、派生クラスのメソッドの挙動が変わるようなケースは少なく、「一般的な処理と例外的な処理」でコーディングされるのが通常です。
 たとえば、5つの派生クラスと5つの関数を記述することなると、25個の関数を記述することになります。このようなプログラム構造はいくらデバッグしてもバグが残存する原因となります。

 条件分岐がバグの温床になり、多態性を使ったほうがいいというのが一般論ですが、if文の == と書くべきところを = で書いてしまったり、switch 文の break を抜かしてまったりするポケミスが多いことは多くの人が経験しています。。ユーザー要件としては、あくまでも条件として定義されてくるものなです。それから本当に複雑な条件文では多態性は役にに立ちません。

 それでは、どのようなケースで多態性は有用なのでしょうか?それは違うI/Oインターフェイスを切り替えるような場合です。またデザパタでは基底クラスの仮想関数に派生クラスのメンバー関数をオーバーライドを行うような例がありますが、これはユーザーごとにプログラムをカスタマイズし、違う動作を実現するのには有用な技術となます。パッケージソフトのアドインなどには応用できます。

 これからもオブジェクト指向を学ぶ人は、サンプルコードを見た時に、漫然と見るのではなく、どの一行が「決めの一手」なのかを考えてくださいね。
 

inserted by FC2 system