← Назад к вопросам

Что такое DDD (Domain-Driven Development)?

3.0 Senior🔥 152 комментариев
#Архитектура и паттерны#Опыт и карьера

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое DDD (Domain-Driven Design)?

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

Ключевые концепции DDD

DDD строится на нескольких фундаментальных концепциях:

  1. Домен (Domain) и Поддомен (Subdomain):
    *   **Домен** — это конкретная область бизнеса, которую модель должна представлять (например, банковское обслуживание, логистика, электронная коммерция).
    *   Внутри домена выделяются **Поддомены**: **Core** (ядро бизнеса), **Supporting** (поддерживающие) и **Generic** (общие, часто готовые решения).

  1. Единый язык (Ubiquitous Language):
    Это согласованный набор терминов и определений, используемый **всеми участниками проекта** — разработчиками, бизнес-экспертами, аналитиками. Этот язык применяется в документации, в общении и, что самое важное, **в коде**. Это устраняет недопонимание и создает прямую связь между бизнесом и реализацией.

```php
// Пример использования единого языка в названии класса
// Вместо абстрактного "PaymentProcessor" используется бизнес-термин
class InvoiceIssuingService {
    public function issue(Order $order): Invoice {
        // "Invoice" и "issue" — термины из языка бизнес-аналитиков
    }
}
```

3. Модель (Model) и ее строительные блоки:

    DDD предлагает четкие паттерны для структурирования модели домена:
    *   **Сущность (Entity)**: Объект, идентифицируемый по своему ID, а не по атрибутам. Его состояние может меняться, но идентичность сохраняется.
    ```php
    class Customer {
        private CustomerId $id; // Уникальный идентификатор
        private string $name;
    
        // Изменение имени не делает это другой сущностью
        public function changeName(string $newName): void {
            $this->name = $newName;
        }
    }
    ```
    *   **Значение (Value Object)**: Объект, описываемый только своими атрибутами. Не имеет идентификатора и часто неизменяем.
    ```php
    class Money {
        private int $amount;
        private string $currency;
    
        public function equals(Money $other): bool {
            // Сравнение по значениям атрибутов
            return $this->amount === $other->amount 
                && $this->currency === $other->currency;
        }
    }
    ```
    *   **Агрегат (Aggregate)**: Кластер связанных объектов (Сущностей и Значений), рассматриваемых как единое целое. **Агрегат** имеет корневую **Сущность (Aggregate Root)** и контролирует инварианты (правила целостности) внутри своей границы.
    ```php
    // Order — Aggregate Root
    class Order {
        private OrderId $id;
        private array $lineItems = [];
    
        // Инвариант: нельзя добавить товар с нулевой стоимостью
        public function addLineItem(Product $product, int $quantity): void {
            if ($product->getPrice()->isZero()) {
                throw new InvalidPriceException();
            }
            $this->lineItems[] = new LineItem($product, $quantity);
        }
    }
    ```
    *   **Сервис домена (Domain Service)**: Операция или логика, которая не естественно принадлежит какой-то одной **Сущности** или **Значению**. Часто координирует несколько объектов домена.
    *   **Репозиторий (Repository)**: Абстракция для хранения и поиска **Агрегатов**. Он скрывает детали реализации хранилища (базы данных) от модели.
    *   **Фабрика (Factory)**: Объект, специализирующийся на сложном создании других объектов домена.

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

DDD разделяется на два уровня:

  • Стратегическое проектирование: Фокусируется на высокоуровневом понимании домена. Здесь используются Контексты (Bounded Context) — четко очерченные области, где определенный Единый язык и модель применяются без противоречий. Также строится Картина контекстов (Context Map) для описания взаимодействий между ними.
  • Тактическое проектирование: Именно здесь применяются описанные выше строительные блоки (Сущности, Агрегаты и т.д.) для создания детальной, работающей модели внутри Контекста.

Почему DDD важен для PHP Backend разработчика?

  1. Сложность бизнес-логики: PHP часто используется для крупных enterprise-проектов (CRM, ERP, финансовые системы), где логика крайне сложна. DDD предоставляет инструменты для ее структурирования.
  2. Снижение связности: Разделение на Контексты и использование Агрегатов помогает создавать модульные, тестируемые компоненты, независимые от инфраструктуры.
  3. Эволюция системы: Система, построенная вокруг бизнес-понятий, легче изменяется и расширяется, когда меняются бизнес-правила.
  4. Коммуникация: Единый язык разрушает барьер между разработчиками и бизнесом, уменьшая количество ошибок на этапе интерпретации требований.

Практический пример применения в PHP

Рассмотрим фрагмент системы управления заказами в Контексте "Продажи".

// Агрегат Заказ (Order) с его инвариантами
class Order {
    private OrderId $id;
    private CustomerId $customerId;
    private OrderStatus $status;
    private Money $total;
    private array $items;

    public function __construct(CustomerId $customerId) {
        $this->id = OrderId::generate();
        $this->customerId = $customerId;
        $this->status = OrderStatus::DRAFT();
        $this->total = Money::zero('USD');
        $this->items = [];
    }

    // Доменная операция: добавление товара
    public function addProduct(Product $product, int $quantity): void {
        // Проверка инварианта: нельзя добавить товар в подтвержденный заказ
        if ($this->status->isConfirmed()) {
            throw new OrderAlreadyConfirmedException();
        }

        $lineItem = new OrderItem($product, $quantity);
        $this->items[] = $lineItem;
        
        // Обновление итоговой стоимости (другой инвариант)
        $this->total = $this->total->add($lineItem->getPrice());
    }

    // Доменная операция: подтверждение заказа
    public function confirm(): void {
        // Инвариант: нельзя подтвердить пустой заказ
        if (empty($this->items)) {
            throw new EmptyOrderException();
        }
        $this->status = OrderStatus::CONFIRMED();
        // Здесь может генерироваться доменное событие OrderConfirmed
    }
}

// Репозиторий, абстрагирующий персистентность
interface OrderRepository {
    public function save(Order $order): void;
    public function findById(OrderId $id): ?Order;
}

// Сервис домена для сложной операции
class OrderFulfillmentService {
    public function __construct(
        private OrderRepository $orderRepository,
        private InventoryService $inventory
    ) {}

    public function fulfillOrder(OrderId $orderId): void {
        $order = $this->orderRepository->findById($orderId);
        // Координация нескольких агрегатов и проверка бизнес-правил
        foreach ($order->getItems() as $item) {
            $this->inventory->reserve($item->getProductId(), $item->getQuantity());
        }
        $order->markAsFulfilled();
        $this->orderRepository->save($order);
    }
}

Выводы для собеседования

На собеседовании важно показать, что вы понимаете DDD не как набор паттернов для копирования, а как мышление. Это подход, требующий глубокого сотрудничества с бизнес-экспертами для выявления Ядра (Core) системы и построения вокруг него устойчивой, понятной архитектуры. В PHP это часто реализуется через сочетание DDD с другими архитектурными стилями, например, Гексагональной архитектурой (Ports & Adapters) для чистого отделения домена от инфраструктуры. Говорите о важности Единого языка и Контекстов как средств борьбы со сложностью, и о том, что тактические паттерны (Агрегаты, Репозитории) — это инструменты для реализации стратегического видения.

Что такое DDD (Domain-Driven Development)? | PrepBro