Clean Architecture - seiyab/wiki GitHub Wiki
Clean Architecture
Book
Clean Architecture 達人に学ぶソフトウェアの構造と設計
Notation
- 鉤括弧「」は書籍から引用した文や語彙
Notes
第II部 構成要素から始めよ
- 第5章 オブジェクト指向プログラミング
- 依存関係逆転
- 「ビジネスルールは、UIやデータベースとは独立してデプロイできる」
- データベースと独立してビジネスルールをデプロイしたいケースは現実的によくあるのか?(UIはよくある)
- 「データベース」としてテーブルのスキーマ等も含むならビジネスルールの変更と共にデータベースへの変更もデプロイしたい場合が多いのではないか
- そもそもデプロイを高価に見積りすぎではないか。時代と共にデプロイのコストの考え方が変わっている?
- 「システムにあるモジュールを個別にデプロイできるなら、別々のチームが個別に開発できる。」
- これもやはりビジネスルールを書くエンジニアがテーブルのスキーマを書くほうがよいのではないか
- 「ビジネスルールは、UIやデータベースとは独立してデプロイできる」
- 依存関係逆転
第III部 設計の原則
- 第7章 SRP: 単一責任の原則
- 「モジュールはたったひとつのアクターに対して責任を負うべきである」
- すべてのモジュールにこれを当てはめるのは不可能ではないか
- 「変更を望む人たちをひとまとめにしたグループとして扱いたい。」
- このように考えるなら変更する理由とアクターはby definitionで同じになり、意味のない言い換えだ
- 「一番わかりやすいのは、データを関数から切り離すというものだろう。」
- EmployeeDataは依然複数のアクターに責務をもっているようだが、何が解決したというのか
- 「モジュールはたったひとつのアクターに対して責任を負うべきである」
- 第10章 ISP: インターフェイス分離の原則
- 「再コンパイルや再デプロイを強制されるので明らかに有害」
- 再コンパイルや再デプロイは「明らかに有害」というほど高価ではなくなったのではないか
- 「再コンパイルや再デプロイを強制されるので明らかに有害」
第IV部 コンポーネントの原則
- 第14章 コンポーネントの結合
- トップダウンの設計
- 「コンポーネントの依存構造は、システムの論理設計に合わせて育てていくものだ」
- 依存構造を絶対的に制御するため依存関係逆転を推奨する記述が多いが、そもそも達成したい依存構造はシステムの論理設計に合わせて育てていく
- 例の丸い図より、システムの論理設計が優先されると解釈していいはず
- 「コンポーネントの依存構造は、システムの論理設計に合わせて育てていくものだ」
- 安定依存の原則(SDP)
- わかりやすい指針を示しており、目立った欠陥も机上では思いつかないが安定度・抽象度をトラックする仕組みはさほど普及していないのはなぜか
- トップダウンの設計
第V部 アーキテクチャ
- 第15章 アーキテクチャとは?
- 選択肢を残しておく
- 「開発の初期段階でデータベースシステムを選択する必要はない」
- データベースの種類を何も想定しない場合、不可能な方針が出来上がってしまわないか?
- 全く不可能な方針を除けば、論理設計のあとにとりうる選択肢から適切なものを選べるに越したことはない点は同意
- データベースの種類を何も想定しない場合、不可能な方針が出来上がってしまわないか?
- 「開発の初期段階でデータベースシステムを選択する必要はない」
- 選択肢を残しておく
- 第16章 独立性
- 重複
- 「あるデータベースのレコードのデータ構造が、ある画面のデータ構造とよく似ていることに気づくことがある。」
- 重複
- 第17章 バウンダリー: 境界線を引く
- あなたの境界線は何か?いつ境界線を引くのか?
- 「データベースはGUIにとって重要ではないので、その間に境界線を引く。データベースはビジネスルールにとって重要ではないので、その間に境界線を引く。」
- 「結合の悲しい物語」のP社の例はそのように境界線を引き、失敗したのではないか?
- サーバーやドメインオブジェクトを早い段階で分けたことが問題で、境界は引きつつもサーバー等を分けるかの選択を遅延させるのがアーキテクチャの真髄ということか
- 第24章より: 本格的な境界は高価なため、より安価な境界を設けるという選択肢がある
- 本格的な境界を引くかどうかの判断を遅延させるのが優れたアーキテクト
- 「結合の悲しい物語」のP社の例はそのように境界線を引き、失敗したのではないか?
- 「データベースはGUIにとって重要ではないので、その間に境界線を引く。データベースはビジネスルールにとって重要ではないので、その間に境界線を引く。」
- あなたの境界線は何か?いつ境界線を引くのか?
- 第20章 ビジネスルール
- エンティティ
- 「エンティティとは、コンピュータシステムの内部にあるオブジェクトであり、最重要ビジネスデータを操作する最重要ビジネスルールをいくつか含んだものである。」
- Eric Evansのドメイン駆動設計とは異なる定義。
- どちらが正しいというわけではないと思うが、設計界隈で流派によって同じ単語で違うものを指すのはなんとかならないのか
- Eric Evansのドメイン駆動設計とは異なる定義。
- 「エンティティとは、コンピュータシステムの内部にあるオブジェクトであり、最重要ビジネスデータを操作する最重要ビジネスルールをいくつか含んだものである。」
- リクエストとレスポンスのモデル
- 「これらのデータ構造にエンティティオブジェクトへの参照を含めたいと思うかもしれない。(中略)だが、この誘惑に負けてはいけない!」
- 「結合の悲しい物語」のP社はこの誘惑に負けなかった結果、悲しい物語になったといえないのか
- 「それらをまとめることは、閉鎖性共通の原則(CCP)と単一責任の原則(SRP)に違反している。」
- エンティティオブジェクトもSRPが適用され単一アクターに責任を負っているとすればリクエストとレスポンスから独立させなくてよいのではないか
- ここにSRPの理解の手がかりがある気がする
- 解釈例: エンティティオブジェクトには「単一アクターに責任を負っている」は適用しない
- 「これらのデータ構造にエンティティオブジェクトへの参照を含めたいと思うかもしれない。(中略)だが、この誘惑に負けてはいけない!」
- エンティティ
- 第21章 叫ぶアーキテクチャ
- 「最上位レベルのディレクトリ構造と最上位レベルのパッケージのソースファイルは、「ヘルスケアシステム」「会計システム」「在庫管理システム」と叫んでいるだろうか?それとも「Rails」「Spring/Hibernate」「ASP」と叫んでいるだろうか?」
- 同様にディレクトリ構造やパッケージ構成は「クリーンアーキテクチャ」「4つの円」と叫んではいけないはず
- (これはクリーンアーキテクチャに対する批判ではなく、あくまでディレクトリ構造やパッケージ構成を「クリーンアーキテクチャ」には合わせないということ)
- 同様にディレクトリ構造やパッケージ構成は「クリーンアーキテクチャ」「4つの円」と叫んではいけないはず
- 「アーキテクチャのテーマ」
- 「ソフトウェアアプリケーションのアーキテクチャもアプリケーションのユースケースについて叫ぶべきである」
- 上記の言及と併せて、暗に「最上位レベルのディレクトリ構造とパッケージのソースファイルはユースケースについて叫ぶべきである」と言っている?
- 最上位レベルのディレクトリ構造とパッケージのソースファイルがユースケースについて叫んでいればモノリスとマイクロサービスの選択を遅らせたり、移行したりしやすい
- 「ソフトウェアアプリケーションのアーキテクチャもアプリケーションのユースケースについて叫ぶべきである」
- アーキテクチャの目的
- 「優れたアーキテクチャはユースケースを中心にしている」
- これは重要なポイントと思われるが第V部の論調と合わせて自分の中でうまく腹落ち・言語化できていない
- 「優れたアーキテクチャはユースケースを中心にしている」
- 「最上位レベルのディレクトリ構造と最上位レベルのパッケージのソースファイルは、「ヘルスケアシステム」「会計システム」「在庫管理システム」と叫んでいるだろうか?それとも「Rails」「Spring/Hibernate」「ASP」と叫んでいるだろうか?」
- 第22章 クリーンアーキテクチャ
- 「これらのアーキテクチャは、以下の特性を持つシステムを生み出す。」
- 「フレームワーク非依存」
- 下記の場合には強力
- 開発初期段階でフレームワークの決定を遅らせたい場合
- 保守段階で、使用フレームワークが老朽化した場合に非依存を経由して移行
- それ以外の場合、IOさえ分離していれば間接的には依存してもいいのではないか
- フレームワークに直接依存した箇所を限定していれば、変更のコストは依存関係を逆転しているかどうかに関わらなそう
- 下記の場合には強力
- 「テスト可能」
- 依存関係逆転しているかどうかに関わらず、IOと純粋関数を分けていれば問題ないのではないか
- 純粋関数はアーキテクチャに関係なく外部要素なしにテスト可能である
- IOを含む挙動について、スタブを使ったテストで十分と思っていない
- 依存関係逆転しているかどうかに関わらず、IOと純粋関数を分けていれば問題ないのではないか
- 「UI非依存」
- いわゆるMVC程度でも十分に節度があれば満たしているので強調するほどのことと思えない
- 「データベース非依存」
- フレームワーク非依存と同じことが当てはまる
- 「外部エージェント非依存」
- 間接的に外界のインターフェイスについて知っていてもデメリットはなさそう
- 「フレームワーク非依存」
- 「依存性のルールは常に適用される」
- 大事なのは依存性のルールは上記の特性(フレームワーク非依存、テスト可能、UI非依存、データベース非依存、外部エージェント非依存)から導かれるものと思われる
- つまり、上記の特性を(まだ)必要としない場合、依存性のルールやクリーン「アーキテクチャ」を取る必要はない
- アーキテクチャは「選択肢を残しておく」ためのものなので、「クリーンアーキテクチャ」「4つの円」に容易に切り替えられるようにしているならその採用を保留した状態こそがクリーンなアーキテクチャである?
- 「これらのアーキテクチャは、以下の特性を持つシステムを生み出す。」
- 第24章 部分的な境界
- 「問題に直面しているアーキテクトは「確かに違反している。だが、あとで必要になることもある」と考える」
- 直面している「問題」とは?「いま」境界は必要ではないのだから、問題には直面していない
- 和訳の問題かもしれない
- 直面している「問題」とは?「いま」境界は必要ではないのだから、問題には直面していない
- Facade
- 「依存関係の逆転さえも断念する」「再コンパイルが必要になる」「簡単に裏ルートを作れることが想像できる」
- つまり再コンパイルが安価で、裏ルートを防ぐことができるなら依存関係の逆転は断念してもよい
- 現在の計算機資源ではほとんどのプロジェクトは再コンパイルは安価で、デプロイ独立性の方が高価と思われる
- 裏ルートについて、程度の問題とはいえ依存関係を制御しているつもりでも裏ルートを作る誘惑は絶えないので、ツールをつかってCIで防げば良い
- よって、境界さえあれば依存関係の逆転のないシンプルな境界で十分ではないか
- つまり再コンパイルが安価で、裏ルートを防ぐことができるなら依存関係の逆転は断念してもよい
- 「依存関係の逆転さえも断念する」「再コンパイルが必要になる」「簡単に裏ルートを作れることが想像できる」
- まとめ
- 「もちろんほかにも方法はあるだろう。」
- より安価で強固な境界がほしい(願望)
- 「もちろんほかにも方法はあるだろう。」
- 「問題に直面しているアーキテクトは「確かに違反している。だが、あとで必要になることもある」と考える」