Паттерн репозиторий - NurOrNuLL/ESDP-AP-5-6-TEAM-2 GitHub Wiki

Паттерн репозиторий

Паттерн «Репозиторий» — это абстракция поверх системы постоянного хранения. Он скрывает скучные детали доступа к данным, делая вид, что все данные находятся прямо в памяти.

Хранилище в абстрактном виде

Простейший репозиторий имеет всего два метода: add() , чтобы поместить новый элемент в репозиторий, и get() , чтобы вернуть ранее добавленный элемент 1 . Мы твердо придерживаемся использования этих методов для доступа к данным в модели и в слое служб предметной области. Это условие не позволяет нам прицепить модель предметной области к базе данных. Вот как будет выглядеть абстрактный базовый класс (ABC) для репозитория:

Самый простой из возможных репозиториев (repository.py)

class AbstractRepository(abc.ABC):
  @abc.abstractmethod
  def add(self, batch: model.Batch):
    raise NotImplementedError

  @abc.abstractmethod
  def get(self, reference) -> model.Batch:
    raise NotImplementedError

АБСТРАКТНЫЕ БАЗОВЫЕ КЛАССЫ, УТИНАЯ ТИПИЗАЦИЯ И ПРОТОКОЛЫ

Мы используем абстрактные базовые классы в этой книге по дидактическим причинам: мы надеемся, что они помогут объяснить, что такое интерфейс абстракции репозитория. В реальной жизни мы порой удаляем абстрактные базовые классы из производственного кода, потому что Python слишком легко их игнорирует и они в конечном счете остаются без поддержки, а в худшем случае вводят в заблуждение. На практике в целях задействования абстракции мы часто просто опираемся на утиную типизацию Python. Для питониста репозиторий — это любой объект, имеющий методы add(thing) и get(id).

Всякий раз, когда мы добавляем новый объект модели предметной области нам нужео будет писать несколько строк кода в классе репозитория, который хотим получить, но взамен получаем простую абстракцию над слоем хранения, который мы контролируем. Паттерн «Репозиторий» позволит легко вносить фундаментальные изменения в способ хранения, и как мы увидим, его легко подделывать для юнит-тестов.

image

Типичный репозиторий (repository.py)

class SqlAlchemyRepository(AbstractRepository):
  def __init__(self, session):
    self.session = session
  
  def add(self, batch):
   self.session.add(batch)

  def get(self, reference):
    return self.session.query(model.Batch).filter_by(reference=reference)

  def list(self):
    return self.session.query(model.Batch).all()

Дополнительная информация: