Closed5
設計とかDDDとかデザインパターンとか。覚えたことをメモしていく
集約外の整合性を担保する方法について
例えば、「タスク集約」と「タスクの活動履歴集約」がある。(設計上、別集約にしたとする。)
「①,タスク集約を永続化するrepository」と「②,活動履歴集約を永続化するrepository」はそれぞれ用意されている。
パターンA:ユースケース(アプリケーションサービス内)で①と②の処理を書く。
このパターンのデメリットは別の人が他のユースケースを実装したときに①のみ実装して集約間の整合性を壊してしまう可能性がある。
パターンB:①と②の処理まとめたtaskCreaterという名前のドメインサービス作成してタスクを登録する際はこのドメインサービスを使うとプロダクト内でルール決めする。
ただ、ルールを逸脱するとパターンA同様に整合性は壊れる可能性はある。
パターンC:ドメインイベントを実装する。
①の処理を検知して、②の処理を動かすようにドメインイベントを実装する。整合性を破壊することはないが、実装コストが高い。
ドメインイベントについて:https://codezine.jp/article/detail/10392
DDDの目的
①,機能性を高めること
- 役に立つものを作る
- 「作ったけど使えない」を避ける
②,保守性を高めること
- 長期間開発しても機能拡張が容易でありつづける
- 「技術的負債で開発生産性が低下する」ことを防ぐ
目的を達成するために
- 機能性を高めるために
- モデリングを行う
- 保守性を高めるために
- モデルをそのまま表現する
- エンティティ、リポジトリなどの実装パターン
設計を上手くするには?
いろいろな設計パターンがあるので覚えるの大変。
1つ覚えるとしたらで高凝集、低結合であること
凝集度
- モジュール内の要素同士がどれだけ関連しているか?
- クラスの責務、クラスのメソッドとデータの関連の強さ
- 高い方が良き
プロパティが5つあるのにあるメソッドでは2個しか使われていないのは凝集度が低い。
結合度
- モジュール間の依存度の高さを示す指標
- 依存度が高い→依存先の修正の影響を受けやすくなる
- 低い方が良い(低結合、疎結合)
凝集度が低い(Bad)
- クラスの責務が不明確:このクラスは何をしているクラスなのかを問いかける
- データと全く関係ないメソッドがある
class OperationUtil( // 責務が曖昧なクラス名
private var count: Int
) {
fun increment() { // なんらかの数値をインクリメント
count++
}
fun greet() { // 保持している数値に関係ない挨拶を出力
println("Hello!")
}
}
凝集度が高い
- クラスの責務が明確、単一
- 責務、データとメソッドが関連している
class Counter( // 責務が明確なクラス名
private var count: Int = 0 // クラスの責務と関連が明確なデータ
) {
fun increment() { // クラスの責務、データと関連が明確なメソッド
count++
}
fun getCurrentCount(): Int { // クラスの責務、データと関連が明確なメソッド
return count
}
}
結合度が高い(Bad)
Printer.print() // 0が出力される
Counter.increment() // 何かしらをインクリメント
Printer.print() // 何が出力される?
// ↑ 1が出力された!!
// この振る舞いは外側から推測が難しい
// 依存している
object Printer {
fun print() {
println(Counter.count) // 処理結果がCounterの内部の値に依存している
}
}
object Counter {
var count: Int = 0
fun increment() {
count++
}
}
ドメイン駆動設計との繋がり
-
責務・凝集度の話は設計を考える上で常に重要
-
アーキテクチャのレイヤー化時に考えることは
「レイヤーによる責務の切り分け」
-
エンティティ、リポジトリなどの設計を考えることは
- 「クラスによる責務の切り分け」
-
とにかく責務を考え、凝集度を上げる
-
この原則でかなりの領域をカバーできる
依存関係は循環させてはいけない
プログラムを読みやすく、変更しやすくする方法
- 名前は略語ではなく、普通の名前で行う
- 数行のコードを意味のある単位として「段落」に分ける
- 「目的別の変数」を使う
- 意味のあるコードのmとまりを「メソッド」として独立させる
- 業務の関心事に対応したクラス(ドメインオブジェクト)を作る
このスクラップは2022/12/08にクローズされました