gpt4 book ai didi

domain-driven-design - 获取域实体的附加数据

转载 作者:行者123 更新时间:2023-12-01 08:10:38 24 4
gpt4 key购买 nike

我有一个聚合域,将其称为“Order”,其中包含一个 OrderLines 列表。订单跟踪订单行上的金额总和。客户有一个运行中的“信用”余额,他们可以从中订购,这是通过汇总他们的数据库交易历史计算得出的。一旦他们用完了“资金池”中的所有资金,他们就不能再订购任何产品。

因此,每次向订单添加一行时,我都需要检查池中还剩下多少,以及订单是否超过了订单。池中的金额不断变化,因为其他相关客户不断使用它。

问题是,从 DDD 的角度考虑,我如何获得这个数量,因为我不想用 DataContext 问题污染我的领域层(在这里使用 L2S)。由于我不能只从域中查询数据库,我该如何获取该数据以便验证业务规则?

这是使用领域事件的实例吗?

最佳答案

您的订单聚合应该被完全封装。因此,它需要能够确定添加项目是否有效,即是否超过客户信用。有多种方法可以做到这一点,但它们都依赖于 Order 存储库返回一个知道如何执行此特定操作的特定聚合。例如,这可能与您用于满足订单的订单聚合不同。

在这种情况下,您必须识别并在代码中捕获您期望订单履行特定角色的事实,即添加额外订单项的角色。为此,您可以为此角色创建一个接口(interface),并创建一个具有对该角色的内部支持的相应聚合。

然后,您的服务层可以向您的 Order 存储库请求满足此显式角色接口(interface)的订单,因此该存储库有足够的信息来说明您需要什么来构建满足该要求的东西。

例如:

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 );
}
}

接下来,实现 IAddItemsToOrder 的 Order 类需要一个客户实体,以便它可以检查贷方余额。因此,您只需通过定义特定接口(interface)来级联相同的技术。订单存储库可以调用客户存储库以返回履行该角色的客户实体并将其添加到订单聚合中。

因此,您将拥有一个基本的 ICustomer 接口(interface),然后是一个从它派生的 ICustomerCreditBalance 接口(interface)形式的显式角色。 ICustomerCreditBalance 充当您的客户存储库的标记接口(interface),告诉它您需要客户做什么,因此它可以创建适当的客户实体,并且它具有方法和/或属性来支持特定角色。像这样的东西:

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;
}

明确的角色接口(interface)为存储库提供了他们需要的关键信息,以便他们就从数据库中获取哪些数据以及是急切还是延迟获取做出正确的决定。

请注意,在这种情况下,我已将 CreditBalance 属性放在 ICustomerCreditBalance 接口(interface)上。但是,它也可以在基础 ICustomer 接口(interface)上,然后 ICustomerCreditBalance 变成一个空的“标记”接口(interface),让存储库知道您将要查询贷方余额。这一切都是为了让存储库知道您希望它返回的实体扮演什么角色。

正如您在问题中提到的,将所有这些结合在一起的最后一部分是域事件。如果超过客户的信用余额,订单可以引发失败域事件,以通知服务层订单无效。另一方面,如果客户有足够的信用,它可以更新客户对象上的余额或引发域事件以通知系统的其余部分需要减少余额。

我没有将域事件代码添加到 CartService 类中,因为这个答案已经很长了!如果您想了解更多关于如何做到这一点的信息,我建议您发布另一个针对该特定问题的问题,我会在那里展开讨论;-)

关于domain-driven-design - 获取域实体的附加数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1242552/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com