Как стать автором
Обновить

Стратегические паттерны DDD

Уровень сложностиСредний
Время на прочтение8 мин
Количество просмотров12K

Введение

Привет, Хабр! После того, как я углубился в мир DDD, прочитав множество книг, я решил поделиться с вами своими мыслями и наработками, которые, я надеюсь, окажутся полезными для разработки эффективных приложений вашим командам.

В данной статье мы погрузимся в мир DDD, сфокусировавшись на самом важном аспекте – модульности. Разберем стратегические паттерны, предоставляющие необходимые инструменты для эффективной организации модульности на уровне организации. Обсудим, как определить границы между контекстами, установить правила взаимодействия и эффективно управлять сложностью в разработке крупных бизнес-приложений.

Модульность

Рано или поздно каждый из нас сталкивается с необходимостью разделить что-то сложное на более мелкие, управляемые части. Это может быть вызвано желанием упростить задачу или необходимостью эффективного распределения ответственности.

В рамках крупных компаний с множеством функциональных команд часто встает вопрос о том, как оптимально распределить обязанности между ними.

Разделение ответственности следует проводить таким образом, чтобы минимизировать взаимодействие между разными частями системы. Это позволяет скрыть сложность за абстракциями и предоставить простой и понятный интерфейс для взаимодействия.

В контексте разработки программного обеспечения подобные принципы связаны с идеей модульности. Если цель — избежать создания сложного и трудно поддерживаемого кода, необходима четкая и модульная структура проекта. Но что, если требуется обеспечивать модульность в организации бизнес-процессов?

Здесь на помощь приходят стратегические паттерны DDD (Domain-Driven Design), предоставляя ценные рекомендации и решения для управления сложностью, абстрагирования различных аспектов бизнеса и установления четких границ между областями ответственности.

Domain и Subdomain

Домен (Domain) представляет собой нечто большее, чем просто техническое определение. В контексте разработки, это сфера деятельности или область знаний, тесно связанная с бизнес-процессами, которые ваше приложение воплощает. Рассмотрим пример: если ваш проект – интернет-магазин, то доменом будет охватываться весь цикл бизнес-процессов, начиная от управления продуктами и заканчивая обработкой заказов. Это абстрактное пространство, где технические и бизнес-аспекты взаимодействуют для достижения общей цели.

Поддомен (Subdomain) представляет собой уточненную часть более крупного домена, выделенную для детального анализа и организации. На примере интернет-магазина, поддомены могут включать в себя управление продуктами, обработку заказов, учет клиентов и другие аспекты деятельности. Каждый поддомен фокусируется на конкретной области и предоставляет структурированный подход к ее реализации.

Важно отметить, что каждый поддомен, со временем и с ростом бизнеса, может вырасти в отдельный домен. Большой интернет-магазин, например, может иметь множество подразделений, каждое из которых представляет собой отдельный домен. Однако не все эти домены будут иметь одинаковую степень важности. Некоторые из них будут являться ключевыми (Core domain), в то время как другие могут оставаться вспомогательными.

Целевая структура в случае поддоменов напоминает матрешку, где каждая внутренняя часть представляет собой более узкую, специализированную область, а внешние слои представляют более широкие и общие области. Это значит, что каждый поддомен может выступать доменом для своих дочерних поддоменов.

Bounded context

Теперь, когда мы имеем представление о том, что такое домен и поддомен, настало время глубже погрузиться в мир ограниченных контекстов, ключевого элемента методологии Domain-Driven Design (DDD). Ограниченные контексты — это стратегический инструмент, который помогает эффективно управлять сложностью внутри наших систем.

Представим, что у нас есть система управления персоналом в интернет-магазине. Этот домен включает в себя несколько подобластей:

  1. Управление сотрудниками: Включает в себя информацию о сотрудниках, их персональные данные, навыки, опыт работы и другую связанную информацию.

  2. Управление зарплатой: Отвечает за расчет и выплату заработной платы сотрудникам, учет отработанных часов, вычеты и так далее.

  3. Управление обучением: Занимается отслеживанием учебных программ, пройденных курсов и обучающих мероприятий для сотрудников.

  4. Управление вакансиями: Отвечает за информацию о доступных вакансиях в организации, найм новых сотрудников и процессы отбора.

