ワイヤーフレームからドメイン設計が進んだ話

はじめに ドメイン設計だけでは埋まらない違和感 ワイヤーフレームを作って起きた変化 1. ユーザーの行動が具体化される 2. 必要なデータと制約が見えてくる 3. ドメイン設計の「抜け」が露出する ワイヤーフレームは見た目のためではない まとめ おわりに はじめに 最近、アプリ開発の中で「ワイヤーフレーム」を使い始めたところ、思いがけずドメイン設計が大きく前進しました。 ワイヤーフレームとは、 Figma などを使って作る UI デザインの一種です。 ただし、色やフォントサイズなどの細かい UI にはこだわりません。 ボタンや入力欄であることがわかれば良いという程度のラフな UI デザインのことを言います。 もともとドメイン駆動で設計を進めていたのですが、どうしても「抜け」や「曖昧さ」が残る感覚があり、手応えが弱い状態が続いていました。 しかし、ワイヤーフレームを作り始めたことで、その状況が一変しました。 この記事では、 ワイヤーフレームがどのようにドメイン設計を補完し、加速させたのかを整理してみます。 ドメイン設計だけでは埋まらない違和感 ドメイン設計を進めていると、以下のような状態に陥ることがありました。 ユースケースはある程度整理されている エンティティや値オブジェクトも定義できている しかし「本当にこれで使えるのか?」という違和感がある つまり、構造はあるが、実感がない状態です。 このとき不足していたのは、「ユーザーがどう操作するか」という視点でした。 ワイヤーフレームを作って起きた変化 試しにワイヤーフレームを作り始めたところ、明確な変化がありました。 1. ユーザーの行動が具体化される ワイヤーフレームでは「画面上で何をするか」を考える必要があります。 どこで入力するのか どの順番で操作するのか 何を確定とみなすのか これにより、ユースケースが単なる文章ではなく、操作として具体化されました。 2. 必要なデータと制約が見えてくる 操作を具体的にすると、自然と以下が見えてきます。 この画面では何のデータが必要か この操作はどんな条件で許されるのか ここで重要なのが、 不変条件(インバリアント) です。 例えば、口座振替管理アプリなら、 支払い元は必ず 1 つである 振替は「元 → 先」の関係を持つ 不正な組み合わせは作れない など、これらはドメイン設計だけでも定義できますが、 ワイヤーフレーム上で「操作」として考えることで、一気に現実味を帯びます。 3. ドメイン設計の「抜け」が露出する ワイヤーフレームを作る中で、次のような気づきが頻発しました。 この状態、どうやって作る? この操作、どのユースケースに対応する? このデータ、どこに属する? つまり、ドメイン設計で曖昧だった部分が強制的に表に出てくるのです。 ...

March 18, 2026 · 1 分 · 奥田 智紘

DDDで「集約はIDで参照する」とはどういう意味か

