CQRS командовать или нет, вот в чем вопрос - PullRequest
1 голос
/ 23 февраля 2020

Я новичок в CQRS, но вижу ценность в этом, поэтому я пытаюсь применить это к финансовой системе, которую мы заняты восстановлением.

Как я уже говорил, это основа c Система Fin с базовым c балансом, выводом, внесением, как функциональность.

У меня есть команды снятия и внесения. Но я борюсь с балансом.

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

В мире CQRS вы распределяете guish между командами, которые Изменять состояние и запросы, которые каким-то образом извлекают данные.

Извиняюсь, если мое понимание здесь ошибочно. Может кто-нибудь указать мне правильное направление?

РЕДАКТИРОВАТЬ: Может быть, позвольте мне сказать это так. Я думал о создании CheckBalanceCommand, который создает транзакцию и вставляет BalanceCheckedEvent в хранилище. Но тогда мне также нужно было бы создать CheckBalanceQuery для получения фактического баланса из прочитанной БД. Мне нужно будет вызвать оба, чтобы удовлетворить запрос баланса.

Ответы [ 2 ]

0 голосов
/ 25 февраля 2020

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

Однако я предлагаю смоделировать это явно, а не пытаться обобщать это. Эта функция, вероятно, обусловлена ​​бизнес-потребностями, и вы должны смоделировать ее как таковую. Под этим я подразумеваю, что вы должны рассматривать службу, обслуживающую чтение, как отдельную службу, которая может инициировать собственные события для событий, которые произошли, и проектировать остальную часть системы реактивным способом (ie реагируя на сгенерированные события другим BC / service).

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

Я бы не предлагал команду, потому что если вы будете отвечать данными, это не значит, что кто-то может отклонить команду; это уже произошло, у кого-то уже есть данные.

0 голосов
/ 24 февраля 2020

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

Чтобы поддержать эти случаи, я бы представил базовый тип события с именем IdentityEvent (вдохновленный значениями идентичности для различных математических операторов и в качестве обоснования концепции; использование их для определенного значения не меняет его). После выдачи соответствующей команды производные этого события (например, BalanceCheckedEvent в вашем случае) будут добавлены к потоку событий агрегата, и проекция представления может строить представления из них как обычно; однако их метод мутирования не будет выполнять какую-либо фактическую мутацию при восстановлении объектов из потока событий.

Фактическая обработка команды происходит на уровне домена . Некоторые из ваших прикладных служб на прикладном уровне получают запрос и обрабатывают его как обычно. Кроме того, до или после операции запроса одна и та же прикладная служба может выдать команду на уровне домена в самом агрегате root. Это не нарушает никакого принципа: ваша модель чтения и запроса по-прежнему отделена , прикладная служба просто координирует между двумя .

...