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

ソフトウェアにおける 複雑さとは何なのか?
ソフトウェアにおける 複雑さとは何なのか?ソフトウェアにおける 複雑さとは何なのか?
ソフトウェアにおける 複雑さとは何なのか?Yoshitaka Kawashima
 
ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門増田 亨
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかKoichiro Matsuoka
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話Koichiro Matsuoka
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなKentaro Matsui
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean ArchitectureAtsushi Nakamura
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースHajime Yanagawa
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南Mikiya Okuno
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところY Watanabe
 
ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』Yoshitaka Kawashima
 
フロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjugフロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjugItsuki Kuroda
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪Takuto Wada
 
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門泰 増田
 
ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門増田 亨
 
DDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くか
DDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くかDDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くか
DDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くかKoichiro Matsuoka
 
データモデリング・テクニック
データモデリング・テクニックデータモデリング・テクニック
データモデリング・テクニックHidekatsu Izuno
 
ドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解するドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解する増田 亨
 
45分間で「ユーザー中心のものづくり」ができるまで詰め込む
45分間で「ユーザー中心のものづくり」ができるまで詰め込む45分間で「ユーザー中心のものづくり」ができるまで詰め込む
45分間で「ユーザー中心のものづくり」ができるまで詰め込むYoshiki Hayama
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!mosa siru
 

What's hot (20)

ソフトウェアにおける 複雑さとは何なのか?
ソフトウェアにおける 複雑さとは何なのか?ソフトウェアにおける 複雑さとは何なのか?
ソフトウェアにおける 複雑さとは何なのか?
 
ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門ドメイン駆動設計 本格入門
ドメイン駆動設計 本格入門
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
 
モジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェースモジュールの凝集度・結合度・インタフェース
モジュールの凝集度・結合度・インタフェース
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
 
ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』ソフトウェア開発における『知の高速道路』
ソフトウェア開発における『知の高速道路』
 
フロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjugフロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjug
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門
 
ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門ドメイン駆動設計のためのオブジェクト指向入門
ドメイン駆動設計のためのオブジェクト指向入門
 
DDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くか
DDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くかDDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くか
DDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くか
 
データモデリング・テクニック
データモデリング・テクニックデータモデリング・テクニック
データモデリング・テクニック
 
ドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解するドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解する
 
45分間で「ユーザー中心のものづくり」ができるまで詰め込む
45分間で「ユーザー中心のものづくり」ができるまで詰め込む45分間で「ユーザー中心のものづくり」ができるまで詰め込む
45分間で「ユーザー中心のものづくり」ができるまで詰め込む
 
マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!マイクロにしすぎた結果がこれだよ!
マイクロにしすぎた結果がこれだよ!
 

More from Yoshitaka Kawashima

ブルックスのいう銀の弾丸とは何か?
ブルックスのいう銀の弾丸とは何か?ブルックスのいう銀の弾丸とは何か?
ブルックスのいう銀の弾丸とは何か?Yoshitaka Kawashima
 
ソフトウェア設計における 意思決定とそのレビューの秘訣
ソフトウェア設計における 意思決定とそのレビューの秘訣ソフトウェア設計における 意思決定とそのレビューの秘訣
ソフトウェア設計における 意思決定とそのレビューの秘訣Yoshitaka Kawashima
 
システムダウンのひみつ
システムダウンのひみつシステムダウンのひみつ
システムダウンのひみつYoshitaka Kawashima
 
アンチフラジャイルの世界
アンチフラジャイルの世界アンチフラジャイルの世界
アンチフラジャイルの世界Yoshitaka Kawashima
 
それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?それはYAGNIか? それとも思考停止か?
それはYAGNIか? それとも思考停止か?Yoshitaka Kawashima
 
思考停止しないアーキテクチャ設計 ➖ JJUG CCC 2018 Fall
思考停止しないアーキテクチャ設計 ➖ JJUG CCC 2018 Fall思考停止しないアーキテクチャ設計 ➖ JJUG CCC 2018 Fall
思考停止しないアーキテクチャ設計 ➖ JJUG CCC 2018 FallYoshitaka Kawashima
 
ウォーターフォールとアジャイルのフェアな比較
ウォーターフォールとアジャイルのフェアな比較ウォーターフォールとアジャイルのフェアな比較
ウォーターフォールとアジャイルのフェアな比較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-E1Yoshitaka Kawashima
 
たとえ日本人同士でも必要な異文化理解力
たとえ日本人同士でも必要な異文化理解力たとえ日本人同士でも必要な異文化理解力
たとえ日本人同士でも必要な異文化理解力Yoshitaka Kawashima
 
SIerにとっての越境 @ DevLOVE 199
SIerにとっての越境 @ DevLOVE 199SIerにとっての越境 @ DevLOVE 199
SIerにとっての越境 @ DevLOVE 199Yoshitaka Kawashima
 
なぜデータモデリングが重要なのか?
なぜデータモデリングが重要なのか?なぜデータモデリングが重要なのか?
なぜデータモデリングが重要なのか?Yoshitaka Kawashima
 
既婚プログラマの時間捻出術
既婚プログラマの時間捻出術既婚プログラマの時間捻出術
既婚プログラマの時間捻出術Yoshitaka Kawashima
 
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのかJavaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのかYoshitaka Kawashima
 

More from Yoshitaka Kawashima (20)

ブルックスのいう銀の弾丸とは何か?
ブルックスのいう銀の弾丸とは何か?ブルックスのいう銀の弾丸とは何か?
ブルックスのいう銀の弾丸とは何か?
 
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
 
既婚プログラマの時間捻出術
既婚プログラマの時間捻出術既婚プログラマの時間捻出術
既婚プログラマの時間捻出術
 
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのかJavaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
 

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