Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

注文で理解するDDDのエンティティ・オブジェクト場合分け

More than 1 year has passed since last update.

基本パターン

  • 不変オブジェクトでない
    • 同一性を持つ
      • 親エンティティを持たない
        • 生存期間がトランザクションより短い -> 普通のオブジェクト
        • 生存期間がトランザクションより長い -> エンティティ
          • 値オブジェクトで構成される - 普通のエンティティ
          • 他のエンティティや普通のオブジェクトや集合(list, map)で構成される - ルートエンティティ
      • 親エンティティを持つ
        • 生存期間が親エンティティと同じか短い -> エンティティの一部
        • 生存期間が親エンティティより長い -> エンティティへの関連
    • 同一性を持たない -> 普通のオブジェクトだが値オブジェクトに変更可能
  • 不変オブジェクトであるー値オブジェクト
    • エンティティへの参照を持つ -> エンティティへの注釈かエンティティの一部
    • 持たない
      • そもそも構造を持たない -> スカラー値。Intとか文字列とかenumとか
      • 内部構造は有る -> data class とか case class で表される値オブジェクト
      • エンティティと同じ内部構造 -> エンティティのコピー(スナップショット)

色々な同一性の例

私がラーメン屋に入り「ラーメン!ラーメン!」と叫ぶとします。

  • ラーメンが二つ出てきた -> 2回のラーメンがそれぞれ別の同一性を持つ二つのエンティティと解釈した
  • ラーメンが一つ出てきた -> 2回のラーメンが別の注文ではない(別の同一性を持たない)と解釈した
  • ラーメン一つ?と聞かれた -> 2回のラーメンがそれぞれ別の同一性を持つと解釈したが一つの注文を二回発声しただけかもしれないので確認した

注文は注文を受け付ける前から料理を出した後まで存在するのでトランザクションより長い=エンティティです。

私がラーメンとラーメンの食券を出すとします

  • ラーメンが二つ出てきた -> 二つの食券がそれぞれ別の同一性を持つと解釈した
  • ラーメン二つ?と聞かれた -> 二つの食券がそれぞれ別の同一性を持つと解釈したが一つの注文を間違えて二回しただけかもしれないので確認した

※物理的存在は特に理由がなければ同一性を持ちますので二つの食券が一つの注文と解釈されることは有りません。黙ってラーメン一つだけ出てくるということはないでしょう

私が大盛りラーメンの食券を出すとします

  • この食券に書かれているだろう「ラーメン」の文字列はラーメンと呼ばれる何かを指す値オブジェクト
  • この食券に書かれているだろう「大盛り」の文字列は盛り属性を指定する値オブジェクト

私がラーメンの食券を出すとします

  • ラーメン売り切れたからチャーシュー麺でいいよね?と食券が書き換えられた -> 食券のラーメン値オブジェクトがチャーシュー麺値オブジェクトに置き換えられた

私がラーメンと大盛りの食券を出すとします

  • 大盛りラーメンがでてきた -> 大盛りは「大盛り属性」値オブジェクトなので物理的存在にはならない。物理的存在になるラーメンの属性を大盛りにした
  • ラーメンとラーメンでない何かがでてきた -> このラーメン屋では大盛りは属性ではなく「大盛りと呼ばれる何かの料理?」であり物理的存在になりえるのでそれを出した

私がラーメンと味玉の食券を出すとします

  • 味玉を載せたラーメンが出てきた -> ラーメンがルートエンティティであり味玉はその一部とした

味玉を食べずに味玉載せラーメンを完食することは可能でしょうか?味玉は味玉載せラーメンの一部となります。

私がラーメンと大盛りと餃子の食券を出すとします

  • 餃子をのせた大盛りのラーメンが出てきた -> ラーメンがルートエンティティと解釈した
  • 大盛りラーメンと別の皿に餃子が出てきた -> 注文がルートエンティティでありラーメン(大盛り)と餃子がそれに含まれると解釈した

私がラーメンと大盛りの食券を出すとします

  • 「大盛りラーメンのお客さまー?」という私を探す声が聞こえた -> 提供先エンティティ(私)を見失ったので値オブジェクトでのマッチングで絞り込みを行った。
  • 食券に席の番号を書き込んだ -> 提供先エンティティを見失わないように座っている席エンティティのIDを追加した
  • 食券に「いつも大盛りラーメンの人」と書き込んだ -> 提供先エンティティを見失わないようにIDを追加した
  • 食券に何かを書き込み半分にちぎって返してきた -> 食券と半券に注文のIDとなる何かを追加した(提供先エンティティを見失ってもIDでの突合せが可能)

なお、私や席は物理的に存在し同一性を持ちトランザクション以前も以後も存在するのでエンティティです。

水はセルフサービスだった

  • 水はトランザクションに含まれず生存期間は私の任意なのでエンティティとして扱う必要はない=普通のオブジェクト。また、水に同一性は不要なので一杯の水と言う値オブジェクトとして扱ってもそう困らない。

私が大盛りラーメンの写真を撮るとします

  • これは大盛ラーメンのスナップショット

私が大盛りラーメンを日記に書いたとします

  • これも大盛ラーメンのスナップショット

私が独りで大盛りラーメン食べたと日記に書いたとします

  • 独りは大盛りラーメンの一部でもなければ属性でもない=ラーメンの注釈(ラーメンへの関連)

私がラーメン屋ではなくセルフうどん屋にいったとします

  • 自分で盆に載せる=自分のトランザクション内で同一性が保てれば十分=同一性は私がローカルで保持するのでグローバルな同一性は不要=盆やうどんはエンティティではない

終わりに

注文を間違えるとお互いにつらいので同一性はしっかり保持しましょう。
勘違いしがちですが同一性とはなにもしなくとも有るというものではなく注文を間違えないように(IDを発行するなど)同一性を保つ工夫をするものです。

turanukimaru
KotlinとかScalaの仕事探してます
http://turanukimaru.hatenadiary.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away