> Есть ли опыт работы с Domain-Driven Design (DDD)? (PHP)
Уровень: middle · Роль: backend · Язык: PHP · Категория: Технические вопросы
Компании: Travelata
Стек: PHP
> Пример ответа
Короткий ответ
Да, есть практический опыт применения DDD в PHP-проектах. Работал с такими концепциями, как bounded context, aggregate, domain event, repository и application service. Использовал DDD в проектах со сложной бизнес-логикой, где важно было отделить домен от инфраструктуры. Основной фокус - на моделировании бизнес-процессов в коде и поддержании инвариантов внутри агрегатов.
Подробное объяснение
DDD - это подход к проектированию, где основное внимание уделяется доменной логике, а не техническим деталям. В PHP это особенно актуально, потому что язык часто используется для быстрых CRUD-приложений, и без явного выделения домена логика размазывается по контроллерам и сервисам.
В своей работе я применял следующие элементы DDD:
- Bounded context - выделял границы между разными подсистемами (например, заказы и каталог товаров), чтобы избежать смешения моделей.
- Aggregate - проектировал корневые сущности, которые управляют инвариантами. Например,
Orderкак aggregate root, который контролирует изменение позиций заказа. - Domain event - использовал для реакции на изменения внутри домена, например,
OrderPlaced, чтобы запускать сайд-эффекты в других контекстах. - Repository - инкапсулировал доступ к данным, чтобы домен не зависел от ORM или конкретной БД.
- Application service - организовывал сценарии использования (use cases) и транзакции, оставляя домен чистым.
Важный trade-off: DDD добавляет сложность в структуру проекта. Поэтому я применял его не везде, а только там, где бизнес-логика действительно сложная и есть несколько взаимосвязанных правил. Для простых CRUD-модулей DDD избыточен.
На практике
В одном из проектов (система управления подписками) я использовал DDD для моделирования процесса продления подписки. Был bounded context Billing, внутри которого агрегат Subscription управлял состоянием: активна, просрочена, отменена. Все изменения состояния проходили через методы агрегата, что гарантировало соблюдение инвариантов - например, нельзя отменить уже отменённую подписку.
Инфраструктура (Eloquent, очереди, внешние платёжные API) была вынесена за пределы домена. Домен общался с внешним миром через интерфейсы, а адаптеры реализовывались в инфраструктурном слое. Это позволяло тестировать домен без БД и без реальных HTTP-запросов.
Также использовал domain events для интеграции с другими контекстами: после успешной оплаты публиковалось событие PaymentReceived, на которое подписывался контекст Notifications для отправки письма клиенту.
Пример кода
PHP// Domain layer - Aggregate Rootfinal class Subscription{private function __construct(private readonly SubscriptionId $id,private SubscriptionStatus $status,private \DateTimeImmutable $expiresAt,) {}public static function create(SubscriptionId $id, \DateTimeImmutable $expiresAt): self{$subscription = new self($id, SubscriptionStatus::ACTIVE, $expiresAt);$subscription->recordEvent(new SubscriptionCreated($id));return $subscription;}public function renew(\DateTimeImmutable $newExpiryDate): void{if ($this->status === SubscriptionStatus::CANCELLED) {throw new \DomainException('Cannot renew cancelled subscription');}$this->expiresAt = $newExpiryDate;$this->recordEvent(new SubscriptionRenewed($this->id, $newExpiryDate));}public function cancel(): void{if ($this->status === SubscriptionStatus::CANCELLED) {throw new \DomainException('Subscription already cancelled');}$this->status = SubscriptionStatus::CANCELLED;$this->recordEvent(new SubscriptionCancelled($this->id));}}// Application layer - Use casefinal readonly class RenewSubscriptionService{public function __construct(private SubscriptionRepository $repository,private EventDispatcher $dispatcher,) {}public function renew(SubscriptionId $id, \DateTimeImmutable $newExpiryDate): void{$subscription = $this->repository->findById($id);$subscription->renew($newExpiryDate);$this->repository->save($subscription);$this->dispatcher->dispatch($subscription->releaseEvents());}}
Как отвечать на собеседовании
Начни с конкретного примера проекта, где DDD реально применялся. Опиши, какую бизнес-задачу решал, какие bounded context выделил и почему. Покажи понимание trade-off: где DDD оправдан, а где - нет. Упомяни, что DDD - это не про технологии, а про моделирование домена, и что PHP-фреймворки (Laravel, Symfony) не навязывают DDD, но позволяют его реализовать.
Если спросят про сложности - честно скажи, что основная сложность в дисциплине: не тащить инфраструктурные детали в домен и не делать агрегаты слишком большими. Также можно упомянуть, что DDD хорошо сочетается с CQRS и event sourcing, но это не обязательные спутники.
Что проверяет интервьюер
Интервьюер проверяет:
- понимаешь ли ты разницу между domain layer, application layer и infrastructure layer;
- умеешь ли проектировать агрегаты и соблюдать инварианты;
- знаешь ли, когда DDD уместен, а когда - избыточен;
- можешь ли объяснить, как repository и domain events вписываются в общую архитектуру;
- насколько ты критичен к своему опыту - не утверждаешь ли, что используешь DDD везде подряд.
Типичные ошибки
- Говорить, что DDD - это просто слои в папках (
Domain,Application,Infrastructure). Это лишь следствие, а не суть. - Путать aggregate root с обычной Entity. Агрегат управляет целостностью группы объектов, а не просто является моделью из БД.
- Использовать DDD для простого CRUD - это создаёт лишнюю сложность без пользы.
- Не упоминать bounded context. Без него DDD превращается в "одну большую модель на всё приложение", что приводит к проблемам.
- Показывать код, где домен зависит от Eloquent или других инфраструктурных классов - это нарушение принципов DDD.
> Похожие задачи по PHP
> Похожие задачи по backend
Использовали ли Xdebug для отладки PHP
Как определить заказ для повторного запроса с несколькими попытками
Есть ли в Kotlin аналог equals и hashCode и как это реализовано
Использовали ли Kotlin для написания автотестов
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью