オブジェクト指向設計の原則
「JavaプログラマのためのUML」から,簡単なまとめ(メモ)。
設計品質
設計の臭い
依存関係の管理
複雑に絡み合ったコードにならないように依存関係を管理する。
クラス設計の原則
クラス,モジュール設計における原則。クラス分割,依存関係の指針。
- 単一責務の原則(SPR: Single Responsibility Principle)
- クラスを変更する理由がただ一つになるように,責務を一つにする
- 自分の持つ属性に責任を持つなら,外部の環境に依存してはならない(entity)
- クラスを変更する理由がただ一つになるように,責務を一つにする
- 開放/閉鎖の原則(OCP: Open-Closed Principle)
- 変更せずに簡単に拡張できるようにする
- インタフェースと実現クラスに分割して拡張できる構造にする
- 変更せずに簡単に拡張できるようにする
- リスコフ置換の原則(LSP: Liskov Substitution Principle)
- 利用者が派生クラスを基本クラスとして利用できようにする
- 利用者に派生クラスの型を気にさせてはならない
- ダウンキャスト,instanceofの利用は硬直性,脆弱性,低移植性の臭い
- 利用者が派生クラスを基本クラスとして利用できようにする
- 依存関係の逆転の原則(DIP: Dependency Inversion Principle)
- インタフェースや抽象クラスに依存するようにする
- 高レベルが低レベルに依存してはならない
- 抽象が詳細に依存してはならない。詳細が抽象に依存する
- インタフェースや抽象クラスに依存するようにする
- インタフェース分離の原則(ISP: Interface Segregation Principle)
原則はいつ適用すべきか
- 苦痛を感じた時にはじめて原則を適用すべし
- 最初から全ての原則に適合させようとしてはだめ。必要以上に検討することが増えてしまう
- 何か問題が起こった時に受動的に適用する
- ただし,問題の発見は能動的に行うこと
パッケージ設計の原則
パッケージ,コンポーネント設計における原則。クラスのグルーピング(パッケージ化),パッケージ間の関係に関する指針。
- 公開/再利用等価の原則(REP: Release/Reuse Equivalency Principle)
- 再利用しやすい単位にパッケージを作成する
- 再利用が可能なら公開も可能
- 再利用しやすい単位にパッケージを作成する
- 共通閉鎖の原則(CCP: Common Closure Principle)
- 変更が局所化されるようにパッケージにまとめる(SPRの適用)
- 共通再利用の原則(CRP: Common Reuse Principle)
- (ISPの適用)
- 非循環依存関係の原則(ADP: Acyclic Dependencies Principle)
- 独立して作業できるように,依存関係を循環させない
- 安定した依存関係の原則(SDP: Stable Dependencies Peinciple)
- 安定した(変更されにくい)パッケージに依存する
- 変更されやすいパッケージに依存してはならない
- 安定した(変更されにくい)パッケージに依存する
- 安定した抽象化の原則(SAP: Stable Abstructions Principle)
- 変更せずに簡単に拡張できるようにする(OCPの適用)
まとめ
設計の原則
オブジェクト指向設計の原則は,高凝集度,低結合度により,再利用性,拡張性を満たすための設計指針。
でも,最初からすべての原則に適合するように設計する必要はない。必要になったときに原則に立ち返ればよい。
気づいた時に変更しやすいように,まずはシンプルに設計することが重要。
シンプルな設計
複雑なモジュール,モジュール間の複雑な関係はシステムを硬直化させる。依存関係の管理は,「肝となる関係」と,実行環境やその他の要求に影響される「肝でない関係」を明確にすることが重要だと思う。
クラスはシンプルにして,クラス間の関係は「肝となる関係」を残し,外部環境や仕様変更の対象になり得る「肝でない関係」を分離したい。パッケージは再利用しやすく凝集度の高い単位に分割し,パッケージ間の依存関係を切り離したい。
DI(Dependency Injection)
「依存性の注入」と訳される。
シンプルな設計で分離した部分をDIによって繋ぎ合わせることにより,シンプルで本質的な構造のパッケージになり,再利用性,拡張性も持たせられるはず。
また,分析段階での理解のためのモデルを,今以上に設計にスムーズに繋がるはず。