パッケージ設計の原則
パッケージ内の凝集度に関する原則
再利用・リリース等価の原則(REP)
再利用の単位とリリースの単位は等価になる。
ライブラリを提供している作者に対して、使用者が求めること
- 保守の保証。ライブラリのテストはしたくない。
- 古いバージョンのサポートも対応してほしい
ライブラリは、それを再利用する人の視点に立って構造化する必要がある。
- 1つのパッケージ内に入れるクラスは、同じ対象者によって再利用されるものに統一したい。
- コンテナライブラリと、会計処理フレームワークが同一のパッケージにあっても、大体どちらか一つしか使わないよね。
- パッケージ内のクラスは全て再利用可能なものか、全て再利用できないものかのどちらかに統一すべき。
- 再利用可能なクラスのパッケージに、再利用できないクラスが存在しているとノイズでしかない。
全再利用の原則(CRP)
パッケージに含まれるクラスはすべて一緒に再利用される。つまりパッケージに含まれるいずれかのクラスを再利用するということは、その他のクラスも全て再利用することを意味する。
- 互いに強い関連性を持たないクラスを、同じパッケージにまとめるべきではない。
- パッケージを採用するときは、そこに含まれるすべてのクラスに依存することを確認する。
- また、自分でパッケージを作るときも、あるパッケージに1つにまとめるクラスは互いに分離できない関係になるように、また、ユーザーがパッケージから抵抗されるすべてのクラスに依存しなければならないように設計する。
閉鎖性共通の原則(CCP)
パッケージに含まれるクラスは、皆同じ種類の変更に対して閉じているべきである。パッケージに影響する変更はパッケージ内のすべてのクラスに影響を及ぼすが、他のパッケージには影響しない。
- 単一責務の原則のパッケージ版。パッケージも変更の理由を複数持っていてはいけない。
- 変更箇所が1 つのパッケージにしておけば、再リリースは変更されたパッケージで済む。
- 開放閉鎖の原則と密接な関係がある。同じ理由で修正されるクラスは一つのパッケージにしておく。そうすることで、ソフトウェアの再評価、再リリースに掛かる負担を最小限に抑えることができる。
パッケージ内の原則結論
- パッケージ内には、極力同じ理由で修正されるクラスを一つのパッケージにしておくこと
- パッケージは再利用予定のクラス一覧と、再利用予定が無いクラス一覧で分割する。
パッケージ間の結合度に関する原則
非循環依存関係の原則(ADP)
パッケージ依存グラフに循環を持ち込んではならない
- 中規模以上のプロジェクトになると、規約を守らない開発チームの場合、誰もが、誰かが行った最後の変更を使ってコードが動くように変更を重ねてしまう。そのため、安定したバージョンのプロジェクトをビルドすることが出来ない。
これに対する対処法が「ウィークリービルド」と「非循環依存関係の原則」
- ウィークリービルド
- 週に一度結合ビルドする日を設けて、それ以外の日は意識せず開発を行う。
- この作業の仕方では、規模が大きくなるにつれてどうしても結合する時間が大きくなっていく。
- 非循環依存関係の原則
- 開発環境をリリース可能なパッケージに分割する。開発者たちがそれぞれを独立して開発できるようにする。
- 注意点:パッケージを循環させない。相互依存させない。
- 循環してしまってると:
- 依存関係逆転の原則を適用して、上位モジュールは下位モジュールが用意するインタフェースを使用する。下位モジュールは、これまで上位モジュール部品を使用してしまっていた箇所をインタフェース化により、実体を持つことがなくなるため上位モジュールへの依存がなくなる。
- 且つ、必要であれば、上位モジュール・下位モジュールが両方とも依存するようなパッケージを新たに追加して、両方が依存するクラスをこの新しいパッケージに移行する。
- パッケージ構造はトップダウン設計で行うのは不可能。クラスの設計もできていないのに、パッケージ設計は難しい。この段階では、何に対して共通な閉鎖性をもたせるのかわからないし、再利用する要素についても気づかない。
結論
- 依存関係逆転の原則適用を意識する。
- パッケージは開発初期から必要以上に分割せず、再利用したい要素がわかってきたり、どの部分のクラスをパッケージ化するかわかってきた時に分割する。
安定依存の原則(SDP)
安定する方向に依存せよ。
変更すること意識して作られたパッケージが、変更が難しいパッケージに依存されるような立場になってはならない。
変更することを意識して作られたはずのパッケージまで変更が難しくなるため。
- 安定性は変更の回数とは直接無関係。
- 安定しているとは容易に動かないことである。
- パッケージ全てが安定している必要はない。変更することができなくなってしまうため。
- 不安定なパッケージと安定したパッケージが混在しているのが理想的なパッケージ構造
- 不安定なパッケージは上位レベルのパッケージにする。下位レベルのパッケージはユーティリティ的な汎用クラスを置く。
- 上位レベルのパッケージが安定してしまうと、設計が固まってしまう=柔軟性がなくなり、改造しにくい状態になる。
結論
- 依存関係逆転の原則を適用する
- 安定性を保ちつつ、変更に耐える柔軟性を持たせるには開放閉鎖の原則を適用する。
- 修正を加えずに拡張することができる状態を作る。=インタフェースを用意する。
安定度・抽象度等価の原則(SAP)
パッケージの抽象度と安定度は同程度でなければならない。
- パッケージを安定させる場合、パッケージはインタフェースで構成されるべきである。
- 拡張できるようにするため
- 不安定なパッケージに具体的なコードを記載する。
パッケージ間の原則結論
- 安定度・抽象度等価の原則と安定依存の原則をまとめると、パッケージ版の依存関係逆転の原則となる。
- 安定依存の原則は依存関係が安定する方向に依存することを主張
- 安定度・抽象度等価の原則は安定するということは抽象化されていることを意味する。
- 安定性と抽象度は測定する事ができる。
安定性
I = Ce / (Ca + Ce)
I:不安定度(0〜1の値を取る。0に近いほど安定したパッケージ。1に近いほど不安定なパッケージとなる。)
Ca:内側に向かう結合度(このパッケージの外にあり、このパッケージの中にあるクラスに依存するクラスの数)
Ce:外側に向かう結合度(このパッケージの中にあり、このパッケージの外にあるクラスに依存するクラスの数)
抽象度
A = Na / Nc
A:抽象度(0〜1の値を取る。0はパッケージが抽象クラスを全く持たないことを意味する。1はパッケージが抽象クラスしか持たないことを意味する)
Na:パッケージ中の抽象クラスの数。抽象クラスとは、最低一つの純粋インタフェースを持ち、インスタンス化出来ないクラスのこと。
Nc:パッケージ中のクラスの数