Обзор книги “What Is Domain-Driven Design?”
DDD
или Domain Driven Design
— это концепция введенная Эриком Эвансом в одноименной книги в 2003 года, а значит ей скоро исполнится 20 лет. Казалось бы такого срока достаточно для повсеместного принятия этой концепции, ведь она действительно стоящая, но нет. И мне кажется, что проблема в том, что достаточно сложно понять саму концепцию, а дальше начать ее применять. С первым пунктом нам поможет книга “What Is Domain-Driven Design?
” за авторством Vladik Khononov, которую мы разберем здесь, а со вторым пунктом Event Storming
, который мы подробно разберем в следующий раз, а в этот раз ограничимся кратким описанием.
Начнем, пожалуй, с содержимого книги, которое представлено на рисунке ниже. В первой части рассматриваются инструменты и техники для стратегического дизайна, во второй — для тактического, а на закуску рассматривается как перенести инструменты из первых двух частей из теоретической плоскости на практическую.
Update
Vladik Khononov выпустил полноценную книгу Learning DDD
, которая дополняет и расширяет этот отчет. Сравнение этого отчета и книги можно прочитать в статье Сравнение книг “Learning Domain-Driven Design” и “What is DDD”.

Strategic Design
В этом разделе затрагивается анализ бизнес домена, обмен знаниями и общее принятие стратегических решений. Начинается все с
Analyzing Business Domains
Бизнес домен определяет общую деятельность организации. Поддомен в свою очередь — это хорошо очерченная зона активности внутри всего бизнес домена. Поддомены можно поделить на три вида: core
, generic
и supporting
. Каждый из них имеет свои особенности, перечисленные ниже:

Важно отметить, что доменным экспертом (domain expert
) в подходе DDD
является не аналитик, собирающий требования, или архитектор, проектирующий систему, а представитель бизнеса или конечный пользователь проектируемой системы.
Discovering Domain Knowledge
Для общения коллег между собой в DDD
используется Ubiquitous Language
, который является языком бизнеса (не техническим языком) и содержит термины, относящиеся к бизнесу. Важно, чтобы на этом языке говорили как представители бизнеса, так и инженерная команда. Этот язык должен быть точным и консистентным, а значит он не должен содержать неоднозначных терминов или синонимов, означающих приблизительно одно и то же. Интересно, что
The ubiquitous language is a model of the business domain
А так как сам бизнес домен может меняться во времени или у нас может улучшаться его понимание, то следом за этим меняется и сам наш ubiquitous language
.
Managing Complexity with Bounded Contexts
Иногда для одного и того же слова в ubiquitous language
мы должны использовать уточнения, например, для пользователя заказ еды — это одно, для ресторана, куда пришел этот заказ — это второе, а для курьера, что доставляет еду — это что-то третье. В итоге, мы не можем использовать общий ubiquitous language
для всей организации. Выходом становится разделение ubiquitous language
на множество маленьких языков с прикреплением их к явным контекстам, которые мы будем называть bounded context
. Интересно, что bounded context
определяет границы ubiquitous language
, в рамках которых термины являются консистентными. Размер этих контекстов не является решающим фактором при нарезке — главное, чтобы наша модель оставалась консистентной. Интересно отметить различие между bounded contexts
и subdomains
— поддомены являются частью бизнеса и поэтому они есть и их надо просто обнаружить, а контексты проектируются. Bounded Context
определяет физические границы проектируемых систем, а также может служить границей владения и ответственности за систему (ownership boundary
).
Context Mapping
Точки соприкосновения между bounded contexts
называются контрактами. В этих местах команды, отвечающие за разные контексты, взаимодействуют друг с другом. Существуют следующие паттерны взаимодействия: cooperation
, customer-supplier
, separate ways
.
В режиме cooperation
у нас есть 2 опции:
partner
, когда две команды владеют разными контекстами и могут просто договориться об изменениях в контракте. Причем договороспособность тут двухсторонняя и ни у кого нет переговорной силы форсировать свое решение- или
shared kernel patterns
, когда общие части разных доменов выделяют в отдельную часть и дальше ей владеют несколько команд. В общем и целом, это противоречит подходу с владением однимbounded context
одной конкретной командой, поэтому возможны проблемы. Чтобы их не случилось ниже приведена рекомендация по имплементации этого паттерна
The key to implementing the shared kernel pattern is to keep the scope of the shared kernel small, and limited to the integration contract only
В режиме customer-supplier
поставщик сервиса (service provider
) называется upstream
и потребитель сервиса downstream
. В этой конфигурации возможны разные распределения влияния между поставщиком и потребителем и для каждого варианта есть свой паттерн.

Separate ways
— это способ коммуникации, который состоит в ее отсутствии, так как команды идут своим путем. Причинами для этого могут быть:
- проблемы в коммуникациях — когда дешевле реализовать самому, чем договариваться с соседней командой
- система из
generic subdomains
— в этом случае можно просто поднять инстанс готового решения на своей стороне - разница в моделях внутри разных контекстов — дороже выйдет их унификация, чем отдельной развитие
Отдельно стоит сказать, что подход separate ways
не стоит использовать для проблем из core subdomains
.
Для того, чтобы понять какие у нас есть домены, мы можем построить Context Map
и отобразить какие у нас есть взаимоотношения между разными контекстами. Скорее всего такая карта даст определенные стратегические инсайты на разных уровнях:
High-level design
— обзор компонентов системы и моделей, который они реализуютCommunication patterns
— можно будет увидеть паттерны коммуникации разных команд и предпочтительные паттерны интеграции из перечисленных вышеOrganizational issues
—можно будет увидеть организационные моменты во взаимодействии междуconsumers
иproducers
Дальше мы переходим к
Tactical Design
И начнем с главы про
Business Logic Implementation Patterns
Автор выделяет 4 паттерна: transactional script
, active record
, domain model
и event-sourced domain model
. Подробнее про них ниже

