SlideShare a Scribd company logo
4
Most read
10
Most read
16
Most read
強いて言えば「集約どう実装す
るのかな、を考える」な話
kawasima
アーキ部 #13
強いて言えば「集約どう実装するのかな、を考える」な話
CartにCartItemを追加する
Add Cart
Add Cart
Add Cart
1
1
1
{
“productId”: “mikan”,
“quantity”: 1
}
API Endpoint
AddCartItemUseCase
{
“userId”: “kawasima”,
“productId”: “mikan”,
“quantity”: 1
}
ユースケースシナリオ
1. ユーザのカートが存在することを確認する。
2. productIdが実在する商品かつ販売中の商品であることを確認する。
2a. 販売中でない場合
2a1. その旨をユーザに通知して終了
3. カートに商品と数量を追加する
3a. 既にカートの中に同一の商品があれば数量を足し合わせる
3a カート内の商品の数量が100を超える場合
その旨をユーザに通知して終了
4. カートの内容を保存する
高々100件くらい全部メモリにロード
しちゃえばいいじゃないか…
じゃあその件数上限が、数十万件に
なったら?
https://github.com/kawasima/revisiting-domain-model/blob/main/src/victim_performance.ts
ドメインを中心に据えて、外界と
のやり取りをエッジに置く設計
カート
カートアイテム
スタジアム
座席
列
番号
座席ランク
商品ID
数量
1 *
ユースケース: あるカートアイテム
の数量を変更する
ユースケース: ある座席のランクを
変更する
制約: 同一ランクの座席数上限はス
タジアム毎に決まりがある
制約: カート全体に入れることがで
きる商品数量は100個まで
1 1..*
※10万席あるスタジアムもある
A B
ドメインモデルのトリレンマ
https://enterprisecraftsmanship.com/posts/domain-model-purity-completeness/
純粋性
完全性
性能
完全性を犠牲にドメインレイヤの外
にドメインロジックを実装する
純粋を犠牲にドメインレイヤに外界
とのやり取りのコードをインジェク
トする。
全ての外界とのやり取りを業務ロ
ジックの端に追いやる。
ドメインロジックが全てドメイン層で実装されること
ドメイン層が他のレイヤに
依存しないこと
それぞれのメリット
テスト容易性と移植性が向上する。
完全性
性能
純粋性
高凝集が達成され、コードの変更容易性が向
上する。
速ければ速いほどCVRが上がる。
完全性+性能
カートアイテム追加のた
めに、わざわざ全部の
カートアイテムをロード
する必要はない。
(そもそも性能面を考える
と出来ない)
でも、参照系(カートの中
身表示ページ)では必要…
ReadとWriteを分ける
(遅延ロードを使うという
手もある…が事故多し)
https://github.com/kawasima/revisiting-domain-model/blob/main/src/victim_purity.ts
純粋性+性能
ドメインオブジェクトに、DBア
クセスを含めないようにする。
結果として、今回のユースケー
スでは、ドメインロジックはな
くなり、全てがユースケース層
に染み出す結果に。
https://github.com/kawasima/revisiting-domain-model/blob/main/src/victim_completeness.ts
DDDトリレンマ: それぞれの選択に潜む悪魔
純粋性+完全性
純粋性+性能
完全性+性能
理想論の悪魔
👿 「純粋かつ完全なるドメイン …美しい」
ただし、遅くて使い物にならないけどな
アンチドメインモデル貧血症 の悪魔
👿 「業務ロジックを発見し、濃いドメインモデルができたで〜」
こんな簡単なものに、こんな複雑な仕掛けが必要なの ?
テスタビリティの悪魔
👿 「ドメイン層がピュアでテストしやすぅ〜」
ドメイン層スッカスカでテストが簡単に書けても、ユースケースからテスト通
さんと、ほとんど品質保証の意味をなさない。
どれも追求しすぎると、悪魔に取り憑かれる
銀の弾丸(美しい解決策)はなさそう
テスト容易性と移植性が向上する。
完全性
純粋性
高凝集が達成され、コードの変更容易性が向上する。
とはいえ、性能は保った状態で、「完全性」と「純粋性」のメリット、を
少しずつでも享受できる手立てはないものか…?
所詮、どちらも直接的に顧客に不利益をもたらす品質特性ではないので、Take It Easy
高凝集について
完全性を取りに行って、ドメインモデルが貧血症を起こさないように設計出来た
ら「高凝集」になる?
→ 世の中にあるドメインモデルの例たちは、ちょっと怪しい。
https://scrapbox.io/kawasima/ドメインモデル貧血症
「複雑さ」がポイント
実際に高凝集目指すならば、複雑さを紐解かなければならない
異なる振る舞いをするものは、異なるものとしてみなす
(まぁ、ふつうはそれを型で実装する)
(ドメインサービスの乱用による)ドメイン貧血症
class User {
public exists(user: User): bool {
// 重複チェック
}
}
class UserService {
public exists(user: User): bool {
// 重複チェック
}
}
Userに自分自身の存在確認メソッドを持た
せるのは不自然。
なので、そういう場合にだけドメインサービ
スを作るといいよ。
ドメインサービスの乱用は、ドメインモデル
貧血症を招くのでほどほどに …
『ドメイン駆動設計入門』より
どこに定義するかより、同じでないものを区別することが先決では?
内包されている「複雑さ」(異なる概念)を型で表現するのが重要
重複しているかもし
れないユーザ
重複していないことが
保証されているユーザ
両者は別の概念
(なぜなら定義される
振る舞いが異なる)
// ユーザの重複チェック ; 「重複しているかもしれないユーザ」にしか適用されない
type existsUser = MaybeDuplicatedUser -> UniqueUser
// ユーザの登録; 「重複していないことが保証されているユーザ」にしか適用されない
type registerUser = UniqueUser -> RegisteredUser
Parse don’t validate
Parse don’t validate
https://sporto.github.io/elm-patterns/basic/parse-dont-validate.html
Origin: https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/
type alias UserInput =
{ name: Maybe String
, age: Maby Int
}
isValidUser : UserInput -> Bool
このようなバリデータだけが用意されていると、UserInput型のデータはバリデートが済
んでも、invalidな値を保持している可能性がある。
実際に、これが元で過去いくつもの脆弱性が発生している。
http://langsec.org/papers/langsec-cwes-secdev2016.pdf
type alias UserInput =
{ name: Maybe String
, age: Maby Int
}
type alias ValidUser =
{ name: String
, age: Int
}
validateUser : UserInput -> Result String ValidUser
バリデート済みであることを型によって保証する。
なので、バリデートはBooleanを返すのではなく、バリデーション済みの型にParseして返す
Type Safety Back and Forth
https://www.parsonsmatt.org/2017/10/11/type_safety_back_and_forth.html
失敗可能性を後ろへ
失敗可能性を前へ (こっちの方がいいよね、という話)
入力を型によって制約保証す
る。
Domain Modeling Made Functional
https://www.slideshare.net/ScottWlaschin/domain-modeling-made-functional-devternity-2022
Domain Expertとの対話を繰り返しながら、違うものを見つけていく
これで先の
AddCartItemUseCase
を実装してみよう
https://github.com/kawasima/revisiting-domain-model/blob/main/src/made_functional.ts
「複雑さ」を型で表現できれば、それ
を紡ぎ合わせるのがビジネスロジック
になる。
まとめ
● トリレンマにしたがい完全+純粋、純粋+性能、完全+性能な手段が考えら
れる。
● 1つのやり方に執着しすぎると、悪魔に取り憑かれるので注意しよう。
● そもそもドメインにまつわる「複雑さ」は明らかにできているのか?

