Как сделать это в DDD, не ссылаясь на репозиторий из сущности домена? - PullRequest
3 голосов
/ 26 октября 2011

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

public class Customer {
    ...
    public IEnumerable<Order> Orders { get; set; }
}

public class Order {
    ...
    public Customer Customer { get; set; }
    public IEnumerable<OrderItem> OrderItems { get; set; }

    public void Submit() {
       ...
    }
}

public class OrderItem {
    public Product Product { get; set; }
    public decimal SellingPrice { get; set; }
}

Теперь предположим, что цена продажи Продукта по какой-то причине зависит от того факта, что Продукт также был приобретен (или нет) по предыдущему Заказу, по количеству позиций по текущему заказу и предыдущему заказу и т. Д. Я мог сделатьэто:

public void Submit() {
    Order lastOrder = this.Customer.Orders.LastOrDefault();
    CalculatePrice(lastOrder);

, но это загружает весь список заказов , когда мне действительно нужен только последний!

Что я хотел бы сделать, эточто-то вроде этого:

public void Submit() {
    Order lastOrder = _orderRepository.GetLastOrderFor(Customer);
    CalculatePrice(lastOrder);

Но я понимаю, что ссылка на OrderRepository в Домене - это плохой DDD.Итак, что мне делать?Нужно ли размещать Submit () в другом месте, чем в домене?Если да, то где вы предлагаете?

Ответы [ 2 ]

3 голосов
/ 30 октября 2011

У вас есть две разновидности:

Создайте доменную службу и добавьте в нее зависимость для хранилища:

public class MyPricingStrategy : IPricingStrategy
{
  public MyPricingStrategy(IOrderRepository repository)
  { ... }
}

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

Другой вариант - сделать стратегию ценообразования объектом домена с прикладным уровнем, передавая ему необходимые данные из репозитория:

public class LastOrderPricingStrategy
{
  public LastOrderPricingStrategy(Order lastOrder)
  { ... }
}

на прикладном уровне

var lastOrder = orderRepository.GetLastOrder(currentCustomer);
var pricingStrategy = new LastOrderPricingStrategy(lastOrder);
0 голосов
/ 30 октября 2011

Объект Customer может иметь свойство LastOrder:

public class Customer {
    ...
    public IEnumerable<Order> Orders { get; set; }
    public Order LastOrder { get; set; }
}

Таким образом, часть логики создания заказа устанавливает это поле, и оно будет сохранено вместе с Customer.Затем, когда вы загрузите клиента, вы быстро узнаете, какой последний заказ поступил, и примете свои решения, основываясь на этом соответственно.

Другой способ, если вы используете ORM, такой как NHibernate, вы можете создать несколько запросовзагружать коллекцию Orders только с последним заказом.тогда вы можете вернуться к использованию:

public void Submit() {
    Order lastOrder = this.Customer.Orders.LastOrDefault();
    CalculatePrice(lastOrder);

, и вам не нужно ничего загружать, потому что там будет нужный вам порядок.Я очень часто загружаю в коллекцию только те предметы, которые мне нужны, - это шаблон, который я использую довольно часто.

...