Зачем нужны Repository и Unit of Work и какие проблемы они решают?
Архитектурные паттерны
Repository представляет хранилище как коллекцию доменных объектов (`findById`, `save`) и прячет SQL и ORM; Unit of Work отслеживает изменения в рамках бизнес-операции и фиксирует их одной транзакцией.
Repository
- Домен зависит от интерфейса
OrderRepository, а не от Prisma или TypeORM, поэтому логику тестируют на in-memory реализации. - Ошибка: generic
Repository<T>сfindAll/updateна каждую таблицу — пустая обёртка над ORM. Репозиторий заводят на агрегат, методы называют по-доменному:findOverdue().
Unit of Work
- Проблема: сервис меняет заказ, остаток на складе и баланс; без UoW каждый
save()пишет сам, и падение посередине оставляет данные несогласованными. - UoW копит новые, изменённые и удалённые объекты, а на
commit()открывает транзакцию, выполняет запросы и фиксирует или откатывает всё сразу. - Готовые реализации:
SaveChanges()в EF Core, Session в Hibernate и SQLAlchemy,em.flush()в MikroORM.
/**
* Контракт OrderRepository (Order = { id, status: 'new' | 'paid' }):
* findById(id) → Promise<Order | undefined>
* save(order) → Promise<void>
*/
class InMemoryOrders {
#rows = new Map();
async findById(id) { return this.#rows.get(id); }
async save(order) { this.#rows.set(order.id, { ...order }); }
}Коротко для собеседования
Repository даёт домену интерфейс коллекции агрегатов вместо SQL, а Unit of Work собирает все изменения бизнес-операции и коммитит их одной транзакцией. ORM вроде EF Core или Hibernate уже реализуют оба паттерна, поэтому своя прослойка окупается только при богатом домене и тестах без БД.