PassFront
  1. PassFront
  2. База знаний
  3. Архитектурные паттерны

Зачем нужны 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 уже реализуют оба паттерна, поэтому своя прослойка окупается только при богатом домене и тестах без БД.

Другие вопросы раздела