More Related Content

PDF
イミュータブルデータモデル(世代編)
PDF
イミュータブルデータモデル(入門編)
PDF
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
PPTX
概念モデリング再入門 + DDD
PDF
ドメイン駆動設計のためのオブジェクト指向入門
PDF
オブジェクト指向の設計と実装の学び方のコツ
PDF
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
PPTX
データモデリング・テクニック
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(入門編)
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
概念モデリング再入門 + DDD
ドメイン駆動設計のためのオブジェクト指向入門
オブジェクト指向の設計と実装の学び方のコツ
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
データモデリング・テクニック

What's hot (20)

PDF
Tackling Complexity
PDF
イミュータブルデータモデルの極意
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
PDF
ソフトウェアにおける 複雑さとは何なのか?
PDF
ドメイン駆動設計のための Spring の上手な使い方
KEY
やはりお前らのMVCは間違っている
PDF
ドメイン駆動設計サンプルコードの徹底解説
PDF
Where狙いのキー、order by狙いのキー
PDF
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
PDF
ドメインオブジェクトの見つけ方・作り方・育て方
PDF
ドメイン駆動設計 ( DDD ) をやってみよう
PDF
組織にテストを書く文化を根付かせる戦略と戦術
PDF
Pythonによる黒魔術入門
PDF
マイクロにしすぎた結果がこれだよ!
PDF
Python におけるドメイン駆動設計(戦術面)の勘どころ
PDF
シリコンバレーの「何が」凄いのか
PPTX
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
PDF
ドメイン駆動設計 本格入門
PDF
Domain Modeling Made Functional (DevTernity 2022)
PDF
ドメイン駆動設計 基本を理解する
Tackling Complexity
イミュータブルデータモデルの極意
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
ソフトウェアにおける 複雑さとは何なのか?
ドメイン駆動設計のための Spring の上手な使い方
やはりお前らのMVCは間違っている
ドメイン駆動設計サンプルコードの徹底解説
Where狙いのキー、order by狙いのキー
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
ドメインオブジェクトの見つけ方・作り方・育て方
ドメイン駆動設計 ( DDD ) をやってみよう
組織にテストを書く文化を根付かせる戦略と戦術
Pythonによる黒魔術入門
マイクロにしすぎた結果がこれだよ!
Python におけるドメイン駆動設計(戦術面)の勘どころ
シリコンバレーの「何が」凄いのか
今こそ知りたいSpring Batch(Spring Fest 2020講演資料)
ドメイン駆動設計 本格入門
Domain Modeling Made Functional (DevTernity 2022)
ドメイン駆動設計 基本を理解する
Ad

