Агрегат или субъект без бизнес-атрибутов - PullRequest
1 голос
/ 28 апреля 2019

Относительно нижеприведенной выдержки, касающейся cqrs и ddd, из Шаблоны, принципы и практики доменно-ориентированного проектирования, Ник Тьюн, Скотт Миллетт

enter image description here

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

Может ли объект Customer опускать имя, фамилию и т. Д.? Если да, то где будут эти бизнес-атрибуты? Только в считанной модели в CustomerEntity?

Или, может быть, кроме CustomerEntity, содержащего все бизнес-атрибуты, также будет CustomerAggregate, оборачивающий CustomerEntity с отношением 1: 1, и объект команды будет работать на CustomerAggregate? (мне кажется странным).

Что означает " Субъект клиента не имеет смысла "?

Ответы [ 2 ]

1 голос
/ 29 апреля 2019

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

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

Почему тогда сущности и В.О.? 1005 *

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

При подаче агрегата (конструктор, параметры вызова функции и т. Д.) Агрегат должен знать, работает ли он с сущностями и / или с V.O. построить свой ответ.

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

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

В одном агрегате может быть сущность Customer с идентификатором и его именем. В другом агрегате может быть сущность Customer с идентификатором и его точками кармы.

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

Одна важная вещь: если вам просто нужно иметь дело с идентификаторами сущностей, тогда рассматривайте это как V.O. (CustomerIdentityVO), поскольку идентификатор является неизменным, и, вероятно, в этом действии вам просто нужно записать этот CustomerIdentityVO в какое-то поле на постоянной основе, а не изменять какой-либо атрибут Customer.

Это стандартное видение. Как только вы начинаете определять общие структуры, относящиеся к нескольким агрегатам или одному агрегату, которые могут выполнять несколько действий с одними и теми же данными, вы начинаете рефакторинг, повторное использование и т. Д. Это просто вопрос хорошего проектирования ООП и принципов SOLID.

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

Рекомендуемые значения:

http://blog.sapiensworks.com/post/2016/07/29/DDD-Entities-Value-Objects-Explained http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-1 http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-2 https://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-3

и

https://blog.sapiensworks.com/post/2016/08/19/DDD-Application-Services-Explained

для полного видения загадки.

0 голосов
/ 28 апреля 2019

Если вы используете Event Sourcing , тогда вы можете моделировать агрегаты без добавления атрибутов, которые им не нужны для реализации бизнес-логики.

Вот пример:

class Customer {

    public Guid ID { get; private set; }

    public Customer(Guid id, firstName, lastName, ...) {

        ID = id;

        this.AddEvent(new CustomerCreatedEvent(id, firstName, ....);
    }

    public void ChangeName(firstName, lastName) {
       this.AddEvent(new CustomerRenamedEvent(this.ID, firstName, lastName), 
    }
}

Пользовательский имеет только атрибут ID , поскольку он необходим для добавления его к каждому генерируемому событию. FirstName и LastName опущены, поскольку они не нужны даже при вызове метода ChangeName .Он только записывает событие, что это произошло.Если ваша логика требует FirstName , вы можете добавить его.Вы можете опустить любые ненужные свойства.

Ваш Репозиторий в этом случае будет сохранять только события и не будет заботиться о значениях атрибутов Клиента.

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

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

Вот пример:

class Customer {

    public Guid ID { get; private set; }
    public string FirstName { get; private set; }
    public string LastName { get; private set; }

    public void ChangeName(firstName, lastName) {
       FirstName = firstName;
       LastName = lastName;
    }
}

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

Не уверен, что означает «Сущность клиента» .

...