Repository (за Фаулером) - посередник між доменом і даними, що поводиться як колекція доменних об'єктів: додати, знайти, видалити, - приховуючи, як і де вони зберігаються.
Типова реалізація в Laravel-проєктах:
interface OrderRepository
{
public function find(int $id): ?Order;
public function forUser(User $user): Collection;
public function save(Order $order): void;
}
final class EloquentOrderRepository implements OrderRepository { /* ... */ }
Аргументи «за»:
- запити в одному місці: складні запити не розкидані по контролерах і сервісах;
- підміна в тестах: бізнес-логіку можна тестувати з репозиторієм у пам'яті, без бази;
- незалежність від сховища: теоретично можна замінити Eloquent чи базу.
Аргументи «проти» в контексті Laravel:
- Eloquent - уже Active Record: модель сама вміє зберігатися й будувати запити. Репозиторій, що повертає ті самі моделі Eloquent, не приховує сховища: модель усе одно має
save(),delete()і ледаче завантаження зв'язків; - «дірява» абстракція: методи на кшталт
findByStatusAndDateAndUserWithRelations()множаться, бо Eloquent-будівник запитів гнучкіший за будь-який інтерфейс; - заміна бази - рідкісний сценарій, а заміна ORM у Laravel-проєкті - ще рідший;
- тестування з базою в Laravel дешеве (SQLite в пам'яті, транзакції, фабрики), тож аргумент «тести без бази» слабшає;
- більше коду: інтерфейс + реалізація + реєстрація в контейнері на кожну модель.
Компромісні рішення, що дають більшу частину користі:
- scopes і власні будівники запитів (
#[UseEloquentBuilder]) - повторювані умови в одному місці; - query-класи для складних запитів і звітів (
MonthlyRevenueQuery); - action-класи - бізнес-операції, що працюють з моделями напряму.
Коли репозиторій справді виправданий:
- доменна модель окремо від Eloquent (DDD з чистими сутностями, які не знають про базу) - тоді репозиторій обов'язковий: він перетворює рядки бази на доменні об'єкти;
- дані з кількох джерел за одним інтерфейсом (база + зовнішній API + кеш);
- модульний моноліт, де модуль не повинен віддавати свої моделі назовні.
Для співбесіди: важливо показати розуміння компромісу, а не «завжди» чи «ніколи».