メインコンテンツまでスキップ

第14章:ドメインイベントの正体:起きた事実を表す🔔🕒

この章のゴール🎯✨

この章が終わると、次の3つがスッキリ言えるようになります🙂💡

  • ドメインイベントって何?(一言で!)🗣️
  • 「イベントっぽいけど違うやつ」を見分けられる👀
  • ミニEC(注文→支払い→発送)で、イベント候補を自力で5個以上出せる🛒💳📦

14.3 ドメインイベントの構成要素📦🧩

イベントの構成要素

ドメインイベントには、最低限以下の情報を含めます。 ドメインイベント(Domain Event)= ドメイン(業務)の中で起きた、意味のある“事実” 🔔🕒 「アプリにとって都合がいい通知」じゃなくて、現実(業務)で起きたことの記録って感覚です🙂✨

Martin Fowlerさんの説明でも、ドメインイベントは「何かが起きた」ことを表すデータ構造として語られます。 (martinfowler.com) DDDのリファレンス(Eric Evans系)でも、ドメインイベントは「過去の出来事の記録」で、基本的に不変(immutable)で、発生時刻や関係するエンティティの識別子などを含む、とされています。 (Domain Language)


「イベント」って言っても、いろいろあるよね🤔💭

ここで言うドメインイベントは、こういう気持ち👇

  • 業務的に意味がある(人間が読んで「そうだね」ってなる)🙂
  • 過去形の事実(もう起きた)🕒
  • 基本は変えない(歴史を書き換えない)🧊
  • ドメイン語彙で書く(SavedToDb みたいな技術語彙じゃない)🙅‍♀️

例でつかむ:ミニECだとこうなる🛒✨

事実(ドメインイベント)になりやすい例🔔

  • OrderPlaced(注文が確定した)🛒✅
  • PaymentCompleted(支払いが完了した)💳✅
  • OrderCancelled(注文がキャンセルされた)❌
  • ShipmentCreated(発送が作成された)📦
  • ShipmentDelivered(配達完了した)🏠✅

これ、全部 「起きた」 だよね🙂🕒


逆に、ドメインイベントじゃない(または危ない)例⚠️🙅‍♀️

① 命令(コマンド)混入タイプ📣➡️

  • SendPaymentEmail(支払いメール送って!)📧💨
  • ShipOrder(発送して!)🚚

これ、“やれ” だから命令です。 イベントは “やった(起きた)” じゃないとブレやすいよ〜🙂

② 技術都合の出来事タイプ🔧

  • OrderSavedToDatabase(DBに保存された)💾
  • CacheInvalidated(キャッシュ消した)🧹

これは技術的には起きた事実だけど、業務の意味として薄いことが多いです😵‍💫 (※運用や監視で必要になることはあるけど、それは“ドメインイベント”とは分けて考えるのが安全🙂)

③ 未来や仮定が混ざるタイプ🔮

  • PaymentWillBeCompleted(支払いが完了する予定)🌀
  • ShipmentMayBeCreated(発送されるかも)🌫️

イベントは「確定した過去」の記録が基本だよ🕒✅


ドメインイベントは「通知」じゃなく「事実の表現」🧠🔔

ここ、超大事ポイント💡

イベントを使うと、結果として 「メール送る」「ポイント付与する」みたいな処理を“後から”ぶら下げられるようになります🎁📧 でも、イベントの本体はあくまで…

  • その瞬間、業務で何が起きたか
  • それを表す名前と情報

なんだよね🙂✨


ドメインイベントの“最低限セット”って何?📦✨

DDD Referenceの説明をイメージすると、ドメインイベントにはだいたいこれが入ります👇 (Domain Language)

  • イベント名(例:OrderPaid)📝
  • いつ起きたか(OccurredAt / Timestamp)🕒
  • 誰(どの集約)で起きたか(AggregateId / EntityId)🪪
  • 必要なら、重要な値(例:支払い金額、決済手段など“業務上の意味があるもの”)💰

逆に入れない方がいいのは👇🙅‍♀️

  • DbContext / HttpContext / Repository みたいな“仕組みの部品”🔧
  • 巨大なオブジェクト丸ごと(太りやすい🐘💦)

C#での表現:イベントは“不変なデータ”が相性よし🧊💎

C#では「不変なデータ」を作るのが得意なので、イベントと相性がいいです🙂 (2026年1月時点では .NET 10 / C# 14 が最新の安定ラインとして扱えます。 (gihyo.jp))

たとえば「支払い完了」を、イベントとして“記録”するだけの形👇

public interface IDomainEvent
{
DateTimeOffset OccurredAt { get; }
}

public sealed record OrderPaid(
Guid OrderId,
decimal PaidAmount,
DateTimeOffset OccurredAt
) : IDomainEvent;

ポイントはここ💕

  • recordデータっぽく する📦
  • 作ったら基本変えない(=事実の記録)🧊
  • “OrderId と OccurredAt” みたいな 意味ある最小限 を入れる✂️✨

「事実っぽさ」チェックリスト✅🔍

イベント候補が出てきたら、これで判定すると安定します🙂✨

  • 過去形で言える?(〜した / 〜された)🕒
  • 業務の人が聞いて意味わかる?(技術用語だらけじゃない?)🗣️
  • 起きたら取り消せない“歴史”っぽい?(後から編集したくならない?)🧊
  • この出来事で、ドメイン上の状態が変わった?(意味のある変化?)🔁

やってみよう🛠️:ミニECのイベント候補を5つ出す💡🛒

ミニECの流れを思い出してね👇 注文(Order)➡️ 支払い(Payment)➡️ 発送(Shipment)

次の「業務上の出来事」を、過去形のイベント名にしてみよう🙂✍️

お題🎮

  1. 注文が確定した
  2. 支払いが完了した
  3. 支払いが失敗した
  4. 発送が作成された
  5. 配達が完了した

例(答えの形)✨

  • OrderPlaced
  • PaymentCompleted
  • PaymentFailed
  • ShipmentCreated
  • ShipmentDelivered

※ ここでのコツは「技術」じゃなくて「業務」で言うことだよ🙂💕


よくあるミスあるある💥(先に潰そう🙂🧯)

ミス①:イベントを“処理のスイッチ”にしちゃう🎛️😵

「メール送信のためにイベント作る」だけだと、名前がズレがち💦 ✅ まずは事実(例:PaymentCompleted)を置いて、 その後で「メール送信」などを“反応”として付けるのがキレイ🙂✨

ミス②:イベントに何でも詰め込む📦🐘

「あれもこれも必要かも…」で巨大化しがち! ✅ まずは ID+時刻+必要最小限 から始めるのが安全✂️✨

ミス③:イベント名が“内部実装”になる🔧🌀

OrderSavedToDb みたいになると、ドメインから離れていきます🙅‍♀️ ✅ “ユーザーや業務が見る出来事” に寄せる🙂


AI相棒に頼むと超ラク🤖✨(でも判断は自分🎯)

イベント候補出しや命名のたたき台は、AIが得意です🙂💕

使えるお願い例📝

  • 「ミニECで起きる“業務的に意味のある過去形イベント”を10個、短い名前で提案して」🔔
  • 「このユースケースを“事実(イベント)”の列に直して」✍️
  • 「このイベント名、技術寄りじゃない?ドメイン語彙に直して」🧼

⚠️ ただし、**「それが本当に業務的に意味があるか」**は人間が決めるのが大事だよ🙂🎯


14.1 ドメインイベントって何?🔔✨

事実としてのイベント

ドメインイベントは、ドメイン内で**「何かが起きた」という事実**を表すオブジェクトです。

  • 目的は通知じゃなく、まず 事実をちゃんと表現すること 📣✅

  • 迷ったら

    • 過去形?🕒
    • 業務の言葉?🗣️
    • 不変の記録?🧊 でチェック🙂✅

ミニクイズ🎓🎮(サクッと確認)

次のうち「ドメインイベントっぽい」のはどれ?(複数あり)🙂

  1. SendReceiptEmail 📧
  2. OrderPaid 💳✅
  3. OrderSavedToDatabase 💾
  4. ShipmentDelivered 📦🏠✅
  5. RecalculateTotalAmount 🔁

✅ それっぽい:2 と 4 (1と5は命令、3は技術都合になりやすい💡)