.net - 逻辑什么时候属于业务对象/实体,什么时候属于服务?

标签 .net domain-driven-design entity business-logic

在试图理解领域驱动设计时,我不断地回到一个我似乎无法明确回答的问题。

如何确定哪些逻辑属于域实体,哪些逻辑属于域服务?

例子:
我们有一个在线商店的 Order 类。此类是一个实体和一个聚合根(它包含 OrderItems)。

Public Class Order:IOrder
{
    Private List<IOrderItem> OrderItems

    Public Order(List<IOrderItem>)
    {
        OrderItems = List<IOrderItem>
    }

    Public Decimal CalculateTotalItemWeight()
    //This logic seems to belong in the entity.
    {
        Decimal TotalWeight = 0
        foreach(IOrderItem OrderItem in OrderItems)
        {
            TotalWeight += OrderItem.Weight
        }
        return TotalWeight

    }
}

我想大多数人都会同意 CalculateTotalItemWeight 属于实体。但是,在某些时候,我们必须将此订单运送给客户。为此,我们需要做两件事:

1) 确定运送此订单所需的邮费。

2) 确定邮费后打印运输标签。

这两个操作都需要 Order 实体之外的依赖项,例如用于检索邮资费率的外部 Web 服务。我们应该如何完成这两件事呢?我看到几个选项:

1) 直接在域实体中编码逻辑,例如CalculateTotalItemWeight。然后我们调用:
Order.GetPostageRate
Order.PrintLabel

2) 将逻辑放入接受 IOrder 的服务中。然后我们调用:
PostageService.GetPostageRate(Order)
PrintService.PrintLabel(Order)

3) 为对 Order 进行操作的每个操作创建一个类,并通过构造函数注入(inject)将该类的实例传递给 Order(这是选项 1 的变体,但允许重用 RateRetriever 和 LabelPrinter 类):
 Public Class Order:IOrder
{
    Private List<IOrderItem> OrderItems
    Private RateRetriever _Retriever
    Private LabelPrinter _Printer

    Public Order(List<IOrderItem>, RateRetriever Retriever, LabelPrinter Printer)
    {
        OrderItems = List<IOrderItem>
        _Retriever = Retriever
        _Printer = Printer
    }

    Public Decimal GetPostageRate
    {
        _Retriever.GetPostageRate(this)
    }

     Public void PrintLabel
    {
        _Printer.PrintLabel(this)
    }
}

如果有的话,你会为这个逻辑选择哪一种方法?你的选择背后的原因是什么?最重要的是,是否有一套指导方针引导您做出选择?

最佳答案

我倾向于让外部服务确定运费。对我来说,这是应用程序逻辑,而不是特定于订单的逻辑。例如,您可能决定在一段时间内为超过一定尺寸的订单或特定的忠实客户群提供免费送货服务。对我来说,逻辑往往会独立于订单的构建方式而改变。

很可能我会将负责下订单的代码(某种订单处理器服务,在应用程序层或命令处理程序中)移交给服务以获取运费,然后将该费率传递给订单,所以我猜选项2。

对于打印运输标签,我倾向于让域引发类似于 http://www.udidahan.com/2009/06/14/domain-events-salvation/ 的事件。 .然后一个单独的处理程序将处理打印标签。同样,这样做的逻辑是,您打印标签的方式可能会独立于您构建订单的方式而变化,因此将其分开是有意义的。使用域事件似乎是确保在正确的时间打印标签而不需要订单(或者实际上是订单处理器)了解打印逻辑的最干净的方法。

关于.net - 逻辑什么时候属于业务对象/实体,什么时候属于服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4840105/

相关文章:

.NET:Thread 类怎么会被滥用,它不是密封的吗?

.net - 有人使用Microsoft ASML语言吗?

c# - Entity Framework 6 中显式数据库事务的意义是什么?

hibernate - 如何将 ResultSet 对象转换为 Hibernate Entity Bean

ios - 在 Swift 中从 Core Data 设置实体对象

java - JPA 在持久化实体时忽略字段

c# - 简单的类实例化在 C# 中会失败吗?

c# - 使用 Wordnik API 请求定义

domain-driven-design - 在哪里检查用户电子邮件尚不存在?

domain-driven-design - 可以将 Datacontext 设置为存储库中的属性吗?