什么时候逻辑,属于业务对象/实体,而当它在服务属于? [英] When does logic belong in the Business Object/Entity, and when does it belong in a Service?

查看:283
本文介绍了什么时候逻辑,属于业务对象/实体,而当它在服务属于?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在试图理解领域驱动设计我的回头率到一个问题,我似乎无法确切回答。

In trying to understand Domain Driven Design I keep returning to a question that I can't seem to definitively answer.

你如何确定属于哪个逻辑域的实体,属于什么逻辑域服务?

How do you determine what logic belongs to a Domain entity, and what logic belongs to a Domain Service?

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

Example: We have an Order class for an online store. This class is an entity and an aggregate root (it contains 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所属的实体。然而,在某些时候,我们必须运送这个订单给用户。要做到这一点,我们需要做两件事情:

I think most people would agree that CalculateTotalItemWeight belongs on the entity. However, at some point we have to ship this order to the customer. To accomplish this we need to do two things:

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

1) Determine the postage rate necessary to ship this order.

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

2) Print a shipping label after determining the postage rate.

这两项操作都需要依赖的是Order实体外,如外部Web服务来检索邮政资费。我们应该如何完成这两个东西?我看到几个选项:

Both of these actions will require dependencies that are outside the Order entity, such as an external webservice to retrieve postage rates. How should we accomplish these two things? I see a few options:

1)code直接在域实体,如CalculateTotalItemWeight逻辑。然后,我们呼吁:

1) Code the logic directly in the domain entity, like CalculateTotalItemWeight. We then call:

Order.GetPostageRate
Order.PrintLabel

2)把逻辑接受IOrder的服务。然后,我们呼吁:

2) Put the logic in a service that accepts IOrder. We then call:

PostageService.GetPostageRate(Order)
PrintService.PrintLabel(Order)

3)创建一个类的每个操作上订单的动作,并通过构造函数注入传递类订单的一个实例(这是选项1的变化,但允许RateRetriever和LabelPrinter类的重用):

3) Create a class for each action that operates on an Order, and pass an instance of that class to the Order through Constructor Injection (this is a variation of option 1 but allows reuse of the RateRetriever and LabelPrinter classes):

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

这些方法,你选择了这个逻辑,哪一个如果有的话?什么是你的选择背后的原因?最重要的是有没有一套准则,引导你到你的选择吗?

Which one of these methods do you choose for this logic, if any? What is the reasoning behind your choice? Most importantly, is there a set of guidelines that led you to your choice?

推荐答案

我会倾向于有一个外部服务确定利率的运费。对我来说,这就是应用程序逻辑而不是为了特定的逻辑。例如,你可能决定今后一个时期提供免费送货的订单超过了一定规模,还是忠诚的客户的特定群体。对我来说,这种逻辑将倾向于独​​立怎样的顺序构造改变。

I would tend to have an external service determine the shipping rate. For me that's application logic rather then order-specific logic. For example you might decide for a period to offer free shipping for orders over a certain size, or to a particular group of loyal customers. For me that logic will tend to change independently of how an order is constructed.

最有可能我会在code负责下订单(某种订单处理服务,在应用层或在命令处理程序)手头宽裕到服务获得率送货,并然后通过这个速度到订单,所以我猜选项2。

Most likely I would have the code which is responsible for placing the order (some kind of Order Processor service, in an application layer or in a command handler) hand off to a service to get the shipping rate, and then pass that rate into the order, so I guess option 2.

有关打印发货标签,我会倾向于具有域提升沿的 http://www.udidahan.com/2009/06/14/domain-events-salvation/ 。那么一个单独的处理程序将处理打印标签。同样,这样做的逻辑是,你打印标签的方式很可能是独立的,你如何构建一个订单的变化,因此它是有道理的,保持了独立。使用域事件似乎是确保标签打印在正确的时间,而不需要订单(或者实际上的订单处理),以了解打印逻辑的最彻底的方法。

For printing a shipping label, I'd tend towards having the domain raise an event along the lines of http://www.udidahan.com/2009/06/14/domain-events-salvation/. A separate handler would then deal with printing the label. Again, the logic for this is that the way you print labels is likely to vary independently of how you construct an order, so it makes sense to keep that separate. Using a domain event seems to be the cleanest way of ensuring that the label is printed at the right time without requiring the Order (or indeed the order processor) to be aware of the printing logic.

这篇关于什么时候逻辑,属于业务对象/实体,而当它在服务属于?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