Entity
Entityとは
Entityは、業務から見つけた概念をコードで表すための、ドメインモデルの構成要素です。その概念を、名前や状態ではなく同一性によって区別する必要があるとき、Entityとして表します。
Entityを使うと、情報が変わっても以前から続くものとして扱い、反対に、情報が同じでも別のものとして区別できます。
Entityの同一性
例えば、人には名前、住所、年齢などの属性があります。引っ越して住所が変わったり、誕生日を迎えて年齢が変わったりしても、別の人になるわけではありません。
システムでは、会員IDなどの識別子を使って一人ひとりを区別します。属性が変わっても会員IDが同じであれば、同じ人の情報が変更されたものとして扱います。このように、属性が変わっても「その人であること」が変わらない性質を同一性と呼びます。
Entityの特徴
- 状態が変わる
- 名前や状態などの属性を変更しても、別のEntityにはなりません。
- 属性が同じでも区別する
- 同じ商品を同じ数量で注文した二件の注文でも、注文IDが異なれば別の注文です。
- 同一性を持つ
- どのEntityであるかを識別子で区別し、識別子が同じなら属性が変わっても同じEntityとして扱います。
具体例で整理する
前のページでは、参加者募集のドメインモデルとして「募集」「参加申込み」「申込期限」などを見つけました。ここでは「募集」を例にします。
募集の開催場所が渋谷から新宿へ変更されたとします。開催場所が変わっても、募集IDはrecruitment-1のままなので、変更前と同じ募集だと判断できます。
変更前
募集ID:recruitment-1
開催場所:渋谷
変更後
募集ID:recruitment-1
開催場所:新宿
「募集」は、開催場所などの属性が変わっても、募集IDによって変更前と同じ募集として区別できるため、Entityとして表します。
コードで表す
募集をEntityとして表すと、例えば次のようになります。
TypeScript
// 「募集」を表すEntity
class RecruitmentEntity {
constructor(
// 募集の同一性を表す識別子
readonly id: string,
// 変更されることがある募集の属性
private title: string,
private location: string,
) {}
// 開催場所を変更する
changeLocation(newLocation: string) {
this.location = newLocation
}
// 同一性はIDで比較する
isSameAs(other: RecruitmentEntity) {
return this.id === other.id
}
}RecruitmentEntityは、開催場所を変更できる一方で、IDは変更できません。二つの募集が同じかどうかは、タイトルや開催場所ではなくIDで判断します。
フットサルNOWでの配置例
src/features/futsal/
└── domain/ ← ドメインモデルを置くディレクトリ
├── recruitment/
│ └── RecruitmentEntity.ts ← Aggregate Root(Entity)
└── ... ← ほかのドメインモデル※ これはフットサルNOWでの配置例です。DDDが特定のディレクトリ構成を定めているわけではありません。
※ このガイドラインでは、ファイル名やクラス名だけで役割を見分けやすくするため、DDD上の役割を名前に付けています。