2017-02-08 6 views
2

Я просматривал разные CQRS samples, и большинство из них используют обработчики команд, которые не сохраняют UnitOfWork (то есть DataContext в случае Entity Framework). Что-то вроде этого:Почему обработчики команд CQRS исключают сохранение UnitOfWork?

public void Handle(Command message) 
    { 
     var course = Mapper.Map<Command, Course>(message); 

     _db.Courses.Add(course); 
    } 

Сохранение (и фиксация транзакции) обычно происходит в фоновом режиме при обработке запроса.

Я видел этот подход у многих ведущих парней CQRS, но я никогда не слышал его рассуждений.

Самой большой проблемой такого подхода являются случаи, когда вам нужно получить идентификатор объекта сразу после вызова обработчика (что происходит довольно много). Там, очевидно, есть способы обходного пути (например, использование Guid, предварительный запрос уникального идентификатора из вашей базы данных и т. Д.), Но кажутся неуклюжими.

Но каковы преимущества этого подхода? Теоретически это могло бы помочь не делать несколько обращений к базам данных в случае, если у нас есть несколько обработчиков на запрос. Но этого не происходит. Еще одно преимущество, которое приходит мне на ум, заключается в том, что нам не нужно вводить эту рутину «Сохранить вызов», и пусть это произойдет автоматически. Это любопытно, но имеет ли он избыточный вес проблемы генерации Id?

ответ

1

Почему обработчики команд CQRS исключают сохранение UnitOfWork?

Я думаю, что он начинается с Эвансом, Domain Driven Design, глава 6 Жизненный цикл объекта домена.

Существует плоту методов для решения технических проблем доступа к базе данных ....

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

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

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

Эванса очень выразительный об этом, в контексте операций

Оставить управление транзакциями клиента. Хотя REPOSITORY будет вставляться и удаляться из базы данных, он обычно ничего не совершает. Заманчиво совершать после сохранения, например, но клиент предположительно имеет контекст для правильного инициирования и фиксации единиц работы. Управление транзакциями будет проще, если REPOSITORY отдержит руки.

Некоторые дополнительные примечания:

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

Это обычно указывает на то, что вы боретесь с неправильной проблемой. См. Marc de Graauw, Nobody Needs Reliable Messaging.

+0

Я чувствую, что все это имеет немного больше смысла с репозиториями. Когда мы напрямую работаем с DataContext, мы не работаем с доменом, мы модифицируем хранилище данных.И тогда мы не делаем последний шаг (сохраняя то, что мы изменили), и делаем вид, что мы разобрались в манипулировании доменными объектами и работе с хранилищем данных. – SiberianGuy

1

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

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

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

Вот некоторые преимущества:

  1. Все обработчики команд будут иметь общий интерфейс
  2. Таким образом, вы можете написать вспомогательный код, который поддерживает все обработчики команд. например командные маршрутизаторы, проверка безопасности и разрешений, протоколирование, мониторинг производительности, очередность сообщений ....
  3. Это может значительно уменьшить количество кода, который вам нужен для написания.
  4. Это может значительно уменьшить сложность кода, который вам нужно написать
  5. Тестирование гораздо проще и надежнее

это всего лишь несколько с верхней части моей головы.

Почему бы не включить единицу работы?

Возможно, это короткий ответ. Но мне нравится переносить ответственность за настойчивость из обработчика. Обработчик может обратиться к нему, но фактическая настойчивость выполняется в другом месте (мои предпочтения в большинстве случаев находятся в хранилище событий).

+0

Спасибо за ответ, но я бы не пошел так далеко, как называть Гиды элегантными :) – SiberianGuy

+0

Почему бы и нет? Создание глобального уникального идентификатора, независимого от базы данных. Я думаю, что это довольно круто. – Codescribler

+0

Ну ... они уродливые :) И если вам нужно показать идентификатор Guid на url, он никогда не чувствует себя правильно – SiberianGuy