CQRS + Sourcing подій: (чи правильно це) Команди, як правило, передаються «точка-точка», тоді як події домену передаються через pub / sub?


12

Я в основному намагаюся обернути голову навколо концепції CQRS та пов'язаних з цим понять.

Хоча CQRS не обов'язково включає в себе повідомлення та обмін подіями, це здається гарною комбінацією (як це можна побачити з великою кількістю прикладів / блогових постів, що поєднують ці поняття)

Враховуючи випадки використання для зміни стану для чогось (скажімо, щоб оновити запитання щодо SO), чи вважаєте ви наступний потік правильним (як у найкращій практиці)?

Система видає сукупний UpdateQuestionCommand, який може бути розділений на пару менших команд: UpdateQuestion, орієнтований на корінь питання агрегації, та UpdateUserAction (для підрахунку балів тощо), орієнтовані на коріння користувача агрегувати. Вони надсилаються асинхронно, використовуючи точкові повідомлення.

Сукупні корені роблять свою справу, і якщо все добре виходить з пожежних подій QuestionUpdated і UserActionUpdated відповідно, які містять стан, який передається в аутсорсинг магазину подій .., щоб він зберігався yadayada, просто щоб бути повним, не зовсім тут справа.

Ці події також ставлять у паб / під чергу для мовлення. Будь-який абонент (серед якого, ймовірно, один або кілька проекторів, які створюють «Перегляди»), може вільно підписатися на ці події.

Загальне питання: чи дійсно найкраща практика, що команди передаються командами «точка-точка» (тобто: приймач відомий), тоді як події транслюються (тобто: приймач (и) невідомі)?

Припускаючи вищевикладене, яка б була перевага / недолік, щоб дозволити трансляцію команд через pub / sub замість пункту до пункту?

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

З іншого боку, я бачу переваги (гнучкість), коли команди трансляції будуть дозволені.


Добре написане питання btw.
Дав

Відповіді:


19

Відмова від відповідальності: Я лише роблю свої перші кроки у світі CQRS, але можу запропонувати своє сучасне розуміння цього питання і побачимо, чи підтвердять інші. Все, що я пишу нижче, має основну тему "як я бачу", і не є авторитетною.

Справа на 80%

Щоб відповісти на ваше запитання, команди - це справді точкова справа. Коли команда входить до контролера (MVC webapp), він контролює диспетчер команд, щоб знайти один і лише один відповідний обробник команд, і делегує роботу цьому обробнику.

Чому б не опублікувати?

Це питання відповідальності . Якщо щось надсилає команду, це тягне за собою сподівання, що вона буде виконана. Якщо ви просто опублікуєте і сподієтесь, що щось десь підхопить і діє на нього, немає гарантії, що так буде. Екстраполяцією ви також не знаєте, чи кілька обробників не вирішують діяти над командою, можливо, в результаті одна і та ж зміна застосовується більше одного разу.

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

Приклад

Це можна порівняти з реальним життям. Якщо у вас є троє дітей, заходьте в кімнату і просто кричите "Чистіть ванну кімнату", ви не маєте гарантії, що хтось зробить це, і переконайтеся, якщо це не буде зроблено двічі (якщо у вас є слухняні діти ;-) Ви повинні краще, якщо ви призначите конкретну дитину робити те, що ви хочете зробити.

Коли ця дитина закінчить свою роботу, це зручно, якщо вона кричить "Ванна кімната прибрана", так що кожен, хто хоче чистити зуби, знає, що тепер може це зробити.


має багато сенсу. Відмінна аналогія :)
Geert-Jan

Ти загубив мене в .. When a command enters a controller (MVC webapp)-? Ви використовуєте RESTful? або деякі гібридні кінцеві точки API? Чи можете ви додати приклад, будь ласка
Пьотр Кула

@ppumkin ми використовували кінцеву точку WebAPI, яка б викликалася нашим веб-додатком щоразу, коли це було потрібно для виконання команди. Напр. якщо користувач захотів додати коментар до повідомлення, веб-додаток надішле запит на пошту example.com/api/Post/AddPostComment.
Дав

1

Я згоден, що система ініціювання, як правило, ніколи не очікує, що команда може здійснювати трансакцію кількох цільових систем:

  • Команди, як правило, ніколи не надсилають і моляться - система ініціювання команди, як правило, бажає асинхронного зворотного зв’язку, коли відбуваються хід і результат команди (наприклад, такі події держави, як acknowledgementуспішні completionабо failureможуть бути опубліковані цільовою системою для інформування про ініціювання система).
  • Якщо було залучено кілька цільових систем, система ініціювання отримає кілька команд (можливо, суперечливих) результатів для команди (наприклад, ціль 1 вдалася, але ціль 2 не вдалася). Це потребує додаткової складності у визначенні фактичного стану вихідної команди (наприклад, чи буде транзакція команд вважатися успішною лише у тому випадку, якщо всі цілі вдалися? Чи потрібно команду відкотити або компенсувати успішними цілями, якщо одна з цілей не вдалася? тощо). Це спричинило б небажане з'єднання та складність між ініціюючою та цільовою системами.

Однак все-таки заслуговує на те, щоб мати можливість передплатити додаткових (не транзакційних і зазвичай досить «розрядних») споживачів, які «підслуховують» команди, видані між системами

  • Цілі аудиту
  • Інструментальні та експлуатаційні показники (наприклад, навантаження, бізнес-аналітика тощо)
  • Комплексна обробка подій або обробка потокових подій "підслуховувачами" - ці системи можуть виявляти помилки або нерівності в командах (наприклад, частота команд або кореляція між різними комбінаціями команд і подій), а також може викликати сповіщення або коригувальні дії (часто в форма подальших команд різних типів).
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.