SlideShare a Scribd company logo
強いて言えば「集約どう実装す
るのかな、を考える」な話
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

What's hot

オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ増田 亨
 
ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方
増田 亨
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
yoku0825
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェース
Hajime Yanagawa
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
Takuto Wada
 
ドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみようドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみよう
増田 亨
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
Kohei Tokunaga
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
Takuto Wada
 
世界でいちばんわかりやすいドメイン駆動設計
世界でいちばんわかりやすいドメイン駆動設計世界でいちばんわかりやすいドメイン駆動設計
世界でいちばんわかりやすいドメイン駆動設計
増田 亨
 
オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門
増田 亨
 
ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方
増田 亨
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)
Yoshitaka Kawashima
 
ドメイン駆動設計の正しい歩き方
ドメイン駆動設計の正しい歩き方ドメイン駆動設計の正しい歩き方
ドメイン駆動設計の正しい歩き方
増田 亨
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
Takafumi ONAKA
 
リッチなドメインモデル 名前探し
リッチなドメインモデル 名前探しリッチなドメインモデル 名前探し
リッチなドメインモデル 名前探し
増田 亨
 
コンテナ未経験新人が学ぶコンテナ技術入門
コンテナ未経験新人が学ぶコンテナ技術入門コンテナ未経験新人が学ぶコンテナ技術入門
コンテナ未経験新人が学ぶコンテナ技術入門
Kohei Tokunaga
 
ドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装までドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装まで
増田 亨
 
ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門
増田 亨
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
信之 岩永
 
ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門
増田 亨
 

What's hot (20)

オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
 
ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェース
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
ドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみようドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみよう
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
世界でいちばんわかりやすいドメイン駆動設計
世界でいちばんわかりやすいドメイン駆動設計世界でいちばんわかりやすいドメイン駆動設計
世界でいちばんわかりやすいドメイン駆動設計
 
オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門オブジェクト指向プログラミングのためのモデリング入門
オブジェクト指向プログラミングのためのモデリング入門
 
ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方ドメイン駆動設計のための Spring の上手な使い方
ドメイン駆動設計のための Spring の上手な使い方
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)
 
ドメイン駆動設計の正しい歩き方
ドメイン駆動設計の正しい歩き方ドメイン駆動設計の正しい歩き方
ドメイン駆動設計の正しい歩き方
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
 
リッチなドメインモデル 名前探し
リッチなドメインモデル 名前探しリッチなドメインモデル 名前探し
リッチなドメインモデル 名前探し
 
コンテナ未経験新人が学ぶコンテナ技術入門
コンテナ未経験新人が学ぶコンテナ技術入門コンテナ未経験新人が学ぶコンテナ技術入門
コンテナ未経験新人が学ぶコンテナ技術入門
 
ドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装までドメイン駆動で開発する ラフスケッチから実装まで
ドメイン駆動で開発する ラフスケッチから実装まで
 
ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門
 

More from Yoshitaka Kawashima

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

More from Yoshitaka Kawashima (20)

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

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