Clean Architecture 達人に学ぶソフトウェアの構造と設計
読書メモ
第1章 設計とアーキテクチャ
優れたアーキテクチャとは、それが目的地ではなく旅路であること、凍結された成果物ではなく進行形の探索プロセスである
第2章 2つの価値のお話
変更の難易度は、変更の形状ではなく、変更のスコープに比例しなければいけない。
第3章 パラダイムの概要
オブジェクト指向
コンポーネントの分離
構造化プログラミング
機能
関数型プログラミング
データ管理
第4章 構造化プログラミング
プログラミングは数学ではなく反証可能性のある科学
第5章 オブジェクト指向プログラミング
OOとは「ポリモーフィズムを使用することで、システムにあるすべてのソースコードの依存関係を絶対的に制御する能力」である。
第6章 関数型プログラミング
イベントソーシング
状態ではなく取引(トランザクション)を保存するという戦略である。
更新を繰り返すのではなく、ログを保存する
まとめ
構造化プログラミングは、直接的な制御の移行に起立を課すものである。
オブジェクト指向プログラミングは、間接的な制御の移行に規律を課すものである。
関数型プログラミングは、代入に規律を課すものである。
第7章 単一責任の原則
SRP: Single Responsibility Principle
関数は一つのことをせよ、という原則ではない
モジュールは一つのアクターに対して責務を負うべき、という原則
変更をする理由に注目する
アクターの異なるコードは分離すべき
データを関数から切り離す
そのときにFacadeパターンが活用できる
第8章 オープン・クローズドの原則
OCP: Open-Closed Principle
拡張に対して開いていて、修正に対して閉じていなければならない
コンポーネントAがコンポーネントBの変更から保護されるべきならば、コンポーネントBからコンポーネントAに依存すべきである
下位レベルのコンポーネントへの変更が上位レベルのコンポーネントに影響を及ぼさないようにする
第9章 リスコフの置換原則
LSP: Liskov Substitution Principle
インターフェースと実装に関するソフトウェア設計の原則
インターフェースが置換可能
アーキテクチャのレベルで違反すると特別な処理が増えることになる
第10章 インターフェイス分離の原則
ISP: Interface Segregation Principle
使っていないものへの依存を回避すべき
第11章 依存関係逆転の原則
DIP: Dependency Inversion Principle
変化しやすい具象クラスを参照/継承しない
具象関数をオーバーライドしない
具象が抽象に依存するように実装し、使うときは抽象を使う
抽象によって具象を隠す
処理の流れと、依存の流れは逆であることに注意
第12章 コンポーネント
コンポーネントとはデプロイの単位のこと
システムの一部としてデプロイできる最小限のまとまりを指す
e.g., Java -> jarファイル, Ruby -> gemファイル, .NET -> DLL, コンパイル型言語 -> バイナリファイル、インタプリタ型言語 -> ソースファイル
よくできたコンポーネントは個別にデプロイ出来るので、個別に開発も出来る
動的にリンクされたファイルを実行時にプラグイン出来ることがアーキテクチャにおけるソフトウェアコンポーネント
第13章 コンポーネントの凝集性
原則
再利用・リリース等価の原則
再利用の単位とリリースの単位は等価になる
再利用性のためのグループ化
閉鎖性共通の原則
同じ理由、同じタイミングで変更されるクラスをコンポーネントにまとめること
変更の理由やタイミングが異なるクラスは別のコンポーネントに分けること
コンポーネント版の単一責任の原則
保守性のためのグループ化
全再利用の原則
コンポーネントのユーザーに対して、実際には使わないものへの依存を強要してはいけない
みつ結合していないクラスを同じコンポーネントにまとめるべきではない
インターフェース分離の原則の一般化
不要なリリース作業を減らすための分割
これらの原則には相反するところがあり、バランスを取るのが大事
開発時の利便性と再利用性のトレードオフ
第14章 コンポーネントの結合
非循環依存関係の原則
依存が循環してはいけない
安定依存の原則
自分よりも安定したコンポーネントに依存せよ
安定度・抽象度等価の原則
安定度の高いコンポーネントは拡張しやすいように抽象度も高くせよ
安定依存の原則と安定度・抽象度等価の原則の組み合わせがコンポーネント版の依存関係逆転の原則に相当する
第20章 ビジネスルール
エンティティ
コンピュータシステムの内部にあるオブジェクトであり、最重要ビジネスデータを操作する最重要ビジネスルールをいくつか含んだものである。
プレインオールドオブジェクト
ユースケース
自動化されたシステムを使用する方法を記述したものである。
エンティティ使い、エンティティ同士の関係を表現したアプリケーション固有のビジネスルール
第25章 レイヤーと境界
境界を完全に構築しようとすると、コストが高くつくことを認識する必要がある。
第26章 メインコンポーネント
Mainコンポーネントは、究極的な詳細(最下位レベルの方針)である。
Mainはクリーンアーキテクチャの円の最も外側にある下位レベルのモジュールであることだ。
全てを知っている
なので、同心円の最も外側に位置する
第27章 サービス:あらゆる存在
サービスがシステムのアーキテクチャの境界を定義しているのではなく、サービス内部のコンポーネントがそれを定義しているのである。
アーキテクチャは要素の通信や実行の物理的な仕組みで定義されるわけではない。
第28章 テスト境界
テストはシステムの一部
変化しやすいものに依存しない
テストも同じ
時間が経つにつれて、テストは具体的かつ個別化する傾向があるからだ。それとは対照的に、プロダクションコードは抽象的かつ一般化する傾向がある。
第29章 クリーン組み込みアーキテクチャ
ファームウェアは、格納されている場所ではなく、それが何に依存しているのか、ハードウェアの進化に合わせてどれだけ変化しにくいかで決まる。
ファームウェアはハードウェアに依存するソフトウェア、と考えるとしっくりきた
Hardware Abstruction Layer, Processor Abstruction Layer, OS Abstruction Layer を導入して分離する
第33章 事例:動画販売サイト
システムの最初のアーキテクチャを決めるための第一歩は、アクターとユースケースを見つけることだ。
第34章 書き残したこと
モジュールシステムをうまく活用すれば、publicとpublishedをきちんと区別できるようになる。
いくらうまい設計をしても、その実装方法の複雑さを考慮しなければ、あっという間に設計が崩れてしまう。
元ネタになった原著者のブログ記事