Architectural Patterns
Автор выделяет 3 вида архитектур. На самом деле вариантов больше и про них можно прочесть в книге “Fundamentals of Software Architecture” от Neal Ford, Mark Richards (по ссылке мой обзор этой книги). Если возвращаться к видению автора, то вот 3 его архитектуры:
- слоеная архитектура (
layered architecture
) - порты и адаптеры (
ports & adapters
) command & query responsibility segregation
(CQRS
)

Отдельно есть смысл рассмотреть CQRS
архитектуру. На рисунке ниже оранжевым выделены части CQRS
подхода, а желтым характерные особенности этих частей.

Integration of Bounded Contexts
Мы уже раньше обсуждали паттерны взаимодействия команд из связанных bounded contexts
, а теперь поговорим про то, как их правильно интегрировать.

DDD in Practice
Дальше мы переходим к тому, как начать применять DDD
на практике.
Event Storming
Это групповая техника моделирования, которая упрощает процесс получения знаний о домене и формировании ubiquitous language
. Шаги этого процесса представлены ниже. Интересно, что цвета шагов совпадают с рекомендованными цветами стикеров для карточек, которые в основном используются на каждом шаге.

Пройдемся по этим шагам:
unstructured exploration
— на этом шаге в режиме брейншторма все участники группы самостоятельно накидывают на доскуdomain events
timelines
— сгенерированные на предыдущем шагеdomain events
выстраиваются в хронологическом порядке, начиная сhappy path
commands
— на этом шаге добавляютсяcommands
, которые описывают что именно триггерит событие или поток событий. У части команд естьactor
, который и запускает выполнение командыpolicies
— на этом шаге идет разбор команд, которые не имеютactor
. У таких команд естьpolicy
, когда запускается такая команда, обычно она завязана на наступление какого-то другогоdomain event
external systems
— на этом шаге модель расширяется внешними системами, которые не являются частью домена, что разбирается, но которые участвуют в процессе, например, исполняютcommand
или получают нотификации оdomain events
aggregates
— когда все команды и события на месте, участники могут начать задумываться об оптимизации и выделенииaggregates
, которые получают команды и генерируют событияbounded contexts
— на последнем шаге время посмотреть на всю картину. Группы тесно связанныхaggregates
являются естественными кандидатами на определение границ дляbounded contexts
В общем, Event Storming
является очень хорошим инструментом для совместного моделирования сложной предметной области .
Evolutionary Design
Бизнес компании меняется, поэтому поддомены внутри организации могут менять свои типы, которых всего три: core
, generic
, supporting
. Например, могут происходить переходы вида
core
→generic
, например, когда другая компания выходит на рынок с коробочным решением илиSaaS
сервисом, который повторяет core логику компанииgeneric
→core
, например, когда стандартная активность внутри компании реализуется так хорошо, что ее можно начать продавать наружу как сервисsupporting
→core
Одним из симптомов изменений типа поддомена является неспособность существующего технического дизайна дальше поддерживать текущие потребности бизнеса. В итоге, техническое решение вынуждено эволюционировать, так как домен зачастую становиться сложнее:
transaction script
→active record
active record
→domain model
domain model
→event-sourced domain model
В то же время может меняться и сама организация, а именно могут расти центры разработки и становиться географически распределенными. Помимо этого могут менять паттерны коммуникаций и коллабораций команд:
shared kernel
→partnership
, так какbounded contexts
, принадлежащие раньше одной команде разъезжаются по разным, то имеет смысл переходить к партнерствуpartnership
→customer-supplier
— по мере роста организации коммуникации между командами слабеют и все сложнее поддерживать партнерские отношения и они переходят к отношениям поставщик-потребительcustomer-supplier
→separate ways
— по мере нарастания коммуникационных проблем схема поставщик-потребитель становится все менее привлекательной и команды переходят к самостоятельному развитиюseparate ways
→partnership or customer-supplier
— когдаgeneric
илиsupporting subdomain
становитсяcore
, появляется потребность унифицировать работу над ним и уйти от его параллельного развития разными командами
Интересно, что качество знаний о доменной логике напрямую влияет на размер bounded contexts
- если
domain logic
неясна, то проектируйbounded contexts
с широкими границами - если
domain logic
стабильна, то проектируйbounded contexts
с более узкими границами, которые могут быть реализованы посредством микросервисов
Getting Started
Для того, чтобы начать пригодится понимания содержания описанных в отдельных главах концепция
— Ubiquitous Language
— Business Domain
— Context Map
— Bounded Contexts
— Event Storming
— Tactical Patterns: Value Object, Transaction Boundaries, Event-Sourced Domain Model
Итого
Книга действительно хороша и дает быстрый и достаточно глубокий обзор основных концепций Domain Driven Design
, раскрывает плюсы этого подхода и рекомендует как начать его практиковать с нуля.
Источники
- What Is Domain-Driven Design? — book by Vladik Khononov
- Introducing EventStorming — book by Alberto Brandolini
- Fundamentals of Software Architecture — book by Neal Ford, Mark Richards, ссылка на мой обзор
- Domain-Driven Design: Tackling Complexity in the Heart of Software — book by Eric Evans
- Domain-Driven Design Distilled — book by Vaughn Vernon