オブジェクト参照の場合 Order User アプリケーションサービス ID参照の場合 Order User アプリケーションサービス 違いを整理 オブジェクト参照 ID参照 もう一つ重要な違い:イベント駆動に拡張できる Application Service イベントの定義 EventBusの簡易実装 イベントハンドラ ハンドラ登録 イベントの流れ まとめ ドメイン駆動設計(DDD)では、次のようなルールをよく目にします。 集約は他の集約を IDで参照する しかし、初めてこのルールを見たときに疑問が浮かびます。 ID参照にしても結局 Repository.find(id) で取得できるのでは? それなら普通のオブジェクト参照とあまり変わらないのでは? この記事では、このルールの意味を 実際のコードで比較しながら説明します。 オブジェクト参照の場合 まず、他の集約を オブジェクトとして直接持つ設計を見てみます。 Order class Order( val id: OrderId, val user: User ) { fun place() { // 注文処理 user.upgradeToPremium() } } tips : place という単語には、 注文を出す / 発注する という意味があります。 User class User( val id: UserId, var plan: Plan ) { fun upgradeToPremium() { plan = Plan.PREMIUM } } アプリケーションサービス fun placeOrder(orderId: OrderId) { val order = orderRepository.find(orderId) order.place() orderRepository.save(order) } ここで起きていることを図にすると次のようになります。 ...

March 12, 2026 · 2 分 · 奥田 智紘

一つの集約にまとめるべきか、別の集約に分けるべきかの判断基準(DDD)

1. 不変条件を同時に守る必要があるか(最重要) 例 別集約になる例 2. ライフサイクルが一緒か 例 別集約の例 3. 集約は他の集約をIDで参照する 4. 同時に更新されるか 例 5. 集約は小さく保つ まとめ ドメイン駆動設計(DDD)で設計をしていると、次のような疑問に必ずぶつかります。 このエンティティは同じ集約に入れるべきか? それとも別の集約として切り離すべきか? 集約の境界は、DDDにおいて非常に重要な設計判断です。 この記事では、実務でよく使われる判断基準を整理します。 1. 不変条件を同時に守る必要があるか(最重要) 最も重要な基準は 不変条件(Invariant) です。 「このルールは常に同時に成立している必要があるか?」 YESなら 同じ集約 NOなら 別集約 例 注文と注文明細 Order └ OrderItem 不変条件 注文の合計金額 = 各注文金額の合計 注文明細の数量 ≥ 1 数量が変われば、注文全体の合計金額は変わります。 つまり、これらは 常に同時に成立している必要があります。 そのため Order と OrderItem は 同じ集約になります。 別集約になる例 Order Inventory (在庫) ルール 注文が確定したら在庫を減らす この処理は 注文確定 在庫更新 の2つの処理に分かれます。 これらは 同時トランザクションでなくても問題ないため Order集約 Inventory集約 と分けます。 2. ライフサイクルが一緒か 次に考えるのは ライフサイクルです。 「一緒に生まれて一緒に消えるか?」 YES → 同じ集約 NO → 別集約 例 Order └ OrderItem OrderItem は ...

March 12, 2026 · 1 分 · 奥田 智紘

ドメイン設計テンプレート

このドキュメントは、DDD(ドメイン駆動設計)に基づいて、ソフトウェアを設計するためのテンプレートです。 上から順番にテンプレートを埋めていくことで、 DDD に基づいたドメイン周りの設計がスムーズに行えるように作っています。 1. システム概要 システムの目的 対象ユーザー 解決したい課題 2. ユースケース ユースケース一覧 ユースケース詳細 【例】振替関係を作成する 入力 処理概要 出力 3. ユビキタス言語 概念 候補とその言葉のイメージ 賛否の意見 言葉の決定とその採用理由 ユビキタス言語辞書 4. エンティティ候補 5. 不変条件(Invariant) 6. 状態遷移 【例】TransferRelation 状態 状態遷移 7. 集約設計 集約一覧 集約詳細 【例】TransferRelation 属性 不変条件 ドメインメソッド 8. ドメインサービス サービス一覧 サービス詳細 【例】TransferService 9. リポジトリ 10. ユースケース設計 UseCase一覧 UseCase詳細 【例】CreateTransferRelationUseCase 処理 1. システム概要 システムの目的 このシステムは何を解決するものか。 【例】 フリーランスの固定費を管理する 口座振替の関係を可視化する 対象ユーザー このシステムのユーザー。 【例】 個人 フリーランス 企業 解決したい課題 【例】 固定費の支払い関係が分かりにくい 口座振替の全体構造を把握できない 2. ユースケース ユーザーがシステムで行う操作を列挙する。 ...

March 11, 2026 · 2 分 · 奥田 智紘

ドメイン設計テンプレート(補強版)

このドキュメントは、 ドメイン設計テンプレート に以下の項目を加えた補強版となっています。 4.境界コンテキスト 5.コンテキストマップ 7.値オブジェクト 12.ドメインイベント 15.集約境界図 16.不変条件の責任 1. システム概要 システムの目的 対象ユーザー 解決したい課題 2. ユースケース ユースケース一覧 ユースケース詳細 【例】振替関係を作成する 入力 処理概要 出力 3. ユビキタス言語 概念 候補とその言葉のイメージ 賛否の意見 言葉の決定とその採用理由 ユビキタス言語辞書 4. 境界コンテキスト 5. コンテキストマップ 6. エンティティ候補 7. 値オブジェクト 8. 不変条件(Invariant) 9. 状態遷移 【例】TransferRelation 状態 状態遷移 10. 集約設計 集約一覧 集約詳細 【例】TransferRelation 属性 不変条件 ドメインメソッド 11. ドメインサービス サービス一覧 サービス詳細 【例】TransferService 12. ドメインイベント イベント詳細 【例】TransferRelationCreated 発生タイミング ペイロード 13. リポジトリ 14. ユースケース設計 UseCase一覧 UseCase詳細 【例】CreateTransferRelationUseCase 処理 15. 集約境界図(Aggregate Boundary) 【例】TransferRelation 集約名 / Aggregate Root 内部エンティティ 値オブジェクト 集約境界 外部参照 集約ルール 16. 不変条件の責任(Invariant Responsibility) 不変条件一覧 不変条件の責任 振替日は1〜31 同じ口座 + サービスの振替関係は1つだけ 振替関係は必ず口座を持つ 振替関係は必ずサービスを持つ 不変条件の配置ルール 例 1. システム概要 システムの目的 このシステムは何を解決するものか。 ...

March 11, 2026 · 3 分 · 奥田 智紘

DDDにおける「集約」「ドメインサービス」「ユースケース」の違い

DDDにおける「集約」「ドメインサービス」「ユースケース」の違い まず結論 集約(Aggregate) ドメインサービス ユースケース(Application Service) ドメインロジックをどこに置くか 状態を持つドメインサービスはどうなるか ケース1:新しいドメイン概念が生まれた ケース2:一時的な処理状態 判断のための質問 よくある失敗 まとめ DDDにおける「集約」「ドメインサービス」「ユースケース」の違い DDD(ドメイン駆動設計)を学び始めると、多くの人が次の疑問にぶつかります。 集約とドメインサービスは何が違うのか ユースケースはどこまで責任を持つのか ドメインロジックはどこに書くべきなのか この記事では、この3つの概念を整理しながら、ドメインロジックをどこに置くべきかの判断基準を解説します。 まず結論 3つの役割は次のように整理できます。 集約(Aggregate) ドメインの状態を持つ 不変条件を守る ドメインモデルの中心 ドメインサービス(Domain Service) エンティティに属さないドメインロジック 複数の集約にまたがる処理 ユースケース(Use Case / Application Service) ユーザー操作を実現する手順 ドメインモデルを組み合わせる 依存関係は次のようになります。 UI ↓ UseCase ↓ DomainService ↓ Aggregate 重要なルールは 内側の層は外側を知らないこと です。 集約(Aggregate) 集約は 状態と不変条件を守るドメインモデル です。 例として「口座振替」を考えます。 振替関係には次のルールがあります。 振替日は 1〜31 「振替元 + 振替先」が同じ振替関係は 1 つだけ (重複不可) このルールを守る主体が TransferRelation です。 class TransferRelation( val accountId: AccountId, val serviceId: ServiceId, private var paymentDay: PaymentDay ) { fun changePaymentDay(newDay: PaymentDay) { paymentDay = newDay } fun stop() { // 状態変更 } } 【集約の特徴】 ...

March 10, 2026 · 2 分 · 奥田 智紘

DDDでドメインを設計するときの流れ

DDDでドメインを設計するときの流れ ドメイン設計の全体の流れ この記事の前提 1. ユースケースを書き出す 2. ドメイン用語を整理する(ユビキタス言語) 3. エンティティ候補を出す 4. 不変条件を書く 5. 状態遷移を整理する 6. 集約(Aggregate)を決める 7. エンティティの責務を設計する setterが問題になる理由 ドメインメソッドは「操作」を表す 重要な考え方 8. ドメインサービスを定義する 9. リポジトリを定義する 10. 最後にUIを作る まとめ この流れで設計する際のテンプレート DDDでドメインを設計するときの流れ ― 実践的な設計手順 ― ドメイン駆動設計(DDD)を学び始めると、多くの人が次の疑問を持ちます。 ドメイン設計は何から始めればいいのか 実際の開発ではどのような手順で設計するのか DDDの本では概念の説明が多く、「実際の設計手順」がはっきりしないことがあります。 この記事では、実務で使える ドメイン設計の具体的な手順 を整理して紹介します。 ドメイン設計の全体の流れ DDDでドメインを設計する場合、次の順序で進めると整理しやすくなります。 ユースケースを書き出す ドメイン用語を整理する(ユビキタス言語) エンティティ候補を出す 不変条件を書く 状態遷移を整理する 集約(Aggregate)を決める エンティティの責務を設計する 必要ならドメインサービスを作る リポジトリを定義する 最後にUIを設計する 重要なのは UIから設計を始めないこと です。 DDDでは、基本的には、 ユースケース → ドメイン → UI という順序で設計します。 実際には、一度でバシッと決められるわけではないため、ドメインを設計しているときに、ユースケースに戻るなど、各プロセス間を何度も行ったり来たりします。 この記事の前提 この記事では、口座振替管理アプリの開発を想定して、設計の流れを説明してきます。 振替元と振替先をユーザーが紐づけるメモアプリを想像してください。 1. ユースケースを書き出す 最初に、システムでユーザーが行う操作を書き出します。 ポイントは UIではなく行動を書くこと です。 ...

March 10, 2026 · 2 分 · 奥田 智紘

Aggregate Root とは

Aggregate Root とは はじめに Aggregate(集約)とは Aggregate Root(集約ルート)とは 具体例(イメージ) 注文ドメインの例 なぜ Aggregate Root が必要なのか ① 整合性を守るため ② トランザクション境界を明確にするため ③ 依存関係をシンプルにするため 設計時の注意点 ① Aggregate を大きくしすぎない ② 他 Aggregate を直接参照しない ③ Repository は Aggregate Root 単位 よくある誤解 まとめ Aggregate Root とは はじめに DDD(Domain-Driven Design)の文脈で頻繁に登場する Aggregate Root(集約ルート) について解説していきます。 本記事では、 Aggregate / Aggregate Root とは何か なぜこの概念が必要なのか 設計時の注意点 を整理します。 Aggregate(集約)とは Aggregate とは、 関連する複数の Entity / Value Object を 一つのまとまり(整合性の境界) として扱う DDD の設計単位です。 重要なのは、 Aggregate は「常に一貫した状態を保つべき単位」 という点です。 ...

February 12, 2026 · 2 分 · 奥田 智紘