Допустим, мы решаем внести изменения в механизм расчета заработной платы. В рамках единой системы такие изменения могут потребовать корректировок в общих компонентах, связанных с управлением сотрудниками, обучением и вакансиями. Однако введение общих компонентов там, где они не обязательны, может спровоцировать появление частых ошибок и увеличение сложности процесса тестирования. Кроме того, неправильно определенные границы ответственности могут привести к созданию моделей, аналогичных приведенной ниже:

export class Employee {
  id;
  name;
  skills[];
  experience;
  experienceRate;
  personalDetailsForSalary;
  personalDetails;
  hourlyWage;
  hoursWorked;

  addSkill()
  upgradeLevel()
  addWorkingHours()
  calculateWageWithoutTax()
}

Модель сотрудника, как она есть сейчас, включает в себя как навыки, так и количество отработанных часов – это всего лишь малая часть всей информации, которая может потребоваться. Представьте, какой монструозной будет модель спустя некоторое время! Она будет содержать кучу логики из различных областей бизнеса, и разобраться в этом будет ой как непросто. Но что делать? Давайте разделим систему на контексты!
Ограниченные контексты используются для установки логических границ пространства решений предметной области, чтобы лучше управлять сложностью. В DDD ожидается, что каждый ограниченный контекст будет иметь свой единый язык.

  1. Контекст Управления Персоналом — общий контекст, охватывающий все аспекты управления персоналом. Включает в себя основные функции, связанные с сотрудниками.

  2. Контекст Зарплатного Учета — сфокусированный на функциях, связанных с расчетом и выплатой заработной платы, учетом отработанных часов и вычетами.

  3. Контекст Обучения и Развития — сфокусированный на функциях, связанных с обучением, отслеживанием учебных программ и курсов для сотрудников.

  4. Контекст Найма и Отбора — сфокусированный на функциях, связанных с информацией о вакансиях, процессами найма новых сотрудников и отбором кандидатов.

Если при переходе из одной функциональной области в другую вы замечаете, что правила, терминология и модели приобретают уникальные свойства и значения, это является сигналом к рассмотрению возможности установки ограниченных контекстов!

Теперь управление сотрудниками содержит свою модель:

export class Employee {
  id;
  name;
  skills[];
  experience; // количество проработанных лет
  personalDetails; // детали по сотруднику
  
  addSkill()
  upgradeLevel()
}

А контекст управления зарплатой — свою:

export class Employee {
  id;
  hourlyWage;
  hoursWorked;
  experience; // коэффициент опыта, на который умножается премия
  personalDetails; // детали только для зарплаты

  addWorkingHours()
  calculateWageWithoutTax()
}

Важно отметить, что вездесущий язык (ubiquitous language) внутри контекста — это модели и связанные с ними поведения и термины. Выбор контекстов зависит от того, какие аспекты системы важны в каждой подобласти и какие правила и модели требуется определить внутри каждого контекста. Ограниченные контексты позволяют избежать избыточной сложности и улучшают модульность системы, делая ее более гибкой и легкой в поддержке.

Subdomains внутри bounded context

Каждый поддомен в рамках ограниченного контекста олицетворяет определенный аспект бизнеса и содержит свои собственные модели, правила и терминологию. Ограниченный контекст лишь определяет область, в которой действуют определенные поддомены, и обеспечивает логическую изоляцию между различными частями предметной области.

Более того, принято выделять типы поддоменов внутри контекста. Определение типа поддомена в контексте означает указание на то, какая роль или функция у поддомена в пределах данного ограниченного контекста. Проще говоря, это определение, какой вклад или задачу выполняет этот поддомен в рамках конкретной области предмета.

Типы поддоменов выделяют следующие:

  1. Core: Относится к поддомену, содержащему ключевые бизнес-процессы и функциональность в пределах конкретного ограниченного контекста. Включает в себя бизнес-логику, которая является основной для данного контекста.

  2. Generic: Поддомен, ориентированный на общность и переиспользование. Содержит компоненты и функциональность, которые могут быть общими для различных контекстов или даже систем.

  3. Supporting: Связан с поддерживающими аспектами, не являющимися ключевыми бизнес-процессами. Включает функциональность, которая может облегчить разработку, но не является основной для бизнеса в данном контексте.

