Domain driven design 业务逻辑应该放在域中还是放在服务中?

Domain driven design 业务逻辑应该放在域中还是放在服务中?,domain-driven-design,Domain Driven Design,假设您有一个域实体用户,并且您希望支持用户向其购物车添加项目的功能。现在,我们希望确保购物车中的项目是唯一的,因此我们在User类中创建以下函数: function AddItemToCart(Item item) { // Add business logic to make sure item is unique } 这很有效。但是,如果我们现在还想在用户购物车中添加商品时向用户发送电子邮件,该怎么办?我们可以将其添加到AddItemToCart中,但这需要向用户类中注入某种IEm

假设您有一个域实体用户,并且您希望支持用户向其购物车添加项目的功能。现在,我们希望确保购物车中的项目是唯一的,因此我们在User类中创建以下函数:

function AddItemToCart(Item item)
{
    // Add business logic to make sure item is unique
}
这很有效。但是,如果我们现在还想在用户购物车中添加商品时向用户发送电子邮件,该怎么办?我们可以将其添加到AddItemToCart中,但这需要向用户类中注入某种IEmailer依赖项


另一种方法是创建一个服务来处理此事务(例如ShoppingCartService),该服务将执行业务逻辑并发送电子邮件。但是,这会导致一个相当贫乏的域(即用户类只是getter/setter)

保持方法不变,然后创建一个服务类来处理事务。当调用服务类方法时,您可以将电子邮件发送逻辑注入其中。

“但是,这会导致一个相当贫乏的域(即用户类只是getter/setter)”

用户不是整个域

您有购物车、商品和复杂的
Cart.add()
,可将商品放入购物车


那么,如果用户类看起来过于简单怎么办呢?

作为用户域逻辑一部分的逻辑应该留在用户中。这可能涉及也可能不涉及向用户实体注入服务。我认为这取决于服务是否是用户类业务逻辑的一部分,以及这样做是否遵循您的通用语言

我将写下:

class ShoppingCartService
{
    private EmailService emailer;

    public void addItemToUserCart(User u, Item i)
    {
        u.addItemToCart(i);
        this.emailer.sendEmailTo(u, "Item " + i.toString() + " was added to your cart");
    }
}
你可能会觉得有帮助的讨论


我还建议您尽可能地限制getter和setter的范围,以减少耦合。

在大型系统中,用户类最终会有许多不同类型的操作。这门课可能太大了。为了避免这种情况,应该有其他类为用户做一些事情。

如果站点管理员按顺序打电话,会发生什么?您确定User.AddItemToCart在这种情况下是正确的设计吗?