Еще одна серия постов из Telegram-канала «Архитектура ИС»
На этот раз о том, почему техника Domain Storytelling (далее DS) сорвав низко висящее яблоко, не съела его, а всего лишь понадкусывала.
Вообще, проводить анализ-дизайн в виде веселых групповых сессий с рисованием каракуль и развешиванием стикеров хорошо и правильно. Неправильно выходить с таких сессий без внятного результата. В DS совершенно справедливо полагается, что создать хорошую модель предметной области в DDD-подходе невозможно без обсуждения поведения. Именно это помогает нам определить агрегаты, репозитории, быть может даже ограниченные контексты. В общем, те сущности, которыми мы оперируем в domain driven design. Проблема DS в том, что всех этих агрегатов, объектов-значений и пр. в нём нет. Персоны есть, документы есть, даже e-mail и смартфоны есть, а вот агрегатов нет. Зачем же мы тогда проводим такие сессии?
Изначально в DDD было принято рисовать концептуальные карты (concept map). Это отличный метод, у которого есть всего лишь два недостатка. Первый заключается в том, что нарисовать при помощи концептуальной карты можно примерно всё. Т.е. метод настолько универсален, что мало отличается от набросков на салфетке и поэтому и методом то может называться с большой натяжкой. Проблема номер два: концептуальная карта – это граф. Рисовать его более-менее просто, а вот читать нет. Нету в нем сжатия информации и потому эффекта мгновенного понимания ожидать от такой картинки не следует. Ну и вспоминая основную находку Domain Storytelling – совмещение описания структуры и описания поведения, мы вынуждены признать, что в концептуальных картах DDD этого тоже нет. В общем, максимум для чего они годятся – выделять границы контекстов
Описание на одной картинке структуры и поведения – сложная задача. В 60-70 годы прошлого века в картографии случилась своя технологическая революция – появление геоинформационных систем (ГИС). Собираемые для отображения на карте данные перестали сразу же наносить на бумагу, а стали складывать в структурированные хранилища. Затем программа вбирала из такого хранилища нужные для визуализации на данной конкретной карте вещи, отображаемые слои и т.п. и формировала изображение. По аналогии с картографией в ИТ-архитектуре появилась идея единого репозитория из которого формируются нужные для решения данного класса задач и понятные для некоторой группы заинтересованных лиц представления (view). Но проблема ИТ-архитектуры в том, что никто толком не научился совмещать на одной картинке разные слои. Рисовать в одном представлении, например, и структуру и поведение.
Вернемся к DDD и поговорим об описании агрегатов [1]. Агрегат – это кластер нескольких объектов предметной области, рассматриваемых как единое целое. Эффектный, но не особо эффективный способ отображения таких кластеров – представление их в виде молекулы. В центре корень агрегата (aggregate root), к которому крепятся сущности и объекты значения. В таком формате представления отсутствует ряд важных моментов. Во-первых, часть ветвей являются взаимоисключающими. Например, в агрегате заказ вы либо забираете его в пункте самовывоза, либо просите доставить курьером на дом, но никак не одновременно. Другие элементы заказа, такие как набор покупок, взаимоисключающими не являются. Более того, агрегат — это не вполне дерево. Разные ветки могут быть связаны довольно сложными зависимостями
Чем заменить концептуальную карту (молекулу) при моделировании DDD агрегата? За ответом ходить далеко не надо. Достаточно заглянуть в статью Википедии Представление знаний . Сразу же после семантической сети , а это была именно она, следует раздел Фреймы. Фреймы для представления знаний любимы не только в экспертных системах, но и в среде архитекторов. Наверняка вам доводилось видеть картинки-этажерки или холодильники, в которых по полкам (слотам) по определенным правилам размещаются те или иные вещи (бутылки на полку, пельмени – в морозильник). Вот это и есть фреймы. Значительная часть агрегатов неплохо моделируется фреймами. Вспомните заказ из предыдущего примера
Удивительно то что, когда нужно пояснить что такое агрегат на пальцах, даже такие великие эксперты как Мартин Фаулер рисуют именно холодильник(фрейм) https://martinfowler.com/bliki/AggregateOrientedDatabase.html Однако, коль речь заходит о серьезной статье, место понятных картинок занимают UML диаграммы классов и фрагменты кода. Правилом хорошего тона считается включать именно фрагменты кода, даже если в них нет какой-либо логики и просто приведены названия методов и структура данных
Кстати, стрелки на этой картинке направленны не в ту сторону. Скорее всего они олицетворяют ссылки на таблицы, но для совмещения описания поведения со структурой нам понадобиться другая логика в направлении стрелок
В представлении знаний фреймами нет ничего необычного. Скорее наоборот. Мы настолько часто с этим встречаемся, что просто не замечаем этого. Так что еще пара примеров. Бланк заявления (форма), включающий несколько разделов, заполняемых разными людьми. Какие-то разделы такого бланка обязательны. Необходимость заполнения других зависит от предыдущих разделов. Kanban-доска, по которой путешествуют стикеры работ. Бизнес-процесс, представленной сетью Петри …, впрочем, это мы уже спешим и переходим к отображению поведения
Пора переходить к поведению. Что это такое? Из чего оно состоит? Можно довольствоваться утверждением, что поведение – это последовательность событий, запросов и команд (events, queries, commands) и дальше разбирать каждое из них, но слово последовательность я бы заменил на параллельность если бы такое существовало. Последовательностью это было во времена появления клиент-серверных архитектур. Всё моделирование поведения, к сожалению, предполагает контекст, когда пользователь утром включает алфавитно-цифровой терминал, устанавливает соединение с сервером и отправляет ему команды в синхронном режиме. Сегодня даже в бизнес-процессах – очень поверхностном подходе к описанию поведения, принято смещать акцент с оркестровок на хореографии. А информационные системы, с десятками одновременно исполняемых, а часто и взаимодействующих друг с другом, процессов только на одном узле – это уж точно не про оркестровки. Тем не менее, давай чуть подробней поговорим о событиях, запросах и командах…
Осталось совсем немного. Всего пара реплик. Сначала о структуре активности. Есть много источников, чтоб подсмотреть какие объекты может объединять операция. Я взял вот отсюда: https://www.w3.org/TR/activitystreams-vocabulary/
actor | object | target | result | origin | instrument
вы можете воспользоваться другими источниками. Главное – понимание того, что операция является N-мерной ассоциаций, собирающей множество разных объектов. Помимо глагола это: инициирующий операцию actor и object, с которым операция производится. Target и origin – куда и откуда перемещается actor-ом наш object, Помните, агрегат — это шкаф с набором полок; при помощи чего эта операция производится (название API или экранной формы, в общем объект boundary из robustness diagram)
Вспоминая картинку Фаулера, мы скорее нарисовали бы эту историю так: авторизованный пользователь при помощи формы выбора способа оплаты выбирает для данного заказа один из использованных ранее платежных инструментов. С точки зрения DDD в заказе создается объект-значение (value object). Он не будет меняться, даже если в дальнейшем мы отредактируем или удалим этот способ оплаты в клиентском профиле