参考
Clean Architecture 達人に学ぶソフトウェアの構造と設計 | Robert C.Martin, 角 征典, 高木 正弘 |本 | 通販 | Amazon
前回の記事
【ミライトデザイン社内勉強会#25】Clean Architecture 輪読会 「第1部:イントロダクション」「第2部:プログラミングパラダイム」 - Qiita
第3部 設計の原則
Clean Architecture 達人に学ぶソフトウェアの構造と設計 | Robert C.Martin, 角 征典, 高木 正弘 |本 | 通販 | Amazon
SRPとOCPの時間は筆者が参加できなかったので記述が薄いよ
第7章 SRP: 単一責任の原則
-
単一責任の原則が守られてない時のイメージ
-
本の中の
モジュールはたったひとつのアクターに対して責任を負うべきである
っていう説明がわかりやすい -
デプロイとかするときに辛いとこれを破ってるってパターンが多いと思う
- 「違う案件のチームのデプロイが衝突した」ってことは、単一責任になってない
- ( コードレベルかモジュールレベルかコンポーネントレベルかはおいといて )
- 「違う案件のチームのデプロイが衝突した」ってことは、単一責任になってない
第8章 OCP: オープン・クローズドの原則
- 個人的には、本の中にも
これこそが、我々がソフトウェアアーキテクチャを学ぶ根本的な理由だ
とあるように他の原則もOCPを実現したいがためにあるんだと思ってる
第9章 LSP: リスコフの置換原則
具象じゃなくて抽象に依存しろって話?
- 抽象に依存してるから置換できるよって話かな?
- 親子関係があるものを作る時に、どんな場面でも子供に置き換えられるように作れって話で、抽象がどうかはそこまで関係ないかな
- 方法として抽象に依存しているってだけ
LSPを満たしていると派生元に置き換えることができるとあるが、これってインターフェースの特徴じゃないの?
- 継承も抽象クラスも作れるし、インターフェースとかはどうやって実装するかって話でこの原則はあくまでも親子関係があるクラスは差し替え可能にしとけよって話
- 四角形の例がまさにその通りな気がする
- 継承したものは親の性質を全て満たしているはずなので、置換できるはず
親クラスでのpriceは税抜、子クラスでのpriceは税込みとなっていた場合に原則違反となる。みたいな話?
-
これはただのバグ
-
置換できた上で、それが仕様にあっているかは別の問題かな
リスコフの置換原則を守らないと結果的にOCPの原則に違反するから守らないといけないの?
-
あんまり他の原則と比べて考えない方がいいかな
- 結果としては置き換え可能じゃないと、OCPも満たせなくなるけど
-
破るとif文がいっぱい出てくるよってイメージ
- 特定の子供の時だけ、処理をかえないといけない場合は保守が辛いよ
LSP の S は Substitute の S
- 馴染みがない単語だけど、sed で使う
s/
とかが substitute の s だと思う - Ruby の
.sub()
もそうだと思う、なので案外潜んでいる
第10章 ISP: インターフェース分離の原則
これも抽象に依存しろって話に見える
- 抽象に依存した上で、分離しろって話
- 使っていないインターフェースに依存してると、関係のないものの変更を受けることになるので、関係ないなら知らない方がいい
図10-2
でいうところの OPS クラスのような複数のインターフェイスをimplementsしているクラスはすでに、単一責任の原則に反してそうなんだけどどうなんだろう?
- 必ずしもそうじゃないことも多い
- アクターは一緒だけど、処理は違うみたいなこともある
- バラバラなインターフェースを3つ積んでたら、違反してそうだけど、この例からじゃわからない
- フレームワークのコアクラスとかをみると複数のインターフェースをimplementsしているクラスはよくある
凝集度が低い場合には分離ができるって判断基準になりそう(他にどういうのがあるかな)
- 凝集度はあんまし関係ないかも
- 凝集度は自分のクラスの中で使わない変数があるとかそういう話
- ほんとだったから分けても良いものが一緒になってるのが凝集度が低い状態
- インターフェースを使う側(クライアントコード)で、使わないメソッドがあるなら、そのメソッドを別のインターフェースに分けるみたいな
- クライアントコードでsaveメソッドとupdateメソッドが使われるかは別なので、これだけでは判断し辛いかも
- 概念が別れているものが入っていると、分けた方がいい例が多い
- インターフェース単体をみて判断できるものが多い
動的型付け言語の方が疎結合にしやすいというのが、あんまりピンとこない
-
import
が実行時評価だから再コンパイルされないのはそうだけど、論理的には依存しているので安定度の考え方は言語によって変わらないと感じる - Rubyみたいにダックタイプがあれば、importはしなくていい(型をあらかじめ指定しなくていい)みたいな意味なのかな?
- 動的型付けの方が手っ取り早く疎結合にできるけど、静的型付け言語の方がちゃんとやれば疎結合にしやすいイメージ
違反コード思いついたと思ったけど、これどっちかっていうと LSP 違反か...??
java のコレクションってホントに... 😇
List<Integer> ns = Arrays.asList(1, 2, 3);
ns.add(5);
System.out.println(ns);
- できることが少ない方(ArrayList)を、できることが多いも(List)ので受け取っている
- Listはaddを持ってるからコンパイルは通るけど、ArrayListは呼ぶと例外が出る様になっているので実行時に落ちる
第11章 DIP: 依存関係逆転の原則
依存関係逆転の原則は、ドメインがシステムの都合(DB)とかに影響されないように抽象に依存するって話の認識。
-
DIPしたかったら抽象にするしかないよなって話
-
逆転させるときのやり方で抽象を使っている
-
抽象に依存したからってDIPが満たせるわけじゃないよ
- 上位のレイアが下位のレイアのインターフェースに依存しちゃってる場合とか
-
ドメインとシステム都合っていうのはあくまで一例
- それを使ってドメインを分離している
- あくまで、依存の流れを変えたい
- 下位レイヤ→上位レイヤにしたい時(ドメインうんぬんは一旦関係ない)
DIPは具象が抽象を参照することで、依存の向きが下位レイヤ→上位レイヤとなり柔軟なシステムになるよって原則の認識(変更が容易になる)
- 例えば、一年に一回変更があるクラスが、毎日変更されるクラスに依存してたら困る
- 一年に一回の変更でいいクラスが、インターフェース(ルール)を決めて、毎日変更されるクラスがそれを守って実装する
- 結果、依存性が逆転する。ってのをDIPではやりたい
次回
【ミライトデザイン社内勉強会#27】Clean Architecture 輪読会 「第4部:コンポーネントの原則」 - Qiita