Что такое предметно-ориентированное проектирование?
Введение
Предметно-ориентированное проектирование (Domain-Driven Design, DDD) — это методология разработки программного обеспечения, ориентированная на глубокое понимание предметной области и построение архитектуры вокруг нее. Подход был предложен Эриком Эвансом в его книге "Domain-Driven Design: Tackling Complexity in the Heart of Software".

В отличие от традиционных методов проектирования, DDD уделяет особое внимание созданию модели предметной области, которая отражает реальные бизнес-процессы и терминологию. В этой статье мы рассмотрим основные принципы DDD, его преимущества и реальные примеры использования.
Основные принципы DDD
1. Разделение на стратегический и тактический уровни
DDD делится на два ключевых уровня:
  • Стратегический уровень – определяет границы предметной области, разрабатывает контексты и управляет взаимодействием между ними.
  • Тактический уровень – реализует детали проектирования, такие как сущности, агрегаты, репозитории и доменные события.
2. Границы контекста (Bounded Context)
Каждое приложение охватывает несколько контекстов, где одни и те же термины могут означать разные вещи. Например, в системе интернет-магазина термин "Заказ" может означать разные вещи для отдела логистики и отдела продаж. DDD определяет границы контекста (Bounded Context), чтобы избежать путаницы и изоляции изменений внутри конкретной части системы.

3. Единый язык (Ubiquitous Language)
DDD требует, чтобы разработчики, аналитики и бизнес-эксперты использовали единый язык, основанный на терминах предметной области. Это позволяет минимизировать недопонимание между участниками процесса разработки и создать четкую модель системы.

4. Агрегаты (Aggregates)
Агрегаты – это группы объектов, которые управляются как единое целое. Внутри агрегатов одна сущность называется агрегатным корнем, и все внешние изменения проходят через него. Например, в системе заказов агрегатом может быть "Заказ", а его корнем – "Заказ" с вложенными "Позициями заказа".
5. Репозитории (Repositories)
Репозитории – это слои доступа к данным, которые позволяют отделить доменную логику от инфраструктуры хранения (баз данных, API и т. д.). Например, OrderRepository может предоставлять методы FindById(id), Save(order), Delete(order).

6. Доменные события (Domain Events)
DDD активно использует событийную модель, где значимые изменения в системе представляются как доменные события. Например, "ЗаказСоздан" или "ОплатаПринята".
Пример из реального проекта
Представим, что мы разрабатываем систему управления подписками на SaaS-сервис. Вот как DDD может помочь в проектировании:

1. Определение границ контекста
В нашем случае мы имеем два ключевых контекста:
  • Контекст подписки (Subscription Context) – отвечает за управление подписками пользователей.
  • Контекст биллинга (Billing Context) – отвечает за оплату и выставление счетов.
2. Определение агрегатов
В контексте подписки можно выделить агрегат Subscription, который содержит:
  • SubscriptionId
  • UserId
  • Plan
  • Status
  • StartDate
  • EndDate
Агрегатным корнем будет Subscription, а изменение статуса подписки (например, "отмена" или "обновление") должно происходить через методы этого агрегата.

3. Использование доменных событий
При смене статуса подписки можно генерировать доменное событие SubscriptionCancelled, которое затем обработает контекст биллинга, чтобы прекратить списание средств.
public class SubscriptionCancelled : IDomainEvent
{
    public Guid SubscriptionId { get; }
    public DateTime CancelledAt { get; }

    public SubscriptionCancelled(Guid subscriptionId, DateTime cancelledAt)
    {
        SubscriptionId = subscriptionId;
        CancelledAt = cancelledAt;
    }
}
Затем подписчик этого события в контексте биллинга может выполнить необходимые действия:
public class BillingEventHandler
{
    public void Handle(SubscriptionCancelled event)
    {
        StopBilling(event.SubscriptionId);
    }
}
4. Реализация репозиториев
public interface ISubscriptionRepository
{
    Subscription FindById(Guid id);
    void Save(Subscription subscription);
}
Таким образом, DDD помогает создать четкую архитектуру, разделяя ответственность между контекстами и минимизируя зависимость компонентов.
Преимущества DDD
  • Лучшее соответствие бизнес-логики и кода – модель предметной области отражает реальные процессы.
  • Гибкость и расширяемость – система легко адаптируется к изменениям бизнеса.
  • Повышенная читаемость и понимание кода – разработчики и бизнес-эксперты говорят на одном языке.
  • Четкие границы контекста – минимизируется сложность взаимодействия компонентов.
Когда стоит применять DDD?
DDD подходит не для всех проектов. Он особенно полезен, когда:
  • Предметная область сложная и имеет много бизнес-правил.
  • В проекте участвует несколько команд, и важно четко определить контексты.
  • Требуется высокая гибкость системы при изменениях в бизнесе.
Не стоит применять DDD в небольших проектах с простыми CRUD-операциями, где он добавит ненужную сложность.
Заключение
Предметно-ориентированное проектирование – мощный подход к разработке программного обеспечения, который помогает создавать гибкие, расширяемые и удобные для понимания системы. Использование таких концепций, как границы контекста, единый язык, агрегаты и доменные события, позволяет избежать многих проблем, связанных со сложностью программного обеспечения.

Если ваш проект сложен и требует четкой структуры, DDD – отличный выбор, который поможет вам разработать надежную и понятную архитектуру.
Эта тема подробно рассматривается на курсе "DDD и Clean Architecture на практике"
Понравилась статья? Поделись в соцсетях!
Our Website is Almost Ready
Launch a targeted campaign.
Scale your infrastructure with our simple service.
Days
Hours
Minutes
Seconds