参考
Clean Architecture 達人に学ぶソフトウェアの構造と設計 | Robert C.Martin, 角 征典, 高木 正弘 |本 | 通販 | Amazon
前回の記事
第5部
第15章 アーキテクチャとは?
アーキテクトは方針と詳細を分けて考えるというのがなるほどと感心した。システム設計をするときに、データベースとかを気にして考えたりしがちだったけど、ビジネスの方針をしっかり落とし込む必要があってから考えることと理解した。
- アーキテクチャの目的は開発・デプロイ・運用・保守を容易にする
- 方針は詳細に依存してはいけない。
- 方針と詳細を分ける
- 優れたアーキテクトは決定を遅らせることができる
- 遅らせようって話じゃなくて、遅らせても問題ないように設計しようってことだと思う
第16章 独立性
重複
の段落 (162p) に書いてある本物の重複と偶然の重複っていうのがわかりやすい。入門書とかにはよく重複は共通化しろって書かれているからできるだけ共通化するのがいいって思いがちだけど、本当の意味で重複しているのかって考え方が最近わかってきた気がする
- コードの見た目が似ているだけじゃなくて、作った時期とかステークホルダーとかパッケージの構成とかよく見ると全く違ったりする
- 似ているから共通化するのは違う
同じ理由や頻度で変更されるものをまとめましょうって話
-
業務ルールと画面レイアウトは違う理由で変わるよね
- 法律が変わったりして仕様変更が入ることとかあるよね
- レイアウトはリテンション施策とかで変わる
-
クラスとデータベース定義を同じ頻度心構えでリファクタしないよね
-
コードは似てるところで共通化してはいけない
- 今までの経験上、コードが同じところはマジでたまたま
- 同じコードではなくて同じ理由の箇所をまとめる
第17章 バウンダリー境界線を引く
依存関係逆転の原則(DIP)がなぜ必要なのか、どんな時に便利なのかっていうのがわかってたらこの章はさっくり読めると思う
- そうね
依存関係逆転の原則(DIP)で DB と GUI が Business Rules に依存するようにする。 Business Rules は安定したコンポーネントなので、抽象度が高くなり、 DB 、 GUI は不安定なコンポーネントなので抽象度は低くなり、DB、GUI が Business Rules に依存しているので、安定度・抽象度等価の原則(SAP)が適応されている状態になる。 DB 、 GUI 、 Business Rules はそれぞれ違うタイミングやモチベーションで変更されることになるので、単一責任の原則を満たしている。みたいな感じ?
- あってるんじゃない?
- ちなみに、DB、GUI、Business Rules に分けることで単一責任の原則を満たすわけではない。 例えば、 Business Rules の中でも単一責任の原則を満たす努力は必要。
フレームワークのORマッパーを触ってると、自然とデータベースとの紐付けを意識していたので、最近だいぶ意識が変わった
- 厳密にはORマッパーというよりはActiveRecordパターンかな
- Active Record の中の OR マッパー
- データベース単位で考えるんじゃなくて、オブジェクト(概念)を保存するっていう考え方でプログラムを組むのがオブジェクト指向
- DB を中心に考えると手続き型みたいなプログラムになりやすくなる
データベースの操作はフレームワークのORマッパーから入った事が大きいのか、紐付いているものだと思ってたな。ミライト入ってから、今は別物と考えられるようになってきた
- 知識としては得たけど、設計をする際に DB のことを考えずに設計できるかはまた一段ハードルがある
- CRUD を忘れるのは大変
第18章 境界の解剖学
恐怖のモノリス
は何が恐怖なんだ?
-
この章ではモノリスをディスってるわけじゃないから若干タイトルの訳がニュアンスとズレている気がする
-
恐怖のモノリスは 1つの jar ファイルの中の話、デプロイコンポーネントは複数の jar ファイルを組み合わせて作るっていう理解をした
サービスは別のサーバーにデプロイされていてネットワークを通して通信をするもの、ローカルプロセスは同じサーバーの中で別のシステムとして動いているもの(例えば、キューに処理をためて全く別のタイミングで実行するバッチとか)、っていう読み方をした
- ローカルプロセスは並行処理ができるような作りじゃないかな
- 並行処理までは具体的には書かれてないけどね
- 同じサーバー内の話って理解でいいんじゃないかな
- キューに入った処理は別のサーバーから取得して動かすこともあるので、同じサーバーしか拾わないキューって意味ならあってると思う
この章はいまいち理解できなかったけどどういうことが書いてあるの?
- この章は境界の付け方の紹介をしている
- 17章で境界の話をしてるので、一般的にどんなのがあるのかを紹介している
- 境界線って行っても毎回 interface きってソースコードレベルで分離してあるわけじゃないよ、サービス単位で分かれていることもあるよってことが書いてある
- いろんな境界線があるよってこと
- 境界線の具体的な例を紹介している
- 境界線の分離レベルを説明している
恐怖のモノリス
- 1 コンポで中が論理的に分れている
- お約束で分れていると言ってもいい
- 境界線が見えないからと言って境界が存在しないわけじゃあないぞ
-
Helper\ArrayUtil → Domain\User
は普通はしないよね的な
-
- モノリスの中でも、ちゃんとパッケージを考えて DIP とか使っておくと、上手に分業できるぞ
- 越境はただの関数呼び出しなので速いぞ
デプロイコンポーネント
- あるコンポに .jar とかを足す形
- イメージ的には composer でライブラリ持ってきて
巨大な 1 php プロダクトとしてデプロイするのと同じ
- イメージ的には composer でライブラリ持ってきて
- それ以外はモノリスとほぼ同じ
- 越境はただの関数呼び出しなので速い
ローカルプロセス
- ローカルプロセスは OS の通信機能で行われる
- キューって書いてあるけど別に SQS とかは関係ない
- 例えば
PHP ( 下位 ) がファイルを出力 → Shell ( 上位 ) が転送だか吸い込みだかをする
という関係- PHP も Shell もハードコードで
/xxx/out.csv
というパスを持ってはいけない - 実質 Shell が PHP に依存しており、PHP が
/xxx/uc1/out.csv
に場所を変えたら
Shell も修正する必要があるので相互依存になっている- Shell は引数でパスをもらう形にする
- PHP も Shell もハードコードで
- 越境は OS のシステムコールとかで行うが、これはややコストが高いので注意な
- 今までの例と違い物理的に境界が存在するぞ、また物理的に同じ空間で動くぞ
サービス
- レイヤーアーキテクチャのサービスではなく、マイクロサービスの方のサービスのイメージ
- 物理的に同じ場所にいるかどうかはどうでもいい
- 越境はネットワーク経由で行われるので関数呼び出しより遅い、これも注意な
- それ以外は基本的にローカルプロセスと同じ
- 例えば
ContentsService → BillingService
において、
BillingService 側に ContentsService の URL とか入れんなよ- 完了通知とかが欲しければパラメータに RedirectUrl とか入れるとか、
どっかに結果を出して ContentsService からポーリングするとか - OAuth とか考えるとイメージしやすい
- そもそも先にリリースされる上位側が下位側の URL を知り得ないし
- 完了通知とかが欲しければパラメータに RedirectUrl とか入れるとか、
- 例えば
スレッド
- 境界線やデプロイの話ではなく、実行のスケジュールや順序に関するもの
- スレッド : コンポは 1 : 1 でも 1 : n でもいいぞ
第19章 方針とレベル
まとめ
に書かれてあることについて考えてみた
- 単一責任の原則(SRP)、開鎖性共通の原則(CCP)
- 同じ理由で変更されるであろう、文字の読み取り、変換、文字の書き出しは別クラス、または別コンポーネントに分けられれている
- 依存関係逆転の原則(SDP)
- 上位レベルの変換が文字の入出力に依存しないように依存性を逆転している
- 安定度・抽象度等価の原則(SAP)
- 上位レベルの変換コンポーネントは安定していて、抽象度も高い
- ちなみに安定度が高くなると自動的に抽象度も高くなるわけじゃないよ
- SAP は安定度が高くて抽象度が低かったらしんどいよって話
- 安定度高くするなら抽象度も高くしとけよって話
- ちなみに安定度が高くなると自動的に抽象度も高くなるわけじゃないよ
- 上位レベルの変換コンポーネントは安定していて、抽象度も高い
- オープン・クローズドの原則(OCP)
- 変換コンポーネントは、入出力の方法を変更しても影響を受けない(修正に対して閉じている)が、入出力の方法を差し替えることもできる(拡張に対して開いている)
次回