フットサルNOW DDDケーススタディ
CASE STUDY 01
フットサルNOWでDDDを検証する
募集・参加申請・承認を題材に、ガイドラインの推奨が実装でも機能するか確かめます。完成例として見せるのではなく、実装で分かったことと未検証の仮説を区別して記録します。
START HERE · ドメインを理解する
参加申請から承認までの具体例を使って、参加募集の業務を理解する
DDDに「必ずこの作業から始める」という固定手順はありません。フットサルNOWでは、まず参加募集を題材に、利用者と開発者が具体例を会話します。その過程で、業務の言葉、判断、ルール、まだ分からないことを見つけ、理解に合わせてドメインモデルとコードを繰り返し更新します。
この機能で実現したいこと
今日フットサルをしたい人が、参加可能な募集を見つけ、主催者の承認を得られるようにする。
最初に扱うシナリオ
参加者が募集中の募集へ申請し、主催者が定員を確認して承認する。
今回は後回しにする
募集作成、決済、チャット、Push通知、プロフィール評価、会場予約。
最初に会話する一つの流れ
1
募集を見つける
2
参加申請する
3
主催者が承認する
4
参加が確定する
正常例・例外・未決定を並べる
正常例
定員2人の募集へplayer-1が申請し、承認される。残り枠は1人になる。
例外として確認
- ・主催者自身の応募
- ・同じ人の二重応募
- ・定員超過の承認
- ・期限後の応募
まだ答えがない問い
- ・却下後に再応募できる?
- ・承認後の辞退は?
- ・最後の1枠を同時承認したら?
ここまでで明確にすること
- 01目的を表す一文
- 02一つの利用シナリオ
- 03正常例・例外・未決定の問い
- 04チームで揃えた業務の言葉
時間では区切りません。この4つをチームで共有できたら、クラス図やディレクトリ構成の検討へ進みます。
STEP 01 · LANGUAGE
まず、画面ではなく業務の言葉を揃える
画面上の「参加する」は即時参加ではありません。主催者の承認前は「参加申請」であり、申請中・承認・却下を区別します。この違いをドメインモデルの名前と状態に反映しました。
Recruitment主催者が日時・期限・定員を決め、参加者を募る単位RecruitmentApplication参加希望者が募集に対して行う申請approve主催者が申請を参加確定へ進める操作remainingCapacity定員から承認済み人数を引いた値STEP 02 · MODEL
なぜRecruitmentをAggregate Rootにしたか
応募可否と承認可否は、参加申請だけを見ても判断できません。募集状態、開催日時、応募期限、主催者、既存申請、定員を同時に確認するため、Recruitmentを変更の入口にしました。
Application Service
応募・承認Use Case
RECRUITMENT AGGREGATE
Recruitment
状態・期限・主催者・定員を保持
応募時
受付中か、期限内か、本人が主催者でないか、二重応募でないか
承認時
受付中か、開催前か、定員内か、申請中か
変更後
残り枠は承認済み人数から計算し、外部から直接書き換えない
STEP 03 · VERIFY
業務ルールをテストまで追跡する
「守るべき」と書くだけではなく、どの操作が所有し、どのテストが保証しているかを対応づけます。現在は次の5ルールをDomain Testで確認しています。
Recruitment.apply()Test: 参加申請をPendingで受け付けるRecruitment.apply()Test: 主催者自身の応募を拒否するRecruitment.apply()Test: 同じユーザーの二重応募を拒否するRecruitment.approve()Test: 定員を超える承認を拒否するRecruitment.approve()Test: Pending以外の申請は再承認できないDomain: src/features/futsal/domain/Recruitment.ts
Test: src/features/futsal/domain/Recruitment.test.ts
npm run test:futsal
CURRENT GAP
画面とドメインモデルは、まだ接続されていない
現在の画面は操作感を確認するプロトタイプです。「この募集に申請する」を押すとReactのローカル状態へIDを追加しますが、Recruitment.apply()は呼んでいません。
実装・検証済み
- ✓ Recruitmentの状態と操作
- ✓ 5つの不変条件テスト
- ✓ 業務エラーの識別コード
未実装・未検証
- ○ Application Service
- ○ Repositoryと永続化
- ○ 画面からDomainへの接続
- ○ 同時更新と通知
NEXT EXPERIMENT
次の実装で確かめること
- 1
画面をUse Caseへ接続
ReactのappliedIdsをやめ、ApplyToRecruitmentがRecruitmentを取得・操作・保存する。
- 2
Repository境界を検証
interfaceを利用側へ置き、まずInMemory実装でUse Caseをテストする。
- 3
同時承認を検証
最後の1枠を同時に承認した場合に、VersionやDB制約で定員を守れるか確認する。
- 4
通知をイベントで分離
承認後通知が本当にDomain Eventを必要とするか、失敗時の再送を含めて試す。
各実装で「推奨どおりに置けたか」「例外が必要だったか」「テストしやすくなったか」を記録し、判断ルールの推奨・例外・Good / Bad Exampleを更新します。