7/7/2011 3:44:59 PM

From AC
Within BC
You may do some RPC

//SOA Rap

Делить на части в SOA – это как раздевать капусту (Это я продолжаю заметки по ходу курса. Лучший способ утрясти в голове – попробовать рассказать кому-то).
На сервисы поделили – можно делить дальше! :)

Business Components

Сервис, олицетворяя собой business capability, состоит из одного или более Business Component (BC).
Чаще всего всё начинается с одного BC в рамках сервиса и, чаще всего, так и заканчивается.

Однако, иногда возникают ситуации, когда код сервиса начинает “ветвиться”. Udi привёл такой пример: допустим, в наш магазин обратился Стив Балмер, который хочет купить 10 000 единиц товара. Станем ли мы обслуживать его как обычного кастомера? Скажем ли мы ему: “добрый вечер, Стив, спасибо, что зашли, встаньте в конец очереди, пожалуйста, не желаете ли стакан воды”? Попросим ли его в качестве подтверждения дать нам личную кредитную карту на случай? (учитывая, что у Майкрософт есть всего две схемы оплаты и по какой они намерены расплачиваться, они выбирают сами)
Скорее всего нет. А тут ещё Стив Джобс обещал на неделе заглянуть…

В общем, в коде нашего сервиса начинают появляться какие-нибудь условия вроде if (strategicCustomer) {…}.
Раз появилось, два появилось, три появилось – и вот тут уже надо задуматься, а не имеем ли мы дело с другим бизнес-кейсом (в рамках того же capability)?
Рекомендуется в этом случае поговорить с людьми со стороны бизнеса, так как можно получить как ответ “нет, все кастомеры у нас одинаковы, это вот единственное такое исключение”, так и ответ “да, у нас есть определённая категория привелигированных кастомеров, с которыми мы работаем по несколько иной схеме”.
Часто, продолжив разговор, можно обнаружить, что на самом деле бизнес потенциально хотел бы работать с такими кастомерами по ещё более иной схеме, но даже не задумывался над этим, так как давно привыкли думать в рамках того, что позволяет наш софт. И, конечно, на будущее ещё есть планы (Стив Джобс ведь и друзей приведёт).

Если это различие существенно – ура, у нас появился отдельный кейс, выделяемый в отдельный BC.

Создаётся новый BC так: берём тот, что у нас есть, делаем полную копию, убираем из первого всё, что касается кастомера стратегического, из второго – всё то, что касается кастомера обычного.

Отдельно подчёркивается: кроме BC сервис не содержит ничего, кроме, может быть, неймспейса.
Правила простые:

  • Никакого кода помимо кода, содержащегося в BC, в сервисе нет вообще.
  • Два BC друг с другом на уровне кода не связаны никак (никакого наследования одного от другого, никакого общего переиспользуемого кода)
  • Сба BC “выглядят” идентично: они реагируют на одни и те же события, посылают одни и те же сообщения в тех же фазах.
  • Снаружи сервиса BC не видны, сколько их там и что там – не имеет значения, снаружи сервис – это по-прежнему просто сервис.

Таким образом, BC – это этакий мини-сервис, или реализация сервиса в контексте какой-то бизнес-вариации.

Было много вопросов относительно дублирования кода, на которые Udi отвечал примерно так: “если мы обнаружили, что бизнес-аспекты разные, то со временем они будут расходиться дальше, дальше и дальше”, что, в общем-то, имеет смысл.
Как в том примере со стратегическим клиентом: Быть может такому клиенту не имеет большого смысла показывать шоппинг-карту, как обычному клиенту? 10 000 наименований в карте вряд ли кому-то будут интересны. Быть может, схема оплаты для таких клиентов совершенно другая, с ними удобнее работать по предварительному инвойсу, а не по кредитной карте? Быть может схема базы данных для такого случая будет несколько отличаться от “обычной”? А быть может и вообще будет другая база данных?

До тех пор, пока все BC сервиса имеют одинаковый “интерфейс”, то есть, откликаются на одни и те же события (OrderApproved) и посылают одни и те же события (ClientBilled) они “взаимозаменяемы” и снаружи невозможно сказать, какой именно BC обработал событие.
А как они реализованы – их БиСи’шье дело. Ибо инкапсуляция и single responsibility principle.

Autonomous Components

В терминах кода BC представляет собой solution (как я говорил раньше о сервисе, когда сервис у нас был одним BC по сути), состоящий из разных “кусочков”: обработчики событий и сообщений, возможно проект схемы БД, возможно UI какой-то…

Всё это дело можно подразделить на набор неких Autonomous Components (AC).
Правила такие:

  • AC отвечает за определённые типы сообщений (в идеале – за один тип сообщения)
  • AC использует Bus (вход-выход)
  • Допустимы RPC calls в рамках одного BC (внутри AC – who cares, между AC – acceptable, за пределы BC – запрещено)

Важно ещё то, что AC – это единица развёртывания (deployment unit). То есть, AC могут быть установлены на на один или более серверов, в одном или более экземпляре и т.д.
Таким образом, да, BC (а, следовательно, и сервис) у нас может находиться физически на разных машинах и всё такое.

Я вот так себе это в OneNote зарисовал (и да, это у меня почерк такой, особенно когда вертикально на экране пером пишу):