Довольно часто мы можем встретить случаи, когда одни и те же поддомены в разных контекстах имеют разные типы. Давайте рассмотрим наглядные примеры и вернемся к обсуждению. Представим что мы делаем с вами систему управления компетенциями. Определим типы поддоменов:

  1. Управление сотрудниками (Core Subdomain) — здесь будут содержаться ключевые данные о сотрудниках, и их компетенции будут рассматриваться как неотъемлемая часть основных бизнес-процессов.

  2. Управление зарплатой (Supporting Subdomain) — учет компетенций может быть вспомогательным аспектом при расчете заработной платы, и эта информация может быть использована для определения премий или бонусов.

  3. Управление обучением (Core Subdomain) — в данном контексте управления компетенциями, обучение напрямую связано с развитием компетенций сотрудников, и поэтому является основной частью процесса.

  4. Управление вакансиями (Supporting Subdomain) — требования к компетенциям могут быть вспомогательным элементом вакансий, которые могут помочь при подборе подходящих кандидатов.

А теперь представим, что у нас есть ещё система управления персоналом в большой розничной компании, где основной акцент на максимизации продаж. Рассмотрим те же подобласти в этом контексте:

  1. Управление сотрудниками (Core Subdomain) — в данном контексте, где ключевая цель - обеспечение качественного обслуживания клиентов, информация о сотрудниках может быть ключевым элементом основных бизнес-процессов.

  2. Управление зарплатой (Supporting Subdomain) — в контексте розничной торговли управление зарплатой может рассматриваться как вспомогательная функция, обеспечивающая корректные выплаты, но не являющаяся центральным элементом бизнес-стратегии.

  3. Управление обучением (Supporting Subdomain) — обучение персонала может быть важным, но не являться ключевым для розничной компании, где более актуальными могут быть операционные процессы.

  4. Управление вакансиями (Core Subdomain) — в данном контексте, где максимизация продаж ключевая задача, управление вакансиями может играть важную роль в найме квалифицированных сотрудников для обеспечения эффективной работы магазинов.

В первом примере фокус был на управлении компетенциями, а во втором примере мы рассмотрели контекст максимизации продаж с другими акцентами на одних и те же поддоменах. Как вы смогли убедиться, для разных систем одни и те же поддомены могут иметь разную значимость.

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

Например, Core subdomain является ключевым, поэтому хорошо бы по особенному отнестись к его проектированию. В то время как Generic и Supporting можно закрыть вообще аутсорсом/покупкой готового решения. Используйте знания о типах поддоменов, они могут дать много информации, которая поможет в управлении командой.

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

Заключение

Установка границ в Bounded Contexts, напоминающая принцип единственной ответственности, вносит ясность в организацию и структуру системы. Этот принцип гласит: "Что принадлежит одной области, должно оставаться в этой же области". После определения логических границ, наша работа становится более управляемой, поскольку области ответственности четко очерчены. Разделение достигается путем сокрытия сложных бизнес-правил и предоставления узкого и стойкого интерфейса.

Для успешного разделения систем и бизнес процессов вам необходимо искать конфликты в ваших моделях. Разделяйте ответственность, ищите поддомены. Сделайте так, чтобы каждая команда и система работала в своем изолированном контексте. Безусловно, можно поддерживать несколько контекстов, но ни в коем случае не старайтесь эти контексты смешивать. Внутри контекста желательно определять как вы взаимодействуйте с теми или иными поддоменами, чтобы иметь возможность определять приоритеты и принимать решения по дизайну архитектуры.


В результате предоставленных рекомендаций получается набор ценных стратегий для эффективного управления сложностью системы. Эти рекомендации направлены на создание более модульной, гибкой и легко поддерживаемой системы.

Теги:
Хабы:
Всего голосов 15: ↑12 и ↓3+9
Комментарии1

Публикации

Истории

Работа

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
14 сентября
Конференция Practical ML Conf
МоскваОнлайн
19 сентября
CDI Conf 2024
Москва
20 – 22 сентября
BCI Hack Moscow
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
25 сентября
Конференция Yandex Scale 2024
МоскваОнлайн
28 – 29 сентября
Конференция E-CODE
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн