Каждая сущность (Entity) должна иметь репозиторий. Именно он выступает неким "адаптером" между внешним хранилищем (например БД) и нашим доменным слоем. Но вот проблема.
❌ Если мы будем вызывать реализацию репозитория внутри нашего Application слоя, то нарушим правило разделения приложения, которое гласит, что внешние слои могут зависеть от внутренних, а не наоборот (
Infrastructure -> Application -> Domain).👉 Для решения этой проблемы достаточно создать абстракцию (интерфейс), который и будет принадлежать доменному слою, на который и может быть завязан сервис или юзкейс.
❓ Почему интерфейс репозитория принадлежит доменному слою, а сам репозиторий нет?
Вашему бизнесовому коду всё равно, будете вы использовать базу данных, файловую систему или InMemory для хранения и получения данных, ему важно чтобы были методы с определенными именами, принимали конкретные параметры и возвращали нужные типы данных. Именно это и позволяет оставлять наш код независимым от конкретной реализации, таким образом реализация остаётся в инфраструктурном слое.
❗️ Держите код Repository в чистоте
❌ Очень частое упрощение — весь код, который работает с базой выносим в репозиторий. В итоге получаем, что в репозитории у нас 2 метода, которые мы используем постоянно (например
getById() и save()) и 5 методов, которые у нас узконаправлены (например используются для каких-то частных выборок типа отчетов). Здесь вообще стоит немного углубиться в тему Read Model, но пока обойдемся более простой идеей. 👍 Если вам нужен объект из репозитория с ограниченным или наоборот расширенным набором данных только для чтения (то есть вы не предполагаете внесение изменений), то не надо делать этот метод в том-же репозитории. Скорее всего вам нужен
Finder, который сразу может вернуть вам удобные структуры данных (тех же DTO). Это удобно как минимум потому, что:📌 Ваши view не всегда нужны все данные ваших
Entity / Агрегатов.📌 Вам не придётся делать ненужные
getters в вашей основной Entity.📌 Ваши
Entity не должны содержать весь список данных "на всякий случай", со всеми ссылками на другие сущности (например Customer со всеми заказами, со всеми данными этих заказов).📌 В конце концов вы можете разделить источники данных, в то время как
Entity могут работать с реляционной, то View могут быть получены из того же Redis, для ускорения получения данных (вопрос консистентности тоже рассмотрим отдельно).#php #oop #repository #middle #source