TGViewer
Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter @phpproglib · 10.5K subscribers
Post #6046 2.2K
Разбираемся с DDD: как проектировать доменный агрегат, чтобы он не стал безразмерным

В больших PHP-проектах на DDD легко скатиться в один «всемогущий» агрегат, который держит всё и сразу. Итог — дорогая гидрация, лишняя память, сложные транзакции. На примере программы лояльности разберём, как держать границы агрегатов в порядке и не платить лишнего.

🔩 Главная мысль
Агрегат — это не «всё доменное сразу», а границы инвариантов, консистентности и транзакционности. Если объект должен меняться атомарно вместе с другим — это сигнал быть в одном агрегате. Если нет — связь по id и отдельные контексты.

Проблема 1: Границы
Чем больше «подтаскиваем» в агрегат, тем выше риск «один агрегат, чтобы править всеми».
✅ Держим в голове 3 правила:
Инварианты — всё, что нужно для их соблюдения, внутри агрегата.
Консистентность — объект никогда не бывает «наполовину валидным».
Транзакционность — меняются вместе ⇒ сохраняются вместе.
📌 Пример: уровни лояльности зависят от валюты начисления. Меняем валюту → должны атомарно сбросить требования уровней. Уровни — часть агрегата LoyaltyProgram.
А вот Discount может жить отдельно, если после активации ПЛ он больше не меняется вместе с программой (связь по id + доменный сервис для применения скидок).

Проблема 2: Цена (память/гидрация)
Десятки тысяч карт + логи изменений в памяти PHP — больно.
🧰 Рабочие варианты:
Облегчённые структуры вместо коллекций — храним метаданные (id, пути, индексы), а не целые объекты; доменные события обеспечат сохранение нужных сущностей вместе с агрегатом.
Транзакционность в Application-слое — карты вынимаем из репозитория снаружи, операции делаем через корень агрегата (инварианты в домене, транзакция — в use-case). Минус: немного падает cohesion.
Ленивые коллекции — коллекция хранит id, при доступе к элементу бросает доменное событие, инфраструктура подгружает объект. Код домена остаётся чистым, гидрация — по требованию.

Чек-лист проектирования агрегата
Инвариант нарушается без X? → X внутри агрегата.
Объекты меняются атомарно? → вместе в агрегате.
Логика «применения» живёт там, где её нельзя обойти клиентским кодом.
Большие коллекции? → метаданные/ленивая загрузка/перенос транзакций в application.
Скидки/внешние сущности? → отделяйте контексты, связывайте по id, при необходимости используйте доменные сервисы.

⚠️ Анти-паттерн
«Корневой агрегат знает всё и держит всех» → взрыв памяти, сложные сохранения, нарушение SRP.

💬Обсудим в комментах: где вам приходилось резать агрегат и почему?

🔗 Хабр

Библиотека пхпшника
  • ❤ 4
More from @phpproglib
  1. Sep 24, 2026👍 5 способов встроить AI в Laravel Laravel AI SDK позволяет добавлять AI-функции прямо в…
  2. Sep 23, 2026🛠 Symfony 8.2 научился автоматически генерировать JSON Schema для конфигурации приложения…
  3. Sep 23, 2026🚀 Свежий релиз Laravel 13 с набором улучшений и исправлений ✅ добавлена поддержка valkey:…
  4. Sep 21, 2026⚡️ PHP 8.6 выйдет 19 ноября 2026 года. Сейчас версия находится в beta. Самые заметные изме…
  5. Sep 20, 2026❓ Какие существуют проблемы в многопоточной среде? Основные проблемы многопоточности: 1️⃣…
  6. Sep 19, 2026🌞 В Symfony 8.2 появилось 29 новых Bundle — теперь компоненты вроде Mailer, Messenger и C…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →