7/8/2011 3:38:24 PM

Ещё немного про “простые” AC/BC, прежде, чем заняться CQRS.
Так, как “простых” AC в любой системе будет большинство и для них CQRS не нужен, отложим его пока на попозже :)

Persisted ViewModel
В прошлый раз я описывал идею того, как AC сохраняет и читает данные из схемы (БД), принадлежащей BC.

В этой связи стоит обратить внимание на то, что AC такого рода являются некими data-centric, или даже data-driven элементами. Показал данные в UI, пользователь поменял что-то в текстбоксе, сохранил в БД.
Понятно, что операция чтения выполняется гораздо чаще, чем записи.

А раз она выполняется чаще, то можно сделать её быстрее! Для этого можно организовать ещё одно хранилище, базу данных, настолько близко к веб-серверу, насколько можно. Можно сохранять/кешировать нашу инфомарцию там так, чтобы доступ к ней был быстрее.
Можно посмотреть на это с такой стороны, что каждая такая операция AC возвращает определённую, по сути, ViewModel, которая в основном содержит достаточно мало данных (не забываем, что мы находимся в пределах BC и имеем дело только с данными, которые нужны только этому BC, у нас больше нет гигантских объектов).
Тогда можно попытаться сделать так, чтобы одна ViewModel занимала, условно говоря, одну строку в этом новом хранилище-базе-кеше, так будет быстрее эту ViewModel оттуда доставать.

Причём, если мы сумели сделать ViewModel как одну строку, или сущность, то нам, по сути, уже нет разницы, какое хранилище использовать: будет ли это SQL Server (ViewModel per row), будет ли это какая-нибудь Mongo или CoachDB или другое NoSQL-решение (Document per row), главное, чтобы было удобно и быстро, можно даже в файлах хранить :)

Классифицируем это новое хранилище как “Persisted ViewModel”. То есть, в рамках BC мы имеем теперь ещё и Persisted ViewModel, который будет разворачиваться настолько близко к клиентам, насколько возможно, чтобы увеличить скорость работы с ним.

Валидация
Пойдём ещё дальше, подумаем о валидации.

Мы, программисты, иногда путаем валидацию и бизнес-правила. Udi отметил, что нужно чётко разделять эти две категории.
Например “максимальная длина имени пользователя – 25 символов”. Это – валидация.
”Email должен быть уникальным” – это валидация.
Мы часто делаем валидацию на стороне клиента, потом ещё раз проверяем на стороне бизнес-логики, возвращая ошибки, чтобы показать их красненьким и всё такое.
Зачем – большой вопрос. Почему мы так не доверяем собственным клиентам, что валидируем (речь не идёт о бизнес-правилах) их ввод дважды, удивлялся Udi. Что случится, если мы не будем делать валидацию на стороне бизнес-логики?
Наша команда не выполнится, возникнет исключение, “имя пользователя слишком длинное и не влезло в SQL-сервер”, что-то в этом роде.
Почему это может случиться? Например потому, что кто-то попытался обойти валидацию на клиентской части. Какой-нибудь хакер.
Почему мы так заботимся о том, чтобы хакер получил красивые красненькие сообщения, связанные с валидацией, откуда такая забота о хакере – большой вопрос. “Знаете что, я считаю, что хакер даже заслуживает того, чтобы получить ошибку “ваша команда не была выполнена”! Особенно если она будет доставлен ему асинхронно по email!” заявил Udi. :)

Тем не менее.
Persisted ViewModel может использоваться так же и для валидации пользовательского ввода. То есть, нам нужно проверить уникальность пользовательского email, мы можем сделать это с использованием расположенного близко к веб-сервису Persisted ViewModel хранилища.

Промежуточный итог
У нас получилась ситуация, когда простые AC, работающие с неконкурентными данными, имеют возможность быстро-быстро работать с Persisted ViewModel. Причём, поскольку данные неконкурентны, мы можем сразу же в неё и писать прямо внутри этого самого AC, когда пользователь добавляет/изменяет данные.
Сделать это крайне несложно: простые AC, партицированные по business capability и принадлежащие только одному BC данные, ничего лишнего, остаётся только привести их к виду 1 запись – 1 ViewModel в идеале. А часто и это не потребуется, так как такая ситуация часто будет иметь место уже как результат этого вертикального партицирования.
Ещё более того. В таком data-driven AC часто не нужен никакой “слой бизнес-логики”, значит можно пойти ещё дальше и “разговаривать” напрямую с Persisted ViewModel! Особенно это просто, когда в этом качестве выступает NoSQL база данных, они практически все имеют REST/JSON интерфейсы, можно взять данные прямо оттуда и положить данные прямо туда. Нам не нужен никакой DAL, ORM, Database Context, что-то ещё.
Даже SQL Server может выставить наружу по HTTP (если нет возможности “нормального” соединения с сервером) хранимую процедуру. Впрочем, в простоте и удобстве этого решения я как-то не слишком уверен, но вариант такой есть, зато DAL делать не надо.

Один из случаев, вызвавших вопросы в нашей группе (и вызывающих вопросы всегда, как сказал Udi), это то, что, разумеется, в одном BC находятся, например, Order и OrderLines.
Однако, если посмотреть на то, что представляют из себя обе эти сущности, то можно заметить, что Order в рамках BC – это всего лишь OrderId. Ну, CustomerId ещё. А OrderLines – это просто список ProductIds. Больше ничего там нет.
Так ли важно в данном случае хранить две таблицы и делать связь между ними, если у нас там только одни идентификаторы?
Можно, например, сделать из списка ProductIds строку, разделённую запятыми. Not a big deal!

Вместо гигантского объекта Order получаем два Guid’а и ещё список Guisd’ов, разделённых запятыми, одна строка.
”So, where is THE Order?” – это шутка, над которой наша “подгруппа” смеялась на перерывах и вопрос, который в шутку задавался друг другу как фраза для начала какого-то разговора. Ну, например, подходит человек к группе разговаривающих и присоединяется фразой “so, guys, where is the order?”
Потому, что никакого объекта “Order” на самом деле в системе нет.

Вот в следующий раз – точно про CQRS. Обмозговать бы ещё малость.

Comments are closed

Powered by BlogEngine.NET 2.5.0.6

About the author

Alexey Raga Alexey Raga
.NET software developer.

E-mail me Send mail

Twitter

Widget Twitter not found.

Root element is missing.X


Recent posts

Archive

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012

Sign in