タイトル(OO-Style)
タイトル(オブジェクト指向りゅう)

ハードウェアでは当たり前のカプセル化 prev<<>>next インスタンスとオブジェクトの用語について

オブジェクト指向での再利用性向上について

オブジェクト指向開発=再利用性の向上 といったイメージがありますが、実際にオブジェクト指向開発を行えさえすれば 部品などの再利用性が向上するのでしょうか?これについて考えてみます。

▲このページのTOPへ

再利用性向上とは

オブジェクト指向で開発をすると再利用性が高まる。これは本当でしょうか? 少なくともオブジェクト指向言語を使って開発したからといってそれだけで再利用性が高まるなどといことはまずありません。 そもそも再利用って何でしょうか? オブジェクト指向で全ての元となるものはクラスです。それではクラスを再利用するというのはどういうことか次に書き出してみます。

  • 既存のクラスを変更することなく、そのままを利用できる
  • 既存のクラスを変更することなく、継承して利用できる

突き詰めるとこれだけかと思います。前者はSytem.StringクラスやSystem.Text.FileInfoクラス、後者はFormクラスなどが代表的な例です。 JAVA API や、.NET Framework はこれら再利用可能な部品の集合体といえます。 実際これらのクラス群をベースに開発を進めることになります。
今のクラスは非常にコアなクラス群ですが、逆に最もユーザーに近い側から見ていくとどうでしょう。 ユーザーインターフェース(以下、UI)を実装したクラスは再利用可能か?まず無理ですね。 1度や2度設計・製造を行っても、使い勝手やユーザーの好みでかなり仕様が(見た目も)変わります。 それではそのUIと結びつくビジネスロジック部はどうでしょう。 ここも再利用性という点から考えるとやはり難しい。UIを意識した作りになる傾向が強いです。 本来ビジネスロジック層は、UIとは切って設計しますが、PG工程まで降りていった際に結びつく傾向があります。 仮にここの結び付けがなかったにしても、そのシステム固有のロジックがベッタリという傾向も強いものがあります。 しかし機能単位に設計すれば部品化することはできるでしょう。 このように、UIで再利用性のあるクラスを作るのは難しいものがあります。 ビジネスロジックにしても仕様をそのまま作りこんでいったのではとても再利用可能なものはできないのです。

ではどうすれば再利用可能なクラスを見出すことができるでしょう。 それに必要なものはとにもかくにもクラスを設計することです。 これを行わないと、どこに実装するのか、クラスをどう関連付けるのか、そこを伏せての実装になります。 設計とまでいかなくても必ず考える必要のある項目なのです。

そして、再利用をめざず我々としては、何かを実現するときに常に2つ以上のクラスで構成できるか?と考えます。 1つはその機能を一般化(抽象化)した汎用的なクラス。 もう1つはそのクラスを利用したアプリケーションに使いやすい形で提供するクラスです。
もちろんその際にクラスが増えるかもしれないし、分けても意味がない。という結論に至るかもしれません。 しかし、常に 1)部品となるクラスを作る 2)そのクラスを使用する という形を意識することにより、 徐々に「使われる側のクラス」はどのようなものかが見えてくるようになるはずです。 これにより、汎用的に作られたクラスが1つとそれを利用したアプリケーションで実装するクラスが1つとなり、 目的の動作を実現します。そしてこの汎用的に作られたクラスが、再利用可能なクラスとなるのです。
とにかく初めは1つで実現していたものの中から汎用的(抽象的)な部分を抜き出すというのは難しいことですが、 慣れれば必ずできます。モデリングとしてUMLを学ぶのも近道かと思います。

ここにいくつかクラス図を挙げます。青いクラスが再利用可能となり得るクラスです。

フォームの継承 汎用クラスの利用 クラスの拡張 動作の抽象化

フォームの継承

汎用クラスの利用

クラスの拡張

動作の抽象化

このように、UIに関しても必ずアプリケーションでの共通点などがあるはずです。 これを上位クラスに実装することで開発効率のアップと、仕様の統一が図れます。 仮に別のプロジェクトで使用できるような汎用的なクラスまでたどり着けなかったにしても(納期もあるし・・)、 この形を見出すだけでも1プロジェクト内での共通化・標準化にはかなりの効果を発揮します。
全てを1つのクラスで実装するのではなく、上図でいう、青いクラスと白いクラスとで実装するように心がけることが非常に大切です。

かなり感覚的なことをいうようですが、数を使って一生懸命計算をするのではなく、 方程式を見つけ出して、そこに値を入れて答えを出す。という2段構えの形を常にとるよう心がけることが大切です。 この方程式が青いクラス、値を入れて答えを出すが白いクラスにあたります。

▲このページのTOPへ

部品は簡単に交換できるか

よく部品を置き換えることで機能を変更できる。というような書き出しや、絵も見かけます。

交換可能な部品のイメージ

交換可能な部品のイメージ

しかしこれを実装するのはかなり慎重にクラス設計を行わないと難しいものがあります。 というか、筆者はこのクラスの置き換えについてよい例が正直思いつきません。 思い浮かぶとしたら、Streamクラスなどです。(FileStream, MemoryStramなど) きっと絵の中の結合部はStreamクラスでFileStreamを当てていたのをMemoryStreamに変更することにより、 ファイルIOがメモリIOに変更され処理速度を上げた。などといった感じでしょうか? しかし、行われていたファイルパスの指定は不要になるわけで本当に置き換えるだけでOKなものってあるのでしょうか?
ただ、Streamクラスのように、上位クラスで共通のインターフェースを提供し、下位クラスで実装することにより、 インスタンス生成以降は全て同じコーディング・発想で進めることができるということが確実に実現できます。 つまり、FileStream処理もFileStreamクラス1つで完結させるのではなく、Streamクラスとそれを継承したFileStreamクラス という2段構えで構成することにより、MemoryStream、○○Streamクラス、その他のStreamが発生しても すべてStreamクラスで対処ができるのです。つまりここでは、Streamクラスは[Class]、FileStream,MemoryStreamクラスは[ClassA,ClassB]に該当します。

▲このページのTOPへ

提供する側と利用する側

オブジェクト指向開発と一言で言っても、このように部品となるクラスを作る側と、 存在するクラス群を使用する側の大きく2つに分かれます。(開発の二分化 を参照) 自分がどちらにあたるのか(また両方なのか)を意識しましょう。 大規模プロジェクトなどは完全に分かれますが、中規模・小規模プロジェクトとなると、この汎用化・共通化への 工数が持てないことが多く、再利用をしたくてもそのように作れないのが現実化と思います。
大規模プロジェクトの場合は、相反する側の実際の開発には手を出す機会がないでしょうから、 コミュニケーションをしっかりとり、相手側の要望を双方理解することが大切です。
中規模・小規模プロジェクトで、標準化の工数が得られない場合、部品となるクラスを作るのと使うのが同じ人物である可能性が高くなります。 この時、両方を触るのでクラス自体が2つに別れているようでも実は汎用性のないクラスとなっている(クラスが2つになっているだけ)というクラスになることが非常に多いので、 機能分割をしっかりと意識し、先に挙げた青いクラスをなるべく明確に設計することが非常に大切です。