本書の目次
第1部 イントロダクション
第2部 構成要素から始めよ:プログラミングパラダイム
第3部 設計の原則
第4部 コンポーネントの原則
第5部 アーキテクチャ
第6部 詳細
第1部 イントロダクション
第2部 構成要素から始めよ:プログラミングパラダイム
第3部 設計の原則
第4部 コンポーネントの原則
第5部 アーキテクチャ
第6部 詳細
SOLID原則
SOLIDの原則の目的は、「変更に強く、理解しやすく、多くのシステムで再利用
できる」ソフトウェア構造を作ることである
SOLID原則
単一責任の原則(SRP:Single Responsibility Principle)
モジュールを変更する理由は1つでなければならない
オープン・クローズドの原則 (OCP:Open-Closed Principle)
モジュールは拡張に対して開き、修正に対して閉じていなければならない
リスコフ置換原則 (LSP:Liskov Substitution Principle)
派生型はその基本型と置換可能でなければならない
インターフェース分離の原則 (ISP:Interface Segregation Principle)
クライアントが利用しないメソッドへの依存を強制してはならない
依存性逆転の原則(DIP:Dependency Inversion Principle)
「抽象」は実装の詳細に依存してはならない、実装の詳細が「抽象」に依存すべきである
SOLID原則
過去に別の資料にて解説しているので省略します
https://www.slideshare.net/KiyoshiSuzuki5/fizzbuzz-solid
第1部 イントロダクション
第2部 構成要素から始めよ:プログラミングパラダイム
第3部 設計の原則
第4部 コンポーネントの原則
第5部 アーキテクチャ
第6部 詳細
コンポーネント
コンポーネントとは、デプロイ単位のことであり、システムの一部としてデプロ
イできる最小限のまとまりを指す
コンポーネントの原則
~コンポーネントの凝集性~
コンポーネント(デプロイの単位のこと)の凝集性を高めるには、
・不要なものに依存しないこと
・同じタイミング、同じ理由で変更されるものはひとまとめにすること
が重要である。
コンポーネントの凝集性に関する3つの原則
再利用・リリース等価の原則
閉鎖性共通の原則
全再利用の原則
コンポーネントの凝集性に関する3つの原則
再利用・リリース等価の原則
閉鎖性共通の原則
全再利用の原則
再利用・リリース等価の原則
(REP:The Reuse/Release Equivalence Principle)
「コンポーネントを再利用するには、コンポーネントのリリース単位で行う」と
いう原則
言い換えると「再利用の単位とリリースの単位は等価になる」となる
再利用・リリース等価の原則
(REP:The Reuse/Release Equivalence Principle)
再利用の単位がリリースの単位より大きい場合
凝集性の高いクラスが他のコンポーネントに含まれている
再利用の単位がリリースの単位より小さい場合
コンポーネントに凝集性の低いクラスが含まれている
考え方としては重要なのは「コンポーネントに含まれるクラスは、すべてが再利
用されるか、すべてが再利用できないかのどちらかにすべき」ということ
コンポーネントの凝集性に関する3つの原則
再利用・リリース等価の原則
「コンポーネントを再利用するには、コンポーネントのリリース単位で行う」という原則
閉鎖性共通の原則
全再利用の原則
閉鎖性共通の原則
(CCP:The Common Closure Principle)
「同じ理由、同じタイミングで変更されるクラスをコンポーネントにまとめ、変
更の理由やタイミングが異なるクラスは、別のコンポーネントに分ける」という
原則
これは、単一責任の原則(SRP)をコンポーネント向けに言い換えたもので「コ
ンポーネントを変更する理由が複数あるべきではない」としている
閉鎖性共通の原則
(CCP:The Common Closure Principle)
変更箇所が1つのコンポーネントに閉じていれば、変更後にデプロイする必要が
あるのはそのコンポーネントだけになり、そのコンポーネントに依存していない
コンポーネントは再デプロイは不要となる
考え方としては重要なのは「同じ理由、同じタイミングで変更されることが多い
クラスは1つのコンポーネントにまとめておくべき」ということ
コンポーネントの凝集性に関する3つの原則
再利用・リリース等価の原則
「コンポーネントを再利用するには、コンポーネントのリリース単位で行う」という原則
閉鎖性共通の原則
「同じ理由、同じタイミングで変更されるクラスをコンポーネントにまとめ、変更の理由やタイミ
ングが異なるクラスは、別のコンポーネントに分ける」という原則
全再利用の原則
全再利用の原則
(CRP:The Common Reuse Principle)
「1つのクラスだけを再利用するということはめったになく、複数のクラスと組
み合わせて使われることがほとんどのため、そうしたクラス群は1つのコンポー
ネントにまとめる」という原則
例えばコンテナクラスとそれに対応するイテレータがあるとする、これらは互い
に密結合しているため同じコンポーネントに含めるべきである
全再利用の原則
(CRP:The Common Reuse Principle)
どのクラスを同じコンポーネントにまとめるべきかだけを説いているのではなく、
どのクラスを同じコンポーネントに含めるべきではないかも説いている
コンポーネントAがコンポーネントBを再利用する場合、AはBに依存している。
この時AはBの1クラスのみを再利用したいかもしれないが、Bに依存しているこ
とに代わりはない(Bが変更される時、Aも変更する必要があるかもしれない)
コンポーネントに依存するのであれば、コンポーネントに含まれる全てのクラス
に依存するようにしたい。つまりコンポーネントに含まれるクラスの凝集度は高
くあるべき
(再掲)コンポーネントの凝集性に関する3つの原則
再利用・リリース等価の原則
「コンポーネントを再利用するには、コンポーネントのリリース単位で行う」という原則
閉鎖性共通の原則
「同じ理由、同じタイミングで変更されるクラスをコンポーネントにまとめ、変更の理由やタイミ
ングが異なるクラスは、別のコンポーネントに分ける」という原則
全再利用の原則
「1つのクラスだけを再利用するということはめったになく、複数のクラスと組み合わせて使われ
ることがほとんどのため、そうしたクラス群は1つのコンポーネントにまとめる」という原則
原則の相反関係
これらの原則には相反するところがある
再利用・リリース等価の原則と閉鎖性共通の原則は、どちらもひとつのコンポー
ネントを大きくする方向に働く
全再利用の原則は、ひとつのコンポーネントを小さくする方向に働く
原則の相反関係
ノードは原則を、ノードの対辺は原則を違反した場合の代償を表している
原則の相反関係
アーキテクトはプロジェクトの状態を応じて3つの原則のバランスを取る必要が
ある
コンポーネントの原則
~コンポーネントの結合~
コンポーネントを疎結合にするには、
・循環依存を作らないこと
・抽象度が高くなる方向に依存すること
が重要である
コンポーネントの結合に関する3つの原則
非循環依存関係の原則
安定依存の原則
安定度・抽象度等価の原則
コンポーネントの結合に関する3つの原則
非循環依存関係の原則
安定依存の原則
安定度・抽象度等価の原則
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
「コンポーネントの依存グラフに循環依存があってはならない」という原則
コンポーネント間で循環依存がある場合、コンポーネント単独でのデプロイ、リ
リースができずその部分が温床となりコンポーネント間での不整合が発生する
そのため(アプリケーションが成長するにつれてコンポーネントの依存構造も細
かく変わっていくので)、循環依存が生まれないよう適切に管理する必要がある
なお、コンポーネント間での依存は、具象クラスレベルではなく、インターフェ
ース等の抽象レイヤーで依存すること
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
左記のコンポーネント図につい
て考えてみる
コンポーネントがノードであり、
依存関係が有向エッジである
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
例えばPresentersが変更された場
合、影響を受けるのはViewと
Mainである
これは矢印を逆向きにたどるだ
けでわかる
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
注目すべきは循環関係が含まれ
ていないことである
したがって変更が互いに影響を
及ぼしあう関係がないというこ
とである
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
新たに要件が追加されてEntities
に含まれるクラスがAuthorizerに
あるクラスに依存してしまった
とする
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
この変更によって循環依存が発
生してしまう
この循環依存がいくつかの問題
を引き起こす
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
例えばDatabaseの変更を行う際、
Entitiesとの互換性を維持するこ
とを考えれば良かったが、循環
依存しているためDatabaseの変
更を行うのが難しくなった
事実上ひとつの巨大なコンポー
ネントになったようなものだ
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
この問題の解決策は二つ存在す
る
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
一つ目ははDIPによる解決法
左記はコンポーネント図の
EntitiesとAuthorizerの関係を詳細
に記述したものである
外側の四角がコンポーネント、
内側の四角がクラスを表してい
る
Entities Authorizer
User Permissions
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
UserクラスがPermissionsクラス
に要求するメソッドを持つイン
ターフェースを作る
これによってEntitiesとAuthorizer
クラスの依存関係が逆転する
Entities Authorizer
User PermissionsIPermissions
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
したがって循環依存が排除され
る
非循環依存関係の原則
(ADP:Acyclic Dependencies Principle)
2つ目はEntitiesとAuthorizerの両
方が依存するクラスを新しいコ
ンポーネントに移動する
これにより循環依存が排除され
る
コンポーネントの結合に関する3つの原則
非循環依存関係の原則
「コンポーネントの依存グラフに循環依存があってはならない」という原則
安定依存の原則
安定度・抽象度等価の原則
安定依存の原則
(SDP:Stable Dependencies Principle)
「安定度の高い方向に依存すること」という原則
「安定度の高い」とは、変更がしづらいということ。多数のコンポーネントから
依存されたコンポーネントは(変更することの影響が大きいので)変更しづらい、
そのためこういったコンポーネントは安定度が高いと考えらえれる
安定依存の原則
(SDP:Stable Dependencies Principle)
コンポーネントの安定度を測定するひとつの方法
がコンポーネントのファンイン、ファンアウトか
ら求める手法である
<ファンイン>
コンポーネント内のクラスに依存している外部コ
ンポーネントのクラス数
<ファンアウト>
コンポーネント内のクラスが依存している外部コ
ンポーネントのクラス数
<不安定さ>
I = ファンアウト/(ファンイン+ファンアウト)
I=0が最も安定度が高く、I=1が安定度が最も低い
安定依存の原則
(SDP:Stable Dependencies Principle)
例えばコンポーネントCcの安定度を算出する
Ccの外部にある3つのクラスがCcの内部のクラス
に依存しているためファンインは3である
一方、Ccの内部のクラスが依存するCcの外部のク
ラスは1つなのでファンアウトは1である
従ってCcの不安定さIは1/4である
安定依存の原則
(SDP:Stable Dependencies Principle)
各コンポーネントの不安定さIを算出すると下記の
ようになる
CaのI = 0
CbのI = 0
CcのI = 1/4
CdのI = 1
※I = 0となるコンポーネントを独立コンポーネン
ト、I = 1となるコンポーネントを従属コンポーネ
ントと呼ぶ
安定依存の原則
(SDP:Stable Dependencies Principle)
安定依存の原則(「安定度の高い方向に依存する
こと」という原則)を遵守しているか確認する
Ca(I=0)はCc(I=1/4)に依存している
Cb(I=0)はCc(I=1/4)に依存している
Cc(I=1/4)はCd(I=1)に依存している
Cd(I=1)はどこにも依存していない
従って安定依存の原則が遵守されていることが分
かる
コンポーネントの結合に関する3つの原則
非循環依存関係の原則
「コンポーネントの依存グラフに循環依存があってはならない」という原則
安定依存の原則
「安定度の高い方向に依存すること」という原則
安定度・抽象度等価の原則
安定度・抽象度等価の原則
(SAP:Stable Absstractions Principle)
「コンポーネントの抽象度は、その安定度と同程度でなければならない」という
原則
つまり、安定度の高いコンポーネントは抽象度も高くあるべきで、安定度の高さ
が拡張の妨げになってはいけない
一方、安定度が低いことによってその内部の具体的なコードが変更しやすくなる
ため、安定度の低いコンポーネントはより具体的であるべきである
安定度・抽象度等価の原則
(SAP:Stable Absstractions Principle)
コンポーネントの抽象度を表す指標Aを以下のように定める
Nc:コンポーネント内のクラスの総数
Na:コンポーネント内の抽象クラスとインターフェースの総数
A:抽象度。A = Na / Nc
安定度・抽象度等価の原則
(SAP:Stable Absstractions Principle)
抽象度Aと不安定さIの関係をグラフで
表すと左記のようになる
(0, 1)から(1, 0)に伸びる斜線が抽
象度と安定度が一致している理想を表
す
A(抽象度)
I(不安定さ)
(0, 0)
(0, 1) (1, 1)
(1, 0)
苦痛ゾー
ン
無駄ゾー
ン
安定度・抽象度等価の原則
(SAP:Stable Absstractions Principle)
<苦痛ゾーン>
抽象度が低く安定度も低い(抽象度が低いにも関
わらず多くのコンポーネントから依存されてい
る)
データベーススキーマやStringコンポーネントが該
当する。これらは抽象度が低いにも関わらず多く
の場所から依存されているため多少の変更でも大
きな苦痛を伴う
ただしStringコンポーネントは変動性が低い(変更
されにくい)、こういった変動性が低いコンポー
ネントは苦痛ゾーンに存在しても問題ない
A(抽象度)
I(不安定さ)
(0, 0)
(0, 1) (1, 1)
(1, 0)
苦痛ゾー
ン
無駄ゾー
ン
安定度・抽象度等価の原則
(SAP:Stable Absstractions Principle)
<無駄ゾーン>
抽象度が高く安定度も高い(抽象度が高いにも関
わらず、それに依存するコンポーネントが存在し
ない)
例えば実装が一つもないまま放置された抽象クラ
スや、そもそも使われていないクラスなどが該当
する
無駄な要素がある状態は好ましくない
A(抽象度)
I(不安定さ)
(0, 0)
(0, 1) (1, 1)
(1, 0)
苦痛ゾー
ン
無駄ゾー
ン
コンポーネントの結合に関する3つの原則(再掲)
非循環依存関係の原則
「コンポーネントの依存グラフに循環依存があってはならない」という原則
安定依存の原則
「安定度の高い方向に依存すること」という原則
安定度・抽象度等価の原則
「コンポーネントの抽象度は、その安定度と同程度でなければならない」という原則
第1部 イントロダクション
第2部 構成要素から始めよ:プログラミングパラダイム
第3部 設計の原則
第4部 コンポーネントの原則
第5部 アーキテクチャ
第6部 詳細
第5部以降は次回に回します

CleanArchitecture 第4部 「コンポーネントの原則」