Какие три основные принципы DDD?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Три основных принципа Domain-Driven Design (DDD)
Domain-Driven Design — это стратегический подход к разработке сложных программных систем, который фокусируется на сложных доменах (предметных областях) и их бизнес-логике. Его основная цель — создание гибкого, поддерживаемого кода, который точно отражает реальные бизнес-процессы. Три ключевых принципа DDD, образующих его концептуальное ядро, это:
1. Фокусировка на ядре предметной области (Domain-Centric Design)
Первый и главный принцип — это смещение фокуса всей разработки на предметную область (домен) и её бизнес-логику. Технические аспекты (базы данных, фреймворки, API) становятся вторичными. Разработчики, архитекторы и эксперты-доменщики (business experts) должны говорить на одном языке и совместно создавать модель, отражающую реальные бизнес-процессы.
Ключевые практики:
- Глубокое погружение в домен (Deep Modeling): Недостаточно поверхностного понимания. Нужно вникать в нюансы, исключения и правила бизнеса.
- Постоянное обучение: Домен постоянно эволюционирует, и модель должна эволюционировать вместе с ним.
- Разделение на поддомены (Subdomains): Сложный домен делится на более мелкие части:
* **Core Domain:** Самая ценная и уникальная часть бизнеса, ради которой существует система. На неё тратится основное внимание и лучшие ресурсы.
* **Supporting Subdomain:** Вспомогательные процессы, специфичные для бизнеса, но не дающие конкурентного преимущества (например, расчёт сложных налогов).
* **Generic Subdomain:** Стандартные, решаемые готовыми решениями задачи (например, аутентификация, отправка email).
Пример на Go, показывающий фокус на домене, а не на технике (например, на JSON или БД):
package order
// Доменный объект (Entity) "Заказ". Его структура и поведение определяются бизнес-правилами.
type Order struct {
ID OrderID
CustomerID CustomerID
Items []Item
Status OrderStatus // (Created, Paid, Shipped, Cancelled) - важные для бизнеса состояния
Total Money
}
// Доменный сервис, инкапсулирующий бизнес-правило.
// Внимание: логика связана с доменом "Заказ", а не с технической реализацией.
type OrderService struct {
repo OrderRepository
}
func (s *OrderService) CancelOrder(orderID OrderID, reason string) error {
order, err := s.repo.Get(orderID)
if err != nil {
return err
}
// Бизнес-правило: отменить можно только заказы со статусом "Created" или "Paid"
if !order.CanBeCancelled() {
return domain.ErrOrderCannotBeCancelled
}
order.Cancel(reason) // Вызов метода доменного объекта, который меняет состояние
return s.repo.Save(order)
}
2. Использование единого языка (Ubiquitous Language)
Единый язык (Ubiquitous Language) — это структурированный набор терминов, правил и понятий, общий для всех участников проекта: разработчиков, аналитиков, тестировщиков и бизнес-экспертов. Этот язык используется везде: в общении, документации, диаграммах и, что самое важное, в самом коде.
Как это работает:
- Имена типов, функций, методов, пакетов и переменных напрямую берутся из единого языка.
- Это устраняет дорогостоящие преобразования ("на жаргоне бизнеса это X, а в коде у нас поле
abc"). - Код становится самодокументируемым и понятным для всех.
Пример на Go:
// Плохо: техноцентричные имена, не отражающие домен.
type DataRecord struct {
ID int
State string
Amount float64
}
// Хорошо: имена взяты из единого языка домена "Торговля".
type PurchaseOrder struct { // "Заказ на закупку" - конкретный термин бизнеса
ID PurchaseOrderID
Status PurchaseOrderStatus // "Статус заказа" - "Submitted", "Approved", "Rejected"
TotalCost Money // "Общая стоимость" - тип Money явно указывает на домен
}
// Метод назван в соответствии с бизнес-процессом.
func (po *PurchaseOrder) Approve(approverID EmployeeID) error {
// Логика утверждения, соответствующая бизнес-правилам
if po.Status != Submitted {
return domain.ErrCannotApproveNonSubmittedOrder
}
po.Status = Approved
po.ApproverID = approverID
return nil
}
3. Стратегическое проектирование через ограниченные контексты (Bounded Contexts)
Это ключевой принцип для управления сложностью больших систем. Ограниченный контекст (Bounded Context) — это явная граница, внутри которой действует конкретная модель и её единый язык. Один и тот же термин в разных контекстах может иметь разное значение.
Зачем это нужно:
- Предотвращает создание одной огромной, противоречивой "единой модели" для всей системы, что неизбежно ведёт к хаосу.
- Позволяет разным командам независимо разрабатывать и развивать свои контексты.
- Четко определяет, где заканчивается ответственность одной модели и начинается другая.
Пример: В системе электронной коммерции термин "Продукт (Product)" имеет разное значение в разных контекстах:
- Каталог (Catalog Context):
Product— это товар с описанием, фото, категориями. - Заказы (Ordering Context):
Product— это идентификатор (SKU) и цена на момент заказа. - Доставка (Shipping Context):
Product— это физический объект с весом и габаритами.
На уровне кода и архитектуры это разделение можно отразить через разные Go-модули/пакеты:
// Контекст "Каталог"
package catalog
type Product struct {
ID ProductID
Name string
Description string
Images []Image
Categories []Category
// Атрибуты, важные для каталога
}
// Контекст "Заказы"
package ordering
// Локальная модель продукта в контексте заказов.
// Может содержать только необходимые данные.
type OrderProduct struct {
SKU ProductSKU // Идентификатор, связывающий с каталогом
Name string // Возможно, упрощённое имя для чека
Price Money // Цена НА МОМЕНТ ЗАКАЗА (важное бизнес-правило!)
Quantity int
}
// Связь между контекстами осуществляется через идентификаторы или антикоррупционный слой (ACL),
// а не через прямую передачу объектов.
Итог: Эти три принципа взаимосвязаны. Фокус на домене задаёт направление, единый язык обеспечивает эффективную коммуникацию и точное отражение домена в коде, а ограниченные контексты предоставляют практический инструмент для структурирования сложной системы, не позволяя ей превратиться в "большой комок грязи" (Big Ball of Mud). Внедрение DDD требует значительных усилий и особенно оправдано в проектах с высокой сложностью бизнес-логики.