Similar presentations:
Тактические паттерны DDD - Lite
1.
Тактические паттерныDDD-Lite
2.
3.
Сущности(Entities)
4.
Идентифицируемые доменныеконцепты
Сущности должны обладать
надежными и неизменяемыми
идентификаторами, так как
даже полное совпадение
атрибутов концептов не
гарантирует их идентичности
все атрибуты сущности могут
измениться
5.
Сущности чаще всего выражены существительнымиФизические или
материальные объекты
Места размещения
объектов (Places)
Операции (Transactions)
Роли (например
Потребитель, Продавец)
Контейнеры концепций
(Containers for other
Concepts)
Внешние системы
(например Удаленная база
данных)
Абстрактные понятия (Abstract
Nouns) (например Жажда)
Организации
События (например Авария)
Правила/Политики
Записи/Протоколы
6.
У сущностей есть жизненный циклИзменение состояния со временем
Сущности идентифицируемы, и могут быть
отслежены по идентификаторам
При проектировании сущности больше
внимания уделяется их идентифицируемости
(вопрос «Кто») чем их свойствам (вопрос
«Какие»)
Не должны слепо отображать сущности
реального мира (“Model the Real‐World”)
7.
An entity is anything thathas continuity through a
life cycle and has
distinctions independent
of attributes ...
Eric Evans
8.
1.2.
3.
Выделяем идентификатор
Включаем атрибуты по которым
осуществляется запрос (возможные ключи)
Добавляем поведение которое связано с
этими атрибутами
Все остальное можно вынести в поведение
атрибутов (Value Object) или в бизнес сервисы
(Business Services)
4.
5.
Определяем роли и ответственности
Вводим механизм валидации
9.
10.
ПриродаБизнес идентификаторы (Natural Keys)
Генерируемые идентификаторы
▪ Инкрементальные
▪ Глобально уникальные (GUIDs/UUIDs)
▪ Строковые
Происхождение
Введенные пользователем
Генерируемые доменной моделью
Генерируемые базой данных
Генерируемые внешним контекстом
11.
GUIDf36ab21c-67dc-5274-c642-1de2f4d5e72a
содержит
Время создания в миллисекундах
Адрес сервера (IP)
Идентификатор процесса, виртуальной машины (JVM)
Случайное число
Крайне неудобен для отображения и
пользовательского ввода
Может быть преобразован в читаемую форму
APM-P-08-14-2012-F36AB21C
12.
Чаще всего реализуется соответствующим репозиториемМомент идентификации
При сохранении
При создании объекта
13.
Поведение – изменение состояния объекта,реализуется в ООП посредством методов
класса
Поведение чаще всего приписывается
сущности
Если нет подходящих сущностей, то пробел
заполняю порождая (выделяя) новые сущности
Думайте о сущностях скорее как о единицах
поведения, нежели как о единицах данных
(“Tell Don’t Ask”)
14.
Реализация поведения с использованием методов set,get свидетельствует о слабом коде
Если все поведение сводится к смене состояния, лучше
использовать метод с осмысленным именем
Например вместо setActive(boolean) используем методы
activate() / deactivate()
(Intention Revealing Interface)
Если смена состояния сопровождается дополнительной
логикой (например проверкой допустимости операции), то
использовании методов установки (set) зачастую является
симптомом запаха «Класс данных» (Data Class),
всю работу класса вынуждены выполнять клиенты
15.
Исключив обращение к методам get и setиз бизнес логики мы зачастую не можем
убрать их из сущности, так как они
используются механизмами других слоев
приложения (стандарт JavaBean)
В частности, слоем сохранения
Можем использовать паттерн Хранитель
(GoF Memento) для решения этой
проблемы
16.
Побочный эффект это изменениефункцией какого-либо состояния, или
взаимодействие с объектами внешнего
мира
Побочные эффекты выносятся из сущности
в бизнес службы
Пишем функции свободные от
неожиданных побочных эффектов
(Hidden‐Side‐Effect‐Free Functions)
Замкнутые операторы
17.
Доступ к службам может быть реализованследующим образом
Двойная диспетчеризация
Передача службы в параметрах метода
Команда (GoF Command Pattern)
Для создания сущности не нужен контейнер
инверсии управления (IOC)
Использовать службу обнаружения для
разрешения внешнего объекта внутри метода
(Service Locator Pattern)
18.
19.
20.
Ответственность (responsibility) класса выраженаего интерфейсом
Распределение ответственностей между классами
регламентируется принципами SOLID (от Роберт C.
Мартина) и паттернами GRASP (Крейга Лармана)
Если в различных контекстах с различными
клиентами класс обладает различными
ответственностями, говорим о различии ролей
класса
Согласно принципу разделения интерфейса (ISP)
каждая роль должна быть представлена отдельным
интерфейсом
Иногда конкретная роль связана с состоянием класса
21.
Основная ответственность сущностейидентифицируемость
Поведение как изменение состояния не
ключевых атрибутов должно быть
перемещено в объекты значения или с
бизнес сервисы
При перемещении в объекты значения
зачастую происходит нарушение закона
Деметры (The Law of Demeter (LoD))
игнорируем этот факт
22.
Dealing with Roles[Martin Fowler]
23.
Избегаем паттернасостояние (State)
используем явные
модели состояний
24.
Виды валидацииПрограммирование по контракту (DoC,
защищенное программирование) требует
соблюдение определенных предусловий и
поддержки инвариантов
Поддержка бизнес правил и целостности,
зачастую требуют более существенных,
дорогих проверок в которых могут участвовать
несколько сущностей
25.
Само-валидирующиеся (Self‐Validating)сущности
Сущность никогда не должна быть в не
валидном состоянии
26.
Внутренняя инкапсуляцияself-encapsulation
предохранители
guards
27.
Имеет большее отношение к реализацииагрегата
Паттерны
Спецификации (Specifications)
[Evans & Fowler, Spec]
Стратегии (GoF Strategy)
[Gamma et al.]
Отложенная валидация (Deferred Validation)
Checks pattern language, Ward Cunningham
[Cunningham, Checks]
28.
Сущность должна принадлежать одномуклассу, одной доменной модели, одному
ограниченному контексту
Проблемный класс. Сущность используемая в разных контекстах
Необходимо отслеживать согласованность в распределенной системе
29.
30.
31.
Объекты-значения(Value Objects)
32.
Объекты-значения — этодескрипторы или свойства, важные в
той предметной области, которую вы
моделируете
Представляют данные измерений,
количества или описания объектов
Представляют состояние объекта но
не предполагают идентичности
(набор атрибутов без
идентификатора)
33.
... elements of the design thatwe care about only for what
they are, not for who or
which they are
Eric Evans
34.
Можно реализовать атрибут как простой типЗапах Одержимость простыми типами (Primitive Obsession)
Объекты-значения описывают свойства сущностей гораздо
более изящным и объявляющим намерения способом
Заметив их в интерфейсе или методе сущности, вы сразу
поймете, с чем имеете дело
Начинаем моделирование с объектов значений, и если они не
получают поведение (Запах «Ленивый класс» (Lazy Class))
расформировывать
Можно реализовать атрибут как сущность
нужно придумать идентификаторы которые потом могут не
понадобится
пострадает производительность (уникальность)
Flyweight pattern GoF
Предпочитаем объекты значения сущностям
35.
36.
37.
Деньги, популярный объект-значение,гораздо лучше выглядит как параметр
функции API передачи средств, чем просто
десятичное число
38.
39.
НеидентифицируемыОпределяются как эквивалентные по эквивалентности
всех атрибутов
Могут быть предоставлены в совместное использование
(share)
Желательно неизменяемые (Immutable)
Поведение реализуется как функции без побочных
эффектов (Side-Effect-Free Behavior)
При изменении бизнес логики полностью заменяемы
Описывают концептуально целостные объекты
Должны поддерживать высокую сцепленность (Cohesive)
Могут быть скомпонованы в единый объект (Combinable)
Само-валидирующиеся (Self‐Validating)
Никогда не должны быть в не валидном состоянии
40.
Устраняем сложность вносимуюидентификацией
Неприятие коллекций (Collection Aversion)
Считается, что не стоит создавать коллекции
объектов значений (тем самым формируя подобие
идентификатора)
Вместо этого предполагается именовать все
элементы в базовой сущности
IEnumerable<PhoneNumber> PhoneNumber
PhoneNumber HomeNumber; PhoneNumber WorkNumber;
41.
EntityValue Object
42.
С объектами-значениями мы хотим получитьфункции, свободные от побочных эффектов
Добавляя 20 рублей к 20 рублям, вы
изменяете 20 рублей?
Нет, вы создаете новый денежный
дескриптор 40 рублей
Неизменяемость проверяется модульным
тестом
Объект клонируют, выполняют операцию и
сравнивают с эталоном
43.
функция без побочных эффектов (Side-Effect-Free Behavior)44.
Атрибут часто меняетсяУдаление и создание слишком дорого
Замена объекта дорого обходится
Объектов не так уж и много
При выявлении необходимости
модифицировать объект нужно
рассмотреть вариант преобразования его
к сущности
45.
Нет смысла изменить объект, когда можно простозаменить его
Используя функции без побочных эффектов можно
производить замены объектов-значений даже при
изменениях в бизнес логике
46.
Элементы объекта значенияпредставляются как одно целое, и не
имеют смысла друг без друга
Паттерн «Целое значение» Whole Value
[Cunningham, Whole Value aka Value Object]
Цена имеет два атрибута 50 $, по
отдельности эти атрибуты либо ничего не
значат, либо имеют другое значение
47.
Зачем ?48.
Когда имеет смысл выделять один атрибут вобъект значение ?
Со значением связано определенное
поведение
Мы хотим прояснить концепцию, через
формирование информативного
интерфейса
Микро-типы (Micro Types, Tiny Types)
Стандартные типы (Standard Types)
49.
Клиент использует переданное значениепредварительно преобразовав его (например
переписав заглавными буквами)
Исключая дублирование логики и увеличивая
сцепленность кода выделяем объектзначение
50.
Обертка над примитивным типом,сделанная с целью прояснения концепта
51.
Стандартный тип –объект описывающий
тип другого объекта
(Паттерн проектирования
«Power Types»)
52.
Между объектами-значениями не можетбыть двунаправленных ассоциаций,
так как нет возможности ссылки если оба
объекта не идентифицированы
Если такая ассоциация возникает один из
объектов становится сущностью
53.
Статический метод создания (Static FactoryMethods)
Микро тип (Micro Types (Also Known as Tiny
Types))
Например Hours
54.
NoSQLSQL
Плоская денормализация (Flat Denormalization)
▪ Создание формата хранения (asString, toJson)
▪ Преобразование на сохранение
(Persisting Values on Save)
▪ Разбор на загрузке (Parsing Values on Load)
Нормализация
(Normalizing into Separate Tables)
55.
56.
57.
В этом случае объект-значение сохраняетсяв отдельной таблице и идентифицируется
суррогатным ключом
Схема данных и доменная модель приходят
к разногласию по поводу
идентифицируемости концепта
58.
59.
Ассоциации60.
Ассоциации нужно ограничивать помаксимуму
По возможности, избегать сложных
ассоциаций
61.
ДвунаправленныеОтношение многое ко многому
Ассоциации с ограничениями
62.
Избавляемся от двунаправленныхассоциаций
2. Избавляемся от связей многое на многое
3. Удаляем второстепенные ассоциации
(Модель это очищенное знание)
1.
P.S. Любое упрощение требует
дополнительного исследования домена
63.
• Стремимся устранить все двунаправленные ассоциации64.
65.
• Снижаем мощность ассоциации усложняя структуру классов66.
67.
68.
Заменяем прямую ссылку на идентификатор69.
Агрегаты и сводные корни70.
Для упрощения сложной доменноймодели концепты объединяют в
кластера по агрегированию
Правила агрегирования
Корень агрегации должен иметь
глобальный идентификатор
Внешние сущности ссылаются
только на корни
Удаление корня удаляет все
объекты в агрегате
71.
72.
Сводный корень — специальнаясущность, к которой напрямую
обращаются потребители
Определение сводных корней
позволяет избегать чрезмерного
соединения объектов, составляющих
модель
Следует отметить, что сводные корни
отчаянно стерегут свои подсущности
73.
Сводные корни — единственный видсущностей, на который может ссылаться
программа
Это позволяет избежать «Большого кома
грязи»,
потому что теперь у вас есть ограничение,
не дающее создавать тесно связанные
системы, где все сопряжено со всем
74.
75.
Есть сущность под названием полис(Policy)
Полисы продлеваются раз в год,
поэтому, вероятно, есть и сущность под
названием Period
Так как Period не может существовать без
Policy, а на Period можно воздействовать
через Policy, Policy является сводным
корнем, а Period — дочерней сущностью
76.
Policy.CurrentPeriod().Renew();— нарушение закона Деметры
«смерть от тысячи порезов» — хорошее
описание кошмара, которым может
стать поддержание слишком связанной
системы
77.
Policy.Renew();Cводный корень все делает сам
В своих внутренних сущностях он может
найти текущий период, определить,
наступило ли уже время продления, и
сделать все, что потребуется
78.
Агрегаты строятся по потребностямпользовательского интерфейса
Агрегаты это коллекции или контейнеры
объектов
Фокусируемся на связях Has-a
Агрегаты слишком большие
Проблемы с производительностью (большие
объемы загрузки, сложные запросы и т.д.)
Конкуренция (коллизии на транзакциях)
Слабая масштабируемость
Агрегаты слишком маленькие (пустые)
Нет должной защиты инвариантов
79.
Сколько запросовпонадобится для
вытягивания его в
память, какова
сложность этих
запросов
Сколько места в
памяти он займет
Какова вероятность
одновременных
запросов на
модификацию этого
агрегата
80.
Агрегаты высший уровень абстракциипредметной области
Обращаемся ко всем элементам агрегата как к
единому целому
Предпочитаем небольшие агрегаты
Идеально – одна сущность и несколько объектов
значений
Допускается пара дочерних сущностей
Агрегаты основа поддержки инвариантов
предметной области
81.
Инвариант – это бизнес-правило котороевсегда сохраняет свою непротиворечивость
(мгновенная и атомарная транзакционная
согласованность)
Например:
Инвариант