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

DDD — это подход к разработке сложных программных систем, который фокусируется на моделировании предметной области (бизнес-логики) и организации кода вокруг бизнес-концепций.

Основные концепции DDD

1. Ограниченный контекст

Логическая граница, внутри которой определены конкретные модели и термины. Например:

  • "Клиент" в контексте продаж vs "Пользователь" в контексте безопасности

2. Универсальный язык

Общий язык между разработчиками и бизнес-экспертами:

// Вместо
class UserOrderProcessor {
    public function processTransaction() {...}
}

// Используем термины из предметной области
class OrderFulfillment {
    public function completePurchase() {...}
}

3. Слои архитектуры

  1. Domain Layer - чистая бизнес-логика
  2. Application Layer - координирует задачи
  3. Infrastructure Layer - технические детали
  4. Presentation Layer - взаимодействие с пользователем

Ключевые строительные блоки

1. Сущности

Объекты с идентичностью, которые изменяются со временем:

class Product {
    private ProductId $id;
    private string $name;

    public function rename(string $newName): void {
        $this->name = $newName;
    }
}

2. Значения

Неизменяемые объекты без идентичности:

class Money {
    public function __construct(
        private float $amount,
        private Currency $currency
    ) {}

    public function add(Money $other): Money {
        if (!$this->currency->equals($other->currency)) {
            throw new InvalidArgumentException('Currencies must match');
        }
        return new Money($this->amount + $other->amount, $this->currency);
    }
}

3. Агрегаты

Группа связанных объектов, рассматриваемая как единое целое:

class Order {
    private OrderId $id;
    private array $lineItems;

    public function addItem(Product $product, int $quantity): void {
        $this->lineItems[] = new LineItem($product, $quantity);
    }
}

4. Репозитории

Интерфейсы для доступа к агрегатам:

interface OrderRepository {
    public function save(Order $order): void;
    public function findById(OrderId $id): ?Order;
}

5. Сервисы домена

Логика, которая не принадлежит конкретному объекту:

class OrderProcessingService {
    public function __construct(
        private OrderRepository $orders,
        private InventoryService $inventory
    ) {}

    public function process(Order $order): void {
        if (!$this->inventory->isAvailable($order->items())) {
            throw new DomainException('Items not available');
        }
        $order->markAsProcessed();
        $this->orders->save($order);
    }
}

6. События домена

Факты, произошедшие в домене:

class OrderCompleted {
    public function __construct(
        public readonly OrderId $orderId,
        public readonly DateTimeImmutable $occurredOn
    ) {}
}

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

  1. Context Map - визуализация взаимодействия ограниченных контекстов
  2. Shared Kernel - общая модель для нескольких контекстов
  3. Customer-Supplier - явные отношения между командами
  4. Conformist - подчинение чужой модели
  5. Anti-Corruption Layer - защитный слой против чужой модели

Тактическое проектирование

  1. Моделирование сложной логики через:
    • Specification pattern
    • Domain Events
    • CQRS (Command Query Responsibility Segregation)

Пример CQRS:

class PlaceOrderHandler {
    public function __construct(
        private OrderRepository $orders,
        private EventDispatcher $dispatcher
    ) {}

    public function handle(PlaceOrderCommand $command): void {
        $order = Order::place(
            $command->orderId,
            $command->products
        );
        $this->orders->save($order);
        $this->dispatcher->dispatch(new OrderPlaced($order->id()));
    }
}

Когда использовать DDD

  1. Сложная бизнес-логика с множеством правил
  2. Долгоживущие проекты с частыми изменениями
  3. Большие команды с разделением ответственности

Реализация в PHP

Пример структуры папок:

src/
  Domain/
    Model/
      Order/
        Order.php
        OrderId.php
        LineItem.php
    Repository/
      OrderRepository.php
    Service/
      OrderProcessingService.php
    Event/
      OrderPlaced.php
  Application/
    Command/
      PlaceOrderHandler.php
  Infrastructure/
    Persistence/
      DoctrineOrderRepository.php

Резюмируем:

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