【オブジェクト指向のこころ】14章 デザインパターンの原則と戦略

デザインパターンとともに学ぶオブジェクト指向のこころ」の学習記録。
「第14章 デザインパターンの原則と戦略」のまとめ。

解放/閉鎖原則

モジュール、メソッド、クラスは、

  • 拡張性という観点から見た場合、見通しが利くよう(open)になっているべきである。
  • 変更という観点から見た場合、閉鎖的(closed)になっているべきである。

例えば、Bridgeパターンは既存クラスに手を加えることなく、新たな実装を追加(拡張)できる。

解放/閉鎖原則の本質的な意味は、新たな機能を個別に、すなわちモジュール化された形で追加していけるようにすることで、統合コストを最小化したソフトウェア設計にすること。

コンテキストからの設計原則

Bridgeパターンの例

  • 様々なハードウェア上に形状を描画しなければならないとき、つまり様々な実装が必要となる場合、Bridgeパターンを使用することになる。
  • Bridgeによって形状は共通のインタフェースを介して実装(つまり描画プログラム)を使用することが明確化される。
  • つまりコンテキストから設計するという作業により、最初に形状の要求というものを考察する、すなわち描画対象を見極める必要性が示唆される。
  • こういった形状によって実装の振る舞いに対する要求が決定される。
  • 例えば実装(描画プログラム)には、直線、円の描画といった要求がある。
  • 言い換えれば抽象的側面を具体化したもの(様々な形状)が実装を具体化したものに依存することになるとしても、描画プログラムを定義するのはその形状である。
  • 実装のインタフェースを考える場合、目の前にある特殊な状況ではなく、抽象的側面を具体化したもののなかで概念のニーズを考える。

これは「依存性の逆転原則」と呼ばれる。

  • 高次のモジュールは、低次のモジュールに依存してはならない。
  • 高次のモジュールと低次のモジュールは、いずれも抽象的側面に依存すべきである。
  • 抽象的側面は詳細に依存してはならない。
  • 詳細が抽象的側面に依存すべきである。

Christopher Alexanderは、最も簡潔な、概念的なレベルから徐々に詳細や機能を追加していくことで、設計を複雑化させていくプロセスを「複雑化」(complexification)と呼んだ。
この複雑化と依存性の逆転は、デザインパターンの根幹をなす基本原則である。

こういった原則は、オブジェクトを使用する側とされる側との結合が、実装レベルではなく、概念レベルで行われるべきであると述べている。
これは、GoFの「インタフェースを用いて設計を行う」べきであるという主張とも一致している。

一般的な状況と流動的要素を洗い出すための時間を割き、クラスが発生するコンテキストを考察する。
これには共通性/可変性分析(CVA)を用いる。
このテクニックを道いることで、実装の汎用化度合と汎用化にかける追加コストを天秤にかけることができる。

具体例として、形状を描画する際のニーズに着目すると、「直線の描画」と「円の描画」という要求を洗い出すことができる。
「直線と円を用いても描画できない形状とは何か?」と自問することにより楕円という形状を導き出すことができる。
ここでいくつか選択肢が生まれる。

  • 直線と円に加えて楕円を描く方法を実装する。
  • 円は特殊な状況の楕円であると考え、円の代わりに楕円を実装する。
  • 楕円に対応するコストが、それによる利益よりも大きい場合、楕円の実装を行わない。

この類の選択は、あるコンテキスト内で外面的に同じ振る舞いを有するクラスを設計する際に重要となる。
それにより、クライアントのクラスをその実装から切り出すことができる。

流動的要素のカプセル化

著者の設計成果物には類似点がある。
それは、ほとんどの設計において、クラスの継承関係が2階層を超えていないという点である。
3階層以上の設計は、デザインパターン自体が派生元の基底クラスとして複数の階層を要求しているケースが大半となっている。
例えばDecoratorパターンは3階層になっている。

このようになる理由は、クラス内に複数の流動的要素を保持しない、という設計目標があるためである。