Order 集計は完全にカプセル化する必要があります。したがって、アイテムを追加することが有効かどうか、つまり、顧客のクレジットを超えているかどうかを判断できる必要があります。これを行うにはさまざまな方法がありますが、それらはすべて、この特定のことを行う方法を知っている特定の集計を返す Order リポジトリに依存しています。これはおそらく、たとえば、注文を満たすために使用するものとは異なる注文集計になります。
この場合、注文が特定の役割、つまり追加の品目を追加する役割を果たすことを期待しているという事実を認識し、コードに取り込む必要があります。これを行うには、このロールのインターフェイスと、ロールの内部サポートを持つ対応する集約を作成します。
次に、サービス レイヤーは Order リポジトリに、この明示的な役割インターフェイスを満たす注文を要求できます。したがって、リポジトリには、その要件を満たすものを構築できるようにするために必要なものに関する十分な情報があります。
例えば:
public interface IOrder
{
IList<LineItem> LineItems { get; }
// ... other core order "stuff"
}
public interface IAddItemsToOrder: IOrder
{
void AddItem( LineItem item );
}
public interface IOrderRepository
{
T Get<T>( int orderId ) where T: IOrder;
}
これで、サービス コードは次のようになります。
public class CartService
{
public void AddItemToOrder( int orderId, LineItem item )
{
var order = orderRepository.Get<IAddItemsToOrder>( orderId );
order.AddItem( item );
}
}
次に、実装する Order クラスにIAddItemsToOrder
は、クレジット残高を確認できるように顧客エンティティが必要です。したがって、特定のインターフェイスを定義することで、同じ手法をカスケードするだけです。注文リポジトリは、顧客リポジトリを呼び出して、その役割を果たす顧客エンティティを返し、それを注文集計に追加できます。
したがって、基本ICustomer
インターフェースがあり、それから派生するインターフェースの形式で明示的な役割がありICustomerCreditBalance
ます。はICustomerCreditBalance
、Customer リポジトリへのマーカー インターフェイスとして機能し、顧客が何のために必要かを伝えるため、適切な Customer エンティティを作成できます。また、特定のロールをサポートするためのメソッドやプロパティが含まれています。何かのようなもの:
public interface ICustomer
{
string Name { get; }
// core customer stuff
}
public interface ICustomerCreditBalance: ICustomer
{
public decimal CreditBalance { get; }
}
public interface ICustomerRepository
{
T Get<T>( int customerId ) where T: ICustomer;
}
明示的なロール インターフェイスは、データベースからどのデータをフェッチするか、およびそれを積極的にフェッチするか遅延的にフェッチするかについて正しい決定を下すために必要な重要な情報をリポジトリに提供します。
この場合、インターフェイスにCreditBalance
プロパティを配置したことに注意してください。ICustomerCreditBalance
ただし、基本ICustomer
インターフェース上にありICustomerCreditBalance
、空の「マーカー」インターフェースになって、クレジット残高を照会することをリポジトリに知らせることもできます。返されるエンティティに必要なロールをリポジトリに知らせることがすべてです。
質問で述べたように、これをすべてまとめる最後の部分はドメイン イベントです。注文は、顧客のクレジット残高を超える場合に障害ドメイン イベントを発生させ、注文が無効であることをサービス層に通知できます。一方、顧客に十分な信用がある場合は、顧客オブジェクトの残高を更新するか、ドメイン イベントを発生させて、残高を減らす必要があることをシステムの残りの部分に通知できます。
CartService
この回答はすでにかなり長いため、ドメイン イベント コードをクラスに追加していません。その方法について詳しく知りたい場合は、その特定の問題を対象とした別の質問を投稿することをお勧めします。そこで詳しく説明します;-)