AC, BC

Промежуточный результат

Так, как AC у нас это, получается, такие маленькие проектики, суть маленькие DLLs (единицы развёртывания), отвечающие за малое количество сообщений, то и кода там в них, по идее, до��таточно не много.
То есть, мы получили такую декомпозицию, при которой чётко и понятно, что и в каком кусочке находится, при этом эти кусочки достаточно изолированы друг от друга и относительно просты (хоть и являются частью большой сложной системы).

Рассмотрим простой случай, когда производится работа над “неразделяемыми” данными, то есть, данными, которые не изменяются одновременно сразу несколькими пользователями. Например, user profile, или shopping cart (очень маловероятно, что в Вашу карту кто-то что-то ещё положит), или запрос в службу поддержки… Думаю, понятно, что практически в любой системе подавляющее большинство сценариев будет именно таким: крааайне маловероятно, что кто-то ещё будет менять те же данные (такие кейсы есть, но о них позже)

Поскольку AC относительно мал, отвечает за небольшой кусочек функциональности, конкурентности с данными никакой нет, то мы можем фактически свести его виду:

“Я умею сделать SELECT”. То есть, в достаточно большом количестве случаев нам может не понадобиться никакой дополнительной бизнес-логики в AC.
Показать цену для продукта?
Пожалуйста, SELECT * FROM Pricing WHERE ProductId = @id. Быть может, AND Date=@date.
По идее, поскольку данные у нас партицированы по сервису/BC, и мы уже не имеем имеем дела с некой таблицей Products, содержащей кучу полей, мы можем себе позволить эту звёздочку.
Мы можем себе позволить не иметь никакого ORM для этого AC и даже использовать DataSet. DataSet’ы – хорошие, пока не начинают применяться в немереных масштабах.
Это элементарно простой AC, выдающий цену продукта, профиль пользователя, наименование и описание продукта и т.д.

“Я умею обновить информацию”. Простой Update в базу данных. Мы не ожидаем, что кто-то ещё будет обновлять пользовательский профиль в то же самое время, это краааайне маловероятно, если не невероятно вообще. В “случае чего” же сработает правило “последний победил”, мы же всё равно так делаем! :) Что произойдёт в 99.9% систем, если на изменение профиля пользователя вдруг придут два запроса одновременно? (пользователь два раза нажал кнопку send?) Да ничего. Профиль запишется два раза и всего делов. Мы всё равно так делаем. По умолчанию. Но можно и не придерживаться умолчаний.

То есть, в достаточно большом количестве случаев наши AC будут простыми SELECT/UPDATE, что не может не радовать.

Для других, более сложных случаев с конкурентными данными используется CQRS, о чём, может быть, позже.

Comments (3) -

7/7/2011 7:42:25 PM

Евгений

"Быть может, AND Date=@date."
Так не бывает Smile На кой отеделу продаж история цен? Отгрузить по вчерашней? Ну, всякое бывает конечно, но решается не так обычно. Или не решается. Smile
К тому ж, как любой школьник увлекающийся программированием знает, что таблица истории цен выглядит примерно (но необязательно) так
id (id товара)|id_c (*опционально, id цены)|Price (цена)|_Period (дата, или дата-время когда установлена цена)|Mutota (*опционально, всякая муть, что только не придумывают)
Понятно что тут "=" не прокатит....
Жду с нетерпением про CQRS. Самое интересное у вас позже, да ещё и "может быть". Frown

Евгений Russia

7/8/2011 1:47:39 PM

Alexey Raga

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

По сути.
Udi, например, говорит, что нет такого понятия, как цена на продукт. Есть такое понятие, как "цена на продукт в определённый промежуток времени".
Ребята из отдела маркетинга, которые устанавливают цену, назначая новую цену продукту просто "добавляют новую запись в табличку прайсов", если образно.

Это открывает целый спектр возможностей.
Например, установить распродажную цену на определённый период.
Например, система становится агностична ко времени. То есть, в любой момент можно получить картинку на любой момент, достаточно знать только, скажем, orderId и дату.

Alexey Raga Australia

7/9/2011 8:27:30 AM

Евгений

Бывает, ну что ж не вопрос тогда. Тяните, делов то. Smile У многих бывает такое для Балмеров, вот я и предположил просто, что может не нужно в "простом" отделе.  
"Udi, например, говорит, что нет такого понятия, как цена на продукт. Есть такое понятие, как "цена на продукт в определённый промежуток времени". "
"Это открывает целый спектр возможностей."
"Например, система становится агностична ко времени. То есть, в любой момент можно получить картинку на любой момент, достаточно знать только, скажем, orderId и дату."
Udi смотрю любит говорить всякие прописные истины. Smile Тогда у меня возникает вопрос. Вы видели рабочие системы которые бы не могли того о чем вы написали????? (Может Udi видел? Неужто всё так запущено? Smile ) Ниже уже я где то писал - цена всегда периодическая велечина, со всеми вытекающими из этого. Всегда. Это как аксиома, и не зависит от каких либо параметров системы. (Тут опять упомяну школьников - по крайней мере я им так говорю. "Продумайте как будете хранить (и манипулировать) историю цен и так далее") А вы говорите про какие то открывающиеся возможности.

Евгений Russia

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