リポジトリパターンを適切に使用する方法について頭を悩ませようとしています。Aggregate Root の中心的な概念が次々と出てきます。Web とスタック オーバーフローの両方で集約ルートとは何かについてのヘルプを検索すると、それらに関する議論と、基本定義が含まれているはずのページへの無効なリンクが見つかります。
リポジトリ パターンのコンテキストでは、集約ルートとは何ですか?
リポジトリパターンを適切に使用する方法について頭を悩ませようとしています。Aggregate Root の中心的な概念が次々と出てきます。Web とスタック オーバーフローの両方で集約ルートとは何かについてのヘルプを検索すると、それらに関する議論と、基本定義が含まれているはずのページへの無効なリンクが見つかります。
リポジトリ パターンのコンテキストでは、集約ルートとは何ですか?
リポジトリ パターンのコンテキストでは、集約ルートは、クライアント コードがリポジトリからロードする唯一のオブジェクトです。
リポジトリは、子オブジェクトへのアクセスをカプセル化します。呼び出し元の観点からは、ルートが読み込まれると同時に、または実際に必要になったときに (遅延読み込みのように)、それらを自動的に読み込みます。
たとえば、Order
複数のオブジェクトに対する操作をカプセル化するオブジェクトがあるとしLineItem
ます。クライアント コードは、ドメインのその部分の集約ルートとなるオブジェクトを含むLineItem
オブジェクトのみを直接ロードすることはありません。Order
エヴァンス DDD より:
AGGREGATE は、データ変更の目的で 1 つの単位として扱う関連オブジェクトのクラスターです。各 AGGREGATE には、ルートと境界があります。境界は、AGGREGATE の内部にあるものを定義します。ルートは、AGGREGATE に含まれる単一の特定の ENTITY です。
と:
ルートは、外部オブジェクトが [.] への参照を保持できる AGGREGATE の唯一のメンバーです。
これは、集約ルートがリポジトリからロードできる唯一のオブジェクトであることを意味します。
例は、Customer
エンティティとエンティティを含むモデルAddress
です。Address
関連する のコンテキストがないと意味がないため、モデルからエンティティに直接アクセスすることはありませんCustomer
。したがって、Customer
とがAddress
一緒になって集合体を形成し、それCustomer
が集合体ルートであると言えます。
集約ルートは、単純なアイデアの複雑な名前です。
適切に設計されたクラス図は、その内部をカプセル化します。この構造にアクセスするポイントは と呼ばれaggregate root
ます。
ソリューションの内部は非常に複雑かもしれませんが、この階層のユーザーはroot.doSomethingWhichHasBusinessMeaning()
.
車にどのように乗りたいですか?より良い API を選択
オプションA(何とか機能します):
car.ride();
オプション B (ユーザーはクラス内部にアクセスできます):
if(car.getTires().getUsageLevel()< Car.ACCEPTABLE_TIRE_USAGE)
for (Wheel w: car:getWheels()){
w.spin();
}
}
オプション A の方が優れていると思われる場合は、おめでとうございます。背後にある主な理由がわかりaggregate root
ます。
集約ルートは、複数のクラスをカプセル化します。メイン オブジェクトを介してのみ、階層全体を操作できます。
コンピューター エンティティがあるとします。このエンティティも、ソフトウェア エンティティとハードウェア エンティティなしでは生きられません。これらはComputer
集合体を形成し、ドメインのコンピュータ部分のミニエコシステムです。
Aggregate Root は、Aggregate ルート内の母体エンティティ (この場合Computer
は ) であり、Aggregate Root であるエンティティのみをリポジトリで処理するのが一般的であり、このエンティティは他のエンティティの初期化を担当します。
集約ルートを集約へのエントリポイントと見なします。
C# コードの場合:
public class Computer : IEntity, IAggregateRoot
{
public Hardware Hardware { get; set; }
public Software Software { get; set; }
}
public class Hardware : IEntity { }
public class Software : IValueObject { }
public class Repository<T> : IRepository<T> where T : IAggregateRoot {}
Hardware も ValueObject である可能性が高いことに注意してください (それ自体には ID がありません)。これは単なる例として考えてください。
データベース優先のアプローチに従う場合、集約ルートは通常、1 対多の関係の 1 側のテーブルです。
最も一般的な例は人です。各人は多くの住所、1 つまたは複数の給与明細、請求書、CRM エントリなどを持っています。常にそうであるとは限りませんが、9/10 の場合はそうです。
現在、e コマース プラットフォームに取り組んでおり、基本的に 2 つの集計ルートがあります。
顧客が連絡先情報を提供し、トランザクションを顧客に割り当て、トランザクションが項目を取得するなど。
売り手は製品を販売し、連絡先を持ち、私たちについてのページ、特別オファーなどを提供します。
これらは、顧客と販売者のリポジトリによってそれぞれ処理されます。
集約とは、何かの集まりを意味します。
ルートはツリーの最上位ノードのようなもので、そこから<html>
Web ページ ドキュメントのノードなどすべてにアクセスできます。
ブログの類推、ユーザーは多くの投稿を行うことができ、各投稿には多くのコメントを含めることができます。したがって、任意のユーザーを取得すると、ルートとして機能して、関連するすべての投稿とそれらの投稿の追加コメントにアクセスできます。これらはすべてまとめてコレクションまたは集約と呼ばれます
DDD ステップ バイ ステップ(オフライン)から:
Aggregate 内には Aggregate Root があります。集約ルートは、集約内の他のすべてのエンティティおよび値オブジェクトの親エンティティです。
リポジトリは集約ルートで動作します。
詳細については、こちらもご覧ください。
Erlang では、OO 合成ではなく、状態内のデータ構造によって集約が構成されると、集約を区別する必要がなくなります。例を参照してください: https://github.com/bryanhunter/cqrs-with-erlang/tree/ndc-london