
Понимание шаблона репозитория
Термин «репозиторий» сильно перегружен в разработке программного обеспечения, в этой статье мы научимся понимать, что репозиторий - это фасад сбора в памяти, его роль в качестве уровня сценария транзакции и общего примитива доступа к данным, а также его роль в контекст проектирования, управляемый предметной областью, и его общее использование в инструментарии разработчика.
Все эти аспекты тесно связаны, и все они представляют собой эволюцию исходного паттерна репозитория. Этот шаблон предшествовал банде четырех, предметно-ориентированному дизайну и многим популярным фреймворкам и стратегиям, которые существуют сегодня. Вы можете прочитать о репозиториях в Введение в архитектуру программного обеспечения Дэвида Гарлана и Мэри Шоу (1994).
Итак, что это такое? Суть этого:
Создайте оболочку вокруг всей своей логики доступа к данным с помощью интерфейса, не зависящего от базы данных, чтобы можно было отложить привязку к определенному хранилищу данных.
Основное преимущество здесь заключается в том, что в любой момент вы можете заменить базовое хранилище данных, реализовав тот же интерфейс в другом репозитории, и ваша бизнес-логика останется неизменной. Вам все равно потребуется перенести данные, поэтому это не так просто, но это действительно изолирует вашу бизнес-логику от инфраструктурного решения о выборе базы данных. Скептик может спросить: Как часто вы фактически меняете всю свою базу данных? Не так часто. Но вы все время кешируете дорогие функции, о которых я расскажу позже.
Стоит упомянуть и другие преимущества:
- Возможность тестирования. Становится невероятно легко изолировать логику доступа к данным. Также очень легко использовать методы репозитория-заглушки, чтобы избежать необходимости хранить огромные объемы тестовых данных.
- Индексирование. Благодаря тому, что вся логика доступа к данным для таблицы или коллекции собрана в одном месте, очень легко обнаружить возможности для добавления индексов или оптимизации запросов.
- Кэшируемость. Поскольку ваша логика доступа к данным не распространяется на бизнес-домен, вы можете очень легко создавать функции высшего порядка, которые кэшируют вызовы с высокой пропускной способностью либо в памяти (осторожно!), либо в распределенном кеше.
- Возможность повторного использования. Поскольку ваша логика доступа к данным находится в том же месте, вы обязательно найдете там возможности для повторного использования.
Итак, как выглядит репозиторий? Самый простой - это один файл, содержащий всю вашу логику доступа к данным. Ничего особенного, только запросы к базе данных, связанные вспомогательные функции, объявления индексов и все остальное, что связано с базой данных. Вы разделяете модели сохраняемости на отдельные файлы - все, что имеет смысл.
Это ядро шаблона проектирования репозитория. Некоторые могут возразить, что это просто «сценарий транзакции», но на самом деле это очень специализированный подтип того, что предоставляет операции, как если бы вы работали с набором в памяти.
Хотите увидеть код? В Интернете доступно множество ресурсов из авторитетных источников. Вот старая реализация в .NET, которая тоже немного говорит о шаблоне (я уверен, что есть более новые версии). Для конкретных, удобных реализаций шаблона репозитория в JavaScript и TypeScript, ознакомьтесь с моим проектом на github, где вы можете найти работающие, протестированные репозитории почти для десятка различных хранилищ данных, включая mongodb, redis, Google Cloud Firestore. , и более. (Обратите внимание, что этот проект предназначен для использования в качестве шаблона для реализаций базового класса, а не как загружаемый пакет NPM; запросы на вытягивание приветствуются, если вы используете хранилище данных, которое вы не видите в списке).
По мере роста вашего приложения вам необходимо определить стратегию разделения модели. Популярным фреймворком для этого является Domain Driven Design или DDD. Эрик Эванс (автор книги Домен-ориентированный дизайн: преодоление сложности в основе программного обеспечения) определяет репозиторий как часть того, что он называет тактическим DDD; он тактический, потому что, хотя он отделяет уровень службы домена от уровня доступа к данным, он не решает основную проблему DDD, которая формирует повсеместный язык в вашей команде и организовывает отдельные наборы задач. В стратегическом дизайне, ориентированном на предметную область, цель состоит в том, чтобы разделить вашу модель на ограниченные контексты, которые являются границами внутри бизнес-домена, где терминология остается неизменной.
В этом контексте DDD Repository представляет собой «реализацию репозитория» с добавленным ограничением, заключающимся в том, что он предоставляет доступ к данным для совокупного корня или всего ограниченного контекста.
В отличие от того, что было упомянуто выше, реализация «ванильного» репозитория (или только тактическая) может привести к разработке, управляемой существительными, где каждое существительное или таблица в базе данных будет иметь свой собственный репозиторий, службу, контроллер и т. Д. (Шестиугольная архитектура конструкции). С DDD у вас будут репозитории только для агрегированных корней, такие как пользовательский репозиторий, который будет предоставлять доступ ко всему в пределах границ пользователя, и отдельный репозиторий продукта, который будет предоставлять все необходимое из контекста продукта.
Ваш опыт может варьироваться в зависимости от того, сколько слоев требуется для домена или приложения, в котором вы работаете, но в большом сложном домене стоит отметить, что репозитории не должны взаимодействовать друг с другом в разных контекстах. Примером этого является то, что пользовательский репозиторий не должен получать избранные продукты непосредственно из репозитория продуктов. Связь между сервисами должна осуществляться через сервисный уровень, каждый из которых напрямую взаимодействует со своими собственными репозиториями. Границы здесь применяются также и на уровне базы данных; избегайте прямого присоединения к внешним таблицам.
В заключение, реализация репозитория почти всегда является хорошей идеей, потому что это очень маленький шаблон, и вы никогда не знаете, когда вам может потребоваться внести изменения, добавить кеш или добавить небольшое дополнительное тестовое покрытие.
Чтобы получать уведомления, когда я публикую новую статью, подпишитесь на мою рассылку. Вы также можете найти мои публикации с открытым исходным кодом на github.