DDD - шаблоны
Фабрика
Цели
Сокрытие сложностей создания
Какому классу отдать предпочтение
Как осуществлять поддержку инвариантов
Ясное выражение вариантов создания экземпляров объектов
Централизация создания объектов
Когда использовать
Когда создание объекта становится слишком сложным
Если конструктор слишком сложный
Чтобы скрыть подробности агрегата
Фабричный метод
Когда использовать
Когда нужно вызывать различные конструкторы в агрегатах. Фабричный метод делает их вызов более выразительней
Чтобы восстановить объект из внешней службы
Там, где элементы логики конструирования не являются ответственностью зависимого класса
Репозиторий
Цели
Определение границ между предметными моделями и моделями данных
Скрывает технологию работы с данными
Ограничивает доступ к предметным объектам за счёт того, что работают только с агрегатами
Правила
Имена методов должны выражать предметные понятия
Предметные события
Технологии
БД
Подходы
Есть фреймворки, которые позволяют отобразить предметную модель в модель данных
Путём преобразования в модель данных и наоборот
Преобразование в JSON напрямую предметную модель
Можно использовать шаблон "Хранитель" для того, чтобы не светить внутреннее строение агренатов
Потоки событий
Хранилище хранит события и по ним воспроизводит агрегат
Транзакции
Работа с транзакциями должна происходить на прикладном уровне
Во фреймворках реализован шаблон "Единица работы" для транзакций
Единица работы внедряется в репозиторий и прикладной службе
Чтобы внедрить в репозиторий через метод, можно использовать отдельный интерфейс для репозитория с методом-сеттером
С единицей работы можно убрать необходимость сохранения за счёт фреймворка слежения за изменениями
Репозиторий как предохранительный слой
Может содержать метод count
Прикладные службы
Правила
Инфраструктурные задачи
Работа с транзакциями
Идентификаторы
Можно формировать как на стороне прикладной службы
Либо при сохранении
Можно выводить обобщённые сведения через модель Summary (например сумма покупок, количество активных пользователей и т.д.)
Обрабатывает исключения параллельного доступа
Может генерировать исключения при одновременном доступе
Может генерировать исключения при попытке работы пользователя с устаревшими данными
Может делать контрольные проверки перед записью
Может делать журналирование
Агрегаты
Правила
Необходимость делать отложенную загрузку - сигнал не правильно выбранных границ
Границы
Нужно основывать на бизнес-правилах, а не на потребностях пользовательского интерфейса
Все данные агрегаты необходимы для выполнения инвариантов. Если есть лишние данные - то это признак нарушения границ агрената
Нельзя делать отчёты
Объекты-значения
Правила
Незменяемы. В методах изменения всегда возвращается копия
Не имеет публичных свойств и экспортирует только поведение
Можно создавать предметные службы напрямую в агрегате
Только в случае, если у службы только одна реализация
Или не нужно подставлять фиктивные службы
Другие шаблоны
Карта соответствия
Identity map
Гарантирует, что возвращаемая сущность при извлечении всегда будет один и тот-же объект
Единица работы
Unit of work
Фиксирует все записи в репозиторий и применяет их после подтверждения
Могут быть двух видов
Команды
Запросы
Например, создать
В случае команды-создания возвращает идентификатор в виде числа или оборачивает в виде response DTO
На входе получает идентификаторы или request DTO
На выходе возвращает reponse DTO или списки DTO
На входе получает request DTO
Регистрация событий
ORM
C#
NHibernate
RavenDB
RavenDB Management Studio
На основе технологии Silverlight
Affka
Entity Framework
Реализация шаблона единица работы
Более зрелый, чем Entity Framework
Хранитель
memento
Интерфейс-маркер
Агрегат должен
SQL Server
Ncqrs
NEventStore
Kafka
Event Store Грэга янга
Регистрация событий
Разделение ответственности команд и запросов
Command Query Responsibility Segregation
CQRS
Правила
Агрегат фиксирует все предметные события в своё свойство
Агрегат умеет делать свои снимки и из них восстанавливаться
Репозиторий пишет события и оптимизирует загрузку за счёт снимков
Цели
Цели
Запросы
(Операции чтения)
Команды
(Операции записи)
Команды
Материализированные представления (кешированные представления, view caches)
Смегчение проблем взаимодействия различных сценариев
Уменьшить конфликты за доступ к единственному потоку
Фиксирование всей информации
Разделить отвественность большой модели на две более простые и специализированные
Обработчик команд
Правила
Моделируются как глаголы, а не существительные
Команды - это простые DTO
Агрегаты становятся компактнее
Репозитории максимально простыми
Правила
Это разновидность прикладных служб
Реализует только предметную логику, не должна содержать свойств для представления
Проходя через предметную модель помещаются в поток событий
Ответ содержит только результат операции
Правила
Запросы возвращают DTO для представлений
Нужно делегировать принятие решений на основе данных предметным службам и спецификациям
Нужно использовать легковесные ORM для того, чтобы быстро отображать данные в DTO модели представления
Масштабирование
Команды могут выполняться асинхронно через очередь сообщений
Это когда на предметные события в модели записи подписывается модель чтения и пишет себе нужно представление в хранилище
Для масштабирования запросов можно перенести предметные события в очередь запросов
Цели
Выполняют роль посредника между внешними службами и предметной областью
Формирование идентификаторов через репозиторий
Координация выполнения сценариев использования с предметной моделью
Производится проверка на правильность формата параметров
Проверяется не пустая ли строка
Формат электронной почты
Обрабатывает исключения и транслирует их представление
Взамен нужных предметных исключений можно выдавать общее исключение
Регистрация, оценка, мониторинг
Аутентификация и авторизация
Аутентификация - это вошёл или нет
Авторизация - это проверка привелегий
Публикация внешних событий
Обработка и публикация внутренних событий, производство ленты Atom
Симптомы просачивания предметной логики в прикладной уровень
Как определить являются ли шаги в прикладной службе предметной?
Если шаги нельзя выполнять раздельно, то это предметная логика
Если общение с предметным уровнем выразительное - то это хорошо
Отчёты
Netflix
Рекомендательная система на машинном обучении
Почитать про отчёты и анализе данных в системах DDD SOA можно в статье Ротем-Гал-Оза на сайте InfoQ
Структура
Контекст
Может делиться на бизнес-компоненты
Делятся на компоненты
Могут иметь связи между собой
Должны быть несвязанными
Признаки
Должен быть несвязанным с другими контекстами
Границы определяют
Неоднозначность терминов и предметных понятий
Ориентация на подобласти и бизнес-потенциалы компании (функционал)
Организация и физическое местонахождение групп разработчиков
Необходимость интеграции с унаследованным кодом
Необходимость интеграции со сторонними системами
Предметная область
Подобласть
Неспециализированная предметная область
Generic domain
Является универсальной, подходящей для любого корпоративного ПО
Смысловое ядро
core domain
То, что выделяет компанию от конкурентов и составляет конкурентные преимущества. То, что уникально для конкретного бизнеса
Это причина, из-за которой создаётся ПО
Поддерживающая область
Supporting domain
Всё остальное, что поддерживает систему и смысловое ядро в рабочем состоянии
То, что есть везде и не отличает от конкуретнов. Например - каталог товаров в Amazon
Термин
Предметная область - это окружение задачи, над которой работаем
Предметная модель - это абстракция предметной области, облегчённая в сторону программного кода.
Диспетчер процессов
Координирует несколько контекстов когда это нужно бизнес-процессам
Не имеют информации о своём состоянии, кроме шагов бизнес-процесса
Являются по своей сути процедурами
Не имеют состояния
Должны экспортировать функции, а не изменяться под требованием клиентов
Отчёты
Должны предоставлять отчёты, не раскрывая деталей модели