2016-03-22 8 views
2

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

Пример событие:

interface CustomerMadePreferred { 
    customerId: string, 
    issuingService: string, 
    issuingUser: string, 
} 

Пример команда:

interface MakeCustomerPreferred { 
    customerId: string 
} 

Используя команду выше, мы бы не хватаем контекст, в котором подробно пользователь эмиссионного и обслуживание. Мы могли бы потребовать от клиента указать значения для issuingService и issuingUser как часть команды, но проблема в том, что обычно это команда, представленная клиентом, и позволяет предположить в этом случае, что клиент является веб-браузером вне контроля приложения где мы не можем контролировать, какие значения пользователь может представить в команде. Кроме того, мы можем определить эти значения в целом, если наша служба находится за веб-интерфейсом ReSTful или JSON Web, используя такие вещи, как токены OAuth. Это оставляет мне несколько очевидных стратегий.

Возможные стратегии:

  1. Включите issuingService и issuingUser с командой, а затем проверить их от значений, определенных из контекста AUTH. Это позволяет команде, выданной клиентом, быть идентичной команде, обработанной обработчиком, и упрощает реализацию обработчика, поскольку ему нужен только командный параметр и не передается контекст.
  2. Извлечение issuingService и issuingUser из контекста auth и добавил/ввел эти данные в команду, переданную обработчику команд. Это облегчает задачу для клиентов, выдающих исходную команду, но контракт команды немного отличается между обработчиком команд и клиентом. Пример: Object.assign({}, makeCustomerPreferredCommand, authContext);
  3. Передайте контекст auth как отдельный аргумент обработчику команд или сделайте его доступным из службы, которую может вызывать обработчик команд. Это сохраняет контракт команды, но усложняет реализацию обработчика команд.

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

UPDATE: Альтернативы, позволяет называть его вариантом , может быть, чтобы не включать эти данные в созданном CustomerMadePreferred события, а вместо ручки и испускать отдельные CommandIssued события, которые могут содержать ключ какого-то, что может использоваться для связывания информации эмитента с событиями, выпущенными обработчиком команд.

+0

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

+0

@jpierson нет разницы между 2. и 3. насколько * команда немного отличается между обработчиком команд и клиентом *, есть ли? – guillaume31

+0

@ guillaume31, различия между 2 и 3, возможно, но тонкие, но с точки зрения того, как можно будет писать модульное тестирование вокруг этих или любых других отражающих инструментов вокруг типов команд, будет сильно затронуто. Контракт классов/функций обработчика команд также будет затронут. – jpierson

ответ

1

Мне почти нравится вариант 4 - мое чувство, что идентификатор корреляции - это неправильный механизм. Вместо этого я использовал бы идентификатор причинности; Идентификатор корреляции означает что-то немного другое. Все события, созданные командой.ID: N, будут иметь событие.causationId: N, и вы можете вернуться к истории команд (вне домена), чтобы проверить любые проблемы вне домена.

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

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

(Сравните с Don't Create Aggregate Roots, изменения в учетной записи клиента не из ничего ли они на самом деле исходит изнутри домена Если это так, то, что, вероятно, хочет быть отслежены.?.)

+0

Отличные очки! Мне нравится термин causationId, я также слышал фразу _originating command_, используемую для описания концепции ассоциирования событий с данной командой. В моем случае я думаю, что вопрос о том, как включать или включать такую ​​информацию в события, является скорее проблемой _developer_ или _operational_, чем проблемой непосредственно экспертами домена, указывающих, что вариант 4 может быть лучше, если вообще на этом этапе. – jpierson

1

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

+0

Я тоже думал об этом. Я предполагаю, что это зависит от того, насколько контракт подряжается на клиента и зависит ли он от стиля RPC, ограниченного GET/POST, или использования HTTP-объектов, как вы упомянули. – jpierson

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

  • Нет связанных вопросов^_^