本文へスキップ
BecomeCoder

C#実践コース · 第7章 DDD ― ドメイン駆動設計 · レッスン41

エンティティと値オブジェクト

ブラウザで完結

導入

DDD(ドメイン駆動設計)の出発点は「業務の言葉とコードの言葉を一致させる」こと。その第一歩として、モデルの基本パーツエンティティ(IDで識別)とオブジェクト(値そのものが本体)を区別できるようになりましょう。

図解

flowchart TB
    Q{"属性が全部同じ2つを<br/>区別する必要がある?"}
    Q -->|ある(同姓同名でも別人)| E["エンティティ<br/>IDを持つ・状態が変化<br/>例: Member / Order"]
    Q -->|ない(1000円はどれも1000円)| V["値オブジェクト<br/>IDなし・値で等価・不変<br/>例: Money / Email"]
    style E fill:#e1f5fe
    style V fill:#e8f5e9

サンプル

// 値オブジェクト: 金額を int で持たず Money 型にして「不正な金額は存在できない」ようにする
var price = new Money(1000);
var shipping = new Money(500);
Console.WriteLine(price.Add(shipping));   // 1500円

// record なので「値が同じなら等しい」が自動で手に入る
Console.WriteLine(new Money(1000) == new Money(1000));   // True

// エンティティ: IDで同一性を判断(名前が変わっても同じ会員)
var m1 = new Member(1, "Taro");
var m2 = new Member(1, "Taro(改名後)");
Console.WriteLine(m1.IsSameAs(m2));   // True(IDが同じ)

record Money
{
    public int Amount { get; }
    public Money(int amount)
    {
        if (amount < 0) throw new ArgumentException("金額は0以上");
        Amount = amount;
    }
    public Money Add(Money other) => new(Amount + other.Amount);
    public override string ToString() => $"{Amount}円";
}

class Member
{
    public int Id { get; }
    public string Name { get; private set; }
    public Member(int id, string name) { Id = id; Name = name; }
    public bool IsSameAs(Member other) => Id == other.Id;   // 同一性はID
}
  • 値オブジェクト: 値が本体・不変・生成時にバリデーション。recordが最適
  • エンティティ: IDで同一性を判断。属性が変わっても同じ個体
  • 金額をintでなくMoney型にすると「不正な金額」を型で防げる

演習

var email = new Email("taro@example.com");
Console.WriteLine(email.Value);

// TODO: Email 値オブジェクトを record で定義してください
//       ・Value(string) を持つ
//       ・生成時 "@" を含まなければ ArgumentException を投げる
___
  • 期待される出力: taro@example.com
ヒント1を見る

record Email { public string Value { get; } public Email(string value) { if (!value.Contains("@")) throw new ArgumentException(); Value = value; } }

ヒント2を見る

Moneyの構造をまね、検証条件をContains("@")に変えます

まとめ

  • 値オブジェクトは値が本体・不変・生成時バリデーション(record向き)
  • エンティティはIDで同一性を判断する
  • 業務の概念を型にすることで不正状態を防ぐ

次回: 業務ルールをどこに書くか——ドメインの振る舞いです。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。