Aggregate(集約)

Aggregate(集約)とは

Aggregateは、業務上の操作で一緒に確認するドメインモデルを、一つの単位として扱う範囲です。この範囲の中で業務ルールを守ります。

具体例で整理する

例えば、「募集」では、参加希望者から「参加申請」を受け付けます。フットサルNOWでは、主催者による承認は行わず、条件を満たした参加申請は自動で参加確定になります。

参加申請を受け付けるときは、「期限を過ぎていたら受け付けない」「同じ人の申請は二重に受け付けない」「定員に達していたら受け付けない」というルールがあります。

これらのルールを守るには、「募集状態」「申込期限」「定員」「参加者」を一緒に確認する必要があります。そのため、これらを一つの「募集」として扱います。このドメインモデルの範囲がAggregateです。

例:「募集」として扱う範囲

募集を表すドメインモデル

募集

Entity・Aggregate Root

ルールの確認に使うもの

募集状態
定員
参加者ID
申込期限

参加申請の受付で守るルール

「募集」が、必要な情報を使って次のルールを確認します。

  • 期限を過ぎていたら受け付けない

    確認する情報:申込期限

  • 同じ人の申請は二重に受け付けない

    確認する情報:参加者ID

  • 定員に達していたら受け付けない

    確認する情報:定員と現在の参加者数

集約の範囲を決める

集約の範囲は、画面やデータベースの構造ではなく、一つの業務上の操作で一緒に守るルールを基準に決めます。

ディレクトリで表す

フットサルNOWでは、「募集」のAggregateに含めるドメインモデルをdomain/recruitment/に置きます。

src/features/futsal/
└── domain/
    └── recruitment/                ← 「募集」のAggregateを置くディレクトリ
        ├── RecruitmentEntity.ts                  ← Aggregate Root
        ├── RecruitmentStatusValueObject.ts
        ├── RecruitmentCapacityValueObject.ts
        ├── ParticipantIdValueObject.ts
        └── ParticipationRequestDeadlineValueObject.ts

集約の範囲はディレクトリ名ではなく、どの業務ルールを一緒に守るかによって決まります。このディレクトリは、決めた範囲をコード上でも分かりやすくするための配置例です。

※ DDDで必須の命名ではありません。このガイドラインでは、ファイル名やクラス名だけで役割を見分けやすくするため、EntityとValueObjectを名前に付けています。Aggregate RootはEntityに与えられる役割なので、名前には付けず注釈で示します。