概要
ドメイン駆動設計のモデリングの要素の一つ、Entity(エンティティ)の解説です。
DDD 関連記事リンク
◆ ValueObject
記事リンク: https://nrslib.com/valueobject/
◆ Entity(イマココ)
記事リンク: https://nrslib.com/entity/
◆ AggregateRoot
記事リンク: https://nrslib.com/aggregateroot/
◆ Repository
記事リンク: https://nrslib.com/repository/
解説
Entity
Entity は Value Object とは対極に位置するように同一性に焦点を当てたものです。
例えば、同じユーザー名のユーザーがいたとして、そのユーザーは同一でしょうか。
反対に、ユーザー名を変更したとして、ユーザー自体は変わってしまったのでしょうか。
データを見たときに、全く同じ属性を持っていても、別のモノとして認識する必要がある場合 Entity になります。
例としてユーザー情報を表現した User クラスを作ってみます。
User クラスは IsEqualEntity というメソッドで同一性を比較できるようにしています。
ユーザー名を変更したとしても、Id によって同一性を追跡することができます。
もちろん、Equals メソッドと GetHashCode メソッドをオーバーライドしてしまう方法もあります。
等価と等値の扱いを一緒にしてもよいと判断されるのであればそのようにしてよいでしょう。
Entity は同一性を確保するという性質上、ライフサイクルがあり、データベースやファイルなどにデータが永続化されることが多いです。
データベースに保管され、Id を持つという特性から、データベースのテーブルと 1:1 で定義されやすく、DAO (DataAccessObject) と混同されがちです。
しかし、Entity は同一性に着目したオブジェクトであり、そのデータの格納方法には全く関与しません。
Entity はあくまでもデータと手続きをまとめたものです。
よって、SQL などを利用して Entity を構築し、その Entity を利用してビジネスロジックを達成するのが基本的な流れになります。
生成方法
コンストラクタによる生成以外に Factory を考慮することがあります。
コンストラクタによる生成は単純ですが、引数が多くなってきた場合に、インスタンス化によって何を作りたいのかを明確にすることができません。
Factory による生成は Entity の class に static なメソッドを定義しファクトリメソッドとして利用したり、ファクトリクラスを作成し利用します。
永続化
Entity は同一性に着目するため、ライフサイクルが存在し、データベースやファイル等に永続化されることが多いです。
その永続化のための機構として、Repository というものを利用します。
Repository はデータの永続化についての知識が記述されたクラスで、SQL やファイル操作などの処理を活用して Entity を永続化 / 再構築します。
これにより Entity は SQL などのインフラストラクチャ層の知識から解放されます。
とはいえ、Entity を定義するたびに Repository を定義するのはいささか冗長すぎるように思えます。
Entity はおおよそデータベースのテーブル一つと対応が取れるので、Repository がテーブル一つごとに作られることになります。
これはつまりテーブル一つごとに DAO を作るようなことと同義であり、関係データベースなどにおいては折角の Relational が活用できなくなってしまい、非常に非効率的な SQL を発行することになってしまいます。
この問題を防ぐためというわけではありませんが、Repository を定義する基準として AggregateRoot (AR, 集約) という考え方があります。
詳しくは AggregateRoot と Repository の解説でそれぞれ行おうと思いますので、今段階では Entity と必ずしも 1:1 で Repository を作るわけではないという程度で認識しておくとよいと思います。
まとめ
Entity 自体はそれほど難しい概念ではなく、同一性を意識する必要があるオブジェクトのことです。
DDD におけるモデリングのコア部分で、この Entity をただのデータが格納されたオブジェクトとして扱うとドメインモデル貧血症に陥ってしまいます。
SQL などのデータの永続化に関する知識を含めず、Entity にはビジネスロジックを達成する振る舞いを記述するようにするとよいかと思われます。