Як поводитися з помилками після валідації в команді (DDD + CQRS)


18

Наприклад, коли ви подаєте реєстраційну форму, ви повинні перевірити в Domain Model( WriteModelin CQRS), що вона знаходиться у дійсному стані (наприклад, синтаксис електронної адреси, вік тощо).

Потім ви створюєте Commandі відправляєте його до Command Bus.

Я розумію, що Команди нічого не повинні повертати.

То як ви вирішите помилку далі Command Bus? (Наприклад, користувач зареєстрував за 1 секунду раніше те саме username/email).

Як ви знаєте, що команда не вдалася, і як ви знаєте помилку?


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

1
Команди не повинні повертати нічого при успіху . Ідея почалася з CQS , що означало , що команда може все-таки кинути виняток за помилкою. Те, що ви описуєте, - це одностороння команда. Дивіться цю відповідь стосовно цього.
Спікер Кейсі

Відповіді:


4

Я розумію, що Команди нічого не повинні повертати.

Це один погляд, але він не повністю встановлений в камені. Поміркуйте над записом (PUT, POST, DELETE) на HTTP - всі ці повідомлення є командами, в тому сенсі, що це повідомлення з проханням змінити ресурс, і все ж вони повертають відповіді.

Отже, як ви впораєтеся з помилкою поза командною шиною? (Наприклад, користувач зареєструвався за 1 секунду раніше тим самим ім'ям користувача / електронною поштою).

Як ви знаєте, що команда не вдалася, і як ви знаєте помилку?

Так, у випадку, коли ви спілкуєтесь безпосередньо з обробником команд, повернене повідомлення - це цілком розумний спосіб визнати, що команда була отримана та оброблена.

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

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

Альтернативні підходи трохи пряміші. Можна було б включити до повідомлення зворотний дзвінок, який може викликати обробник команд після успішної обробки повідомлення.

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

І звичайно, у вас є додатковий варіант видалити проміжне програмне забезпечення, яке, здається, перешкоджає зробити правильну справу просто.

Наприклад, користувач зареєструвався за 1 секунду раніше тим самим ім'ям користувача / електронною поштою

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


2

Наприклад, коли ви подаєте реєстраційну форму, ви повинні перевірити в Доменній моделі (WriteModel в CQRS), що вона знаходиться у дійсному стані (наприклад, синтаксис електронної адреси, вік тощо)

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

Отже, як ви впораєтеся з помилкою поза командною шиною? (Наприклад, користувач зареєструвався за 1 секунду раніше тим самим ім'ям користувача / електронною поштою).

Цей вид перевірки багато обговорюється в спільноті CQRS, починаючи з початку CQRS. Де це зробити? Це дуже дискутується. Я особисто використовую такий підхід: Перш ніж команда буде відправлена ​​в BUS, я позначаю ім'я користувача / електронну пошту як прийняті централізовано (тобто унікальне обмеження індексу для імені користувача / електронної пошти). Після цього я надсилаю команду. Недолік полягає в тому, що якщо команда не працює, на короткий проміжок часу це ім'я користувача буде взято та не використано; це прийнятно для мого бізнесу, імовірно, для вашого бізнесу.

Як ви знаєте, що команда не вдалася, і як ви знаєте помилку?

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

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


1

Перевірка повинна виконуватися в декораторі. Тоді будь-яка команда, яка потребує перевірки, може бути оформлена як така.

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

Інша можливість полягає в тому, щоб перевірити перевірку як тип "запиту", який би повернув результат перевірки. Запустіть запит перевірки, а потім, якщо він переданий, запустіть команду. Це було б альтернативою декоративного підходу.


Мені подобається підхід до винятку, оскільки це найчистіший спосіб. Але хіба винятки не надто важкі для цього?
EresDev

1
HI @EresDev - Так, вони важкі. Але я не знаю, наскільки "валідні" ваші дані. Скажімо, з 1000 записів 2 недійсні. Винятки можуть бути життєздатними, оскільки це справді виняткові умови. Тепер розглянемо 1000 записів із 200 недійсними. З цієї причини слід уникати винятків, оскільки 20% ваших даних не є дійсними. Отже, я залишаю вам вирішити, чи вибрати цей підхід виходячи з вашої поточної дійсності даних. :)
Джон Рейнор

Я додам до цього, сказавши, що якщо ми збережемо приклад форми реєстрації, де я думаю, що 50% або навіть більше користувачів спочатку вставляють недійсні дані, виняток все одно добре. У задніх програмах веб-додатків ви здебільшого отримуєте дійсні дані, оскільки фронти також виконують перевірку. Ви отримуєте лише те, якщо щось пропустило перевірку фронтену якось рідкісним випадком або якщо хтось обдурить. Отже, винятки в цьому випадку дуже добре.
EresDev
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.