Обработка дублирования логики домена с использованием DDD и CQRS

Я экспериментирую с DDD + CQRS, и я не могу понять, как справиться с проблемами дублирования этой области:

Во-первых, о дублировании между доменами:

Сценарий 1: Скажем, у меня есть приложение, которое обрабатывает служащих. У меня есть 3 ограниченных контекста: отдел программистов, отдел QA и отдел аудита. У каждого БК есть собственный АР: "Программист", "Тестер", "Рабочий". Они на 99% отличаются друг от друга, с каждой логикой в ​​каждой из них, однако у каждого из них есть "Имя", "Фамилия" и простой метод "getFullName", который объединяет эти два.

Вопрос 1: Как я (и должен ли я?) сделать, чтобы общий метод не дублировался в каждом AR?

Самый простой ответ - это, возможно, сделать некоторый общий "человеческий" класс и сделать из них 3 AR, но это противоречит идее DDD, так как "QA Department" никогда не понадобится "getFullName", но нужно немного другой "общий" метод. Поэтому это решение сделает домен спамом с неиспользуемыми методами.

Теперь о дублировании кода CQRS:

Сценарий 2: База данных содержит счета-фактуры. В каждом счете есть поля "сумма" и "налог". На странице "показать счет" мне нужно указать сумму счета с налогом. Поэтому в моей прочитанной модели мне нужно будет сделать "total = sum + tax", чтобы показать ее конечному пользователю. Тем не менее, пользователь может нажать кнопку "одобрить", которая должна, допустим, зарегистрировать сумму счета в другой базе данных (учет или что-то еще). Итак, в моей модели записи мне снова понадобится сделать "total = sum + tax".

Вопрос 2: Как я (и должен ли я?) удалить этот тип дублирования?

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

Любые идеи? Я что-то пропустил?

Ответ 1

Сценарий 1

  • Скопируйте и вставьте код в каждый из трех ограниченных контекстов.
  • Создайте объект Value для имен, содержащихся в общей библиотеке, которая инкапсулирует логику получения полного имени.
  • Создайте ограниченный контекст сотрудника, ответственный за управление деталями сотрудников. Любой дополнительный ограниченный контекст может затем использовать это для поиска сведений о сотрудниках. События будут опубликованы для обеспечения согласованности между ограниченными контекстами (например, EmployeeJoinedCompanyEvent, содержащим их полное имя).

Сценарий 2

Любые вычисления должны быть частью вашей модели домена. Содержится в объектах, объектах Value или Domain Services.

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

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

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

Ссылки

Несколько ресурсов, которые я могу настоятельно рекомендовать для внедрения DDD и CQRS (если вы уже знакомы с книгой Eric Evan DDD).

Ответ 2

Сценарий 1

Довольно часто что-то вроде Управление основными данными было бы ограниченным контекстом. Здесь будет указано имя сотрудника, дата рождения и т.д. Другие ограниченные контексты, а также различные модели чтения могут извлекать свои данные (прямо или косвенно) оттуда.

Сценарий 2

Если вы просто создаете простые суммы, я бы не возражал против дублирования контекстов. Когда у вас есть более сложные способы расчета, они должны быть четко связаны с их соответствующим ограниченным контекстом. В вашем примере может быть ограниченный контекст Invoicing, являющийся естественным местом, где связаны алгоритмы, вычисления и службы, связанные с фактурированием. После этого будут созданы и одобрены счета-фактуры, чтобы заполнить затронутые модели чтения.