Когда логика принадлежит бизнес-объект / сущность, и когда он относится к Сервису?

Пытаясь понять дизайн, управляемый предметной областью, я постоянно возвращаюсь к вопросу, на который, похоже, не могу дать окончательного ответа.

Как вы поживаете. определить, какая логика принадлежит объекту домена, а какая логика принадлежит службе домена?

Пример: У нас есть класс 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, например, внешний веб-сервис для получения ставок почтовых расходов. Как нам достичь этих двух целей? Я вижу несколько вариантов:

1) Закодируйте логику непосредственно в сущности домена, например CalculateTotalItemWeight. Затем мы вызываем:

Order.GetPostageRate
Order.PrintLabel

2) Поместите логику в службу, которая принимает IOrder. Затем мы звоним:

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

3) Создайте класс для каждого действия, которое работает с заказом, и передайте экземпляр этого класса в заказ через внедрение конструктора (это вариант варианта 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)
    }
}

Какой из этих методов вы выберете для этой логики, если таковые имеются? Что послужило причиной вашего выбора? Самое главное, есть ли набор руководящих указаний, которые привели вас к вашему выбору?

5
задан Casey Wilkins 29 January 2011 в 23:23
поделиться