More from Yoshitaka Kawashima (20)

PDF
Grokking Simplicity探訪
PDF
ブルックスのいう銀の弾丸とは何か?
PDF
Are Design Patterns Dead?
PDF
ソフトウェア開発における『知の高速道路』
PDF
ソフトウェア設計における 意思決定とそのレビューの秘訣
PDF
本番障害に至る病
PDF
システムダウンのひみつ
PDF
Mavenの真実とウソ
PDF
アンチフラジャイルの世界
PDF
Atomic Architecture
PDF
それはYAGNIか? それとも思考停止か?
PDF
思考停止しないアーキテクチャ設計 ➖ JJUG CCC 2018 Fall
PDF
ウォーターフォールとアジャイルのフェアな比較
PDF
How to find tech books
PDF
Antifragile Java - Java Day Tokyo 2017 D1-E1
PDF
たとえ日本人同士でも必要な異文化理解力
PDF
SIerにとっての越境 @ DevLOVE 199
PDF
なぜデータモデリングが重要なのか?
PDF
Antifragile Clojure
PDF
Boilerplate vs Magic
Grokking Simplicity探訪
ブルックスのいう銀の弾丸とは何か?
Are Design Patterns Dead?
ソフトウェア開発における『知の高速道路』
ソフトウェア設計における 意思決定とそのレビューの秘訣
本番障害に至る病
システムダウンのひみつ
Mavenの真実とウソ
アンチフラジャイルの世界
Atomic Architecture
それはYAGNIか? それとも思考停止か?
思考停止しないアーキテクチャ設計 ➖ JJUG CCC 2018 Fall
ウォーターフォールとアジャイルのフェアな比較
How to find tech books
Antifragile Java - Java Day Tokyo 2017 D1-E1
たとえ日本人同士でも必要な異文化理解力
SIerにとっての越境 @ DevLOVE 199
なぜデータモデリングが重要なのか?
Antifragile Clojure
Boilerplate vs Magic
Ad

強いて言えば「集約どう実装するのかな、を考える」な話