2016-06-19 9 views
3

Какой уровень должен отвечать за проверку существования какого-либо объекта в базе данных? Допустим, у меня есть заказ как совокупность, и этот заказ может содержать несколько элементов. Логика подразумевает, что я могу добавить только существующие элементы для заказа.Проверка дочернего объекта DDD

Должен ли я написать это в службе приложения:

var item = ItemRepository.GetByID(id); 

//throws exception if the item is null 
order.AddItem(item); 

или

//validate item existence inside aggregate function 
order.AddItem(item, IItemRepository repo); 

ответ

5

Ни, на самом деле.

Субъекты не пересекают общие границы. Либо объект является частью совокупности, и в этом случае совокупность управляет собственным жизненным циклом, или элемент является частью некоторого другого агрегата, и в этом случае вы не разделяете сущность, вы используете ссылку.

order.AddItem(id) 

Часть определения агрегата заключается в том, что изменения в разных агрегатах могут происходить независимо друг от друга. Другими словами, нет никакого способа, чтобы этот агрегат мог знать, что происходит в , что агрегат «сейчас».

Другими словами, вы не можете обеспечить согласованность транзакций по общей границе.

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

interface InventoryService{ 
    boolean currentlyInStock(Item id); 
} 

// ... 

order.addItem(id, inventoryService); 

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

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

Служба домена в этом случае должна не «помогать», выбирая действие на основе доступности инвентаря - возможно, агрегат должен бросить, может быть, агрегат должен бросить для заказов с низким объемом/низким приоритетных покупателей, но используют разные правила, когда заказ превышает миллион долларов. Это задача заказа, чтобы понять это, служба домена просто предоставляет данные.

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

Если вы не согласны принять гонку данных (вы уверены? Amazon принимает заказ на наличие на складе предметов все время ...), тогда вам нужно переосмыслить дизайн своей модели и где вы установили ваши общие границы.

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

Если это неприемлемо, вы поворачиваете изображение матери к стене и выполняете свои бизнес-правила непосредственно в книге записи (т. Е. Ограничениях в вашей РСУБД).

+0

Таким образом, это нормально, если вы выполняете необходимые проверки? – Robert

+1

Я предпочел бы передать весь экземпляр «Item» в метод 'add'. Он больше соответствует вездесущему языку, и вы получаете проверку существования предмета бесплатно или почти так же, как мы, вероятно, можем предположить, что никто не мог бы пройти вручную с помощью экземпляра 'Item'. Затем 'Order' будет просто удерживать идентификатор внутри. Есть и недостатки такого подхода, но в DDD преобладает вездесущий язык. – plalx

Смежные вопросы