Skip to content

Instantly share code, notes, and snippets.

@andyollylarkin
Forked from maestrow/repository.md
Created November 9, 2022 09:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andyollylarkin/395e3a5712a78fc9644859682c9f4ca7 to your computer and use it in GitHub Desktop.
Save andyollylarkin/395e3a5712a78fc9644859682c9f4ca7 to your computer and use it in GitHub Desktop.
Паттерн репозиторий

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

Репозиторий - это слой абстракции, инкапсулирующий в себе всё, что относится к способу хранения данных. Назначение: Разделение бизнес-логики от деталей реализации слоя доступа к данным.

Паттерн Репозиторий стал популярным благодаря DDD (Domain Driven Design). В противоположность к Database Driven Design в DDD разработка начинается с проектирования бизнес логики, принимая во внимание только особенности предметной области и игнорируя все, что связано с особенностями базы данных или других способов хранения данных. Способ хранения бизнес объектов реализуется во вторую очередь.

Применение данного паттерна не предполагает создание только одного объекта репозитория во всем приложении. Хорошей практикой считается создание отдельных репозиториев для каждого бизнес-объекта или контекста, например: OrdersRepository, UsersRepository, AdminRepository.

Пример

public interface IPostsRepository
{
    void Save(Post mypost);
    Post Get(int id);
    PaginatedResult<Post> List(int skip,int pageSize);
    PaginatedResult<Post> SearchByTitle(string title,int skip,int pageSize);
}
  • Метод save определяет какой объект передан - новый или существующий, в зависимости от этого использует команду insert или update.
  • Методы List и SearchByTitle возвращают список постов, в котором указывается информация об отобранной странице.

Generic Repository это антипаттерн

Не существует определенных правил каким должен быть интерфейс репозитория - это всецело зависит от предметной области. Однако есть класс простых приложений, которые работают с данными одинаково. И когда нужно получить простой универсальный способ работы с данными - это единственный случай, когда использование обобщенного репозитория оправдано.

public interface IRepository<T>
{
   IEnumerable<T> GetAll();
   T GetByID(int id);   
   void Add(T entity);
   void Update(T entity);
   void Delete(T entity);
}

Репозиторий и ORM

Возможно у вас возник вопрос: Зачем использовать репозиторий, если я использую ORM?

Действительно, ORM позволяет:

  • работать с данными, оперируя бизнес-объектами (POCO).
  • легко сменить поставщика данных (SQL Server на MySql и т.д.)

Однако может быть масса случаев, когда хранение данных представляет собой нечто более сложное или специфичное, чем просто ORM. И тогда такой слой данных инкапсулируется с помощью паттерна репозиторий:

  • Если вы хотите сменить поставщика данных на NoSql базу данных или файлы.
  • Вы можете использовать несколько поставщиков данных. Например, MySql для данных и файловую систему для хранения изображений.
  • Строго говоря модель ORM не является моделью предметной области. И в случае когда это действительно разные вещи, а используется только модель ORM, то это уже не DDD.

Если ваш репозиторий возвращает IQueryable, то это ошибка, т.к. репозиторий не должен возвращать что-либо относящееся к способу хранения. Правильно было бы IEnumerable.

Преимущества паттерна Репозиторий

  • Выделение общей логики (DRY): проверки, значения по умолчанию, логирование и т.д..
  • Независимость бизнес-логики от способа хранения. Используя репозиторий, вы обращаетесь с коллекциями бизнес объектов (POCO), но не с database related объектами, не с Data Access Objects. Возможность использовать разные способы хранения: ORM, rdbms, cloud storage, file system etc, заменять их и комбинировать.
  • Работая через интерфейсы вы можете создать несколько реализаций репозитория. Это помогает при тестировании (можно передавать заглушку репозитория при тестировании бизнес-логики) и при изменении способа хранения данных. Конкретная реализация репозитория может регистрироваться в IoC и т.о. ни один модуль приложения за исключением точки входа не будет связан с модулем реализации репозитория. Приложение будет работаеть с интерфейсом репозитория и объектами бизнес-логики.

Репозиторий и DAL (Data Access Layer, Persistence Layer)

Репозиторий - это высокоуровневая абстракция доступа к данным. Интерфейс каждого конкретного репозитория (контракт) определяется в слое бизнес-логики наряду с классами предметной области. Реализация каждого репозитория находится в слое доступа к данным DAL. Соответственно DAL состоит из реализации каждого репозитория, ORM-специфичных классов, сущностей, классов-сопоставлений (mapping), контекстов данных и т.д.

Ссылки

Источник: Серия статей by Mike Mogosanu из его блога https://blog.sapiensworks.com:

На момент написания этой заметки статьи Mike размещались в категории Repository, затем он переделал свой блог и эти статьи попали в категорию Best Practces, что охватывает и другие вопросы, выходящие за рамки темы Паттерн Репозиторий. Поэтому привожу здесь ссылку на версию статей 2014 года.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment