📘

DDDのエンティティって何なの?

2024/02/04に公開

はじめに

フレームワークを使った開発をしていると、エンティティの設計がかなりDBに引っ張られてしまって難しいなと感じることが多いです。
DDDにおいてエンティティを作るとき、どのように考えれば良いエンティティを作れるのでしょうか?

結論

  • エンティティはドメインの概念を表すモデル
  • 振る舞いと属性を持つ
  • 識別子で区別され、属性の変更は可能

エンティティとは何なのか?

エンティティは、ドメインにおける概念をモデルにしたものです。
ドメインエキスパートとの対話の中で発見するものになります。

振る舞いと属性をもつ

例えば

  • ユーザーは名前と年齢を入力する。
  • システムによってユーザーの番号が振られる。
  • 名前は後から変更可能。
  • ユーザーにはノーマル、スペシャルという区分がある。

といった要件が出たとします。
この「ユーザー」こそがエンティティとして扱うべき概念となります。
そして、ユーザーには「名前」「年齢」「番号」「区分」といった属性を持つことになります。
また、ユーザーの「区分」を切り替えられるという振る舞いを持つ必要があることも分かってきます。
属性と振る舞いはモデルのフィールドとメソッドと読み替えることができます。
こういった、フィールドとメソッドをモデルとして表現したものがエンティティということになります。

エンティティの特徴

次に、エンティティには3つの特徴があります。

  1. 可変である。
  2. 属性が同じでも区別される。
  3. 同一性を持つ。

順番に説明します。

可変である

可変とは、属性を後から変えることができる性質になります
先の例でも出したように、ユーザーの名前は後から変えたり、区分を切り替えたりできます。
また、名前や区分を変えたからといって別のユーザーになってしまうわけではないです。
つまり、後から属性を変えることができ、属性を変えてもユーザーとしての同一性は保たれるということです。

属性が同じでも区別される

属性が同じエンティティオブジェクトがあっても、その二つは区別されます。
ユーザーの例だと、名前という属性が同じであっても別のエンティティということになります。

同一性を持つ

前の二つを合わせると、属性を変えても同じオブジェクトで、属性が他のオブジェクトと被っても区別されるということになります。
ではそれらをどうやって実現するかというと、識別子を使って同一性を持つことになります。
識別子とはいわゆるIDのように、同一性を判断するためのものです。
以下は単純な例ですが、idを識別しとした場合はユーザーが同一であることを確認するときにidを使って判定します。

public function Equals(User $user):bool
{
    return $this->id == $user->id
}

余談:ドメインモデル貧血症

振る舞いや属性があまり定義されておらず、モデルが何も語っていない状態をドメインモデル貧血症を起こします。
例えば、モデルにゲッターやセッターしかなく、ビジネスロジックが実装されていない状態のことです。
データとメソッドが扱われていないため手続型の設計になります。

GitHubで編集を提案

Discussion