Недавно понял, почему у меня нет необходимости в репозиториях.
У меня просто нет доменного слоя, за счёт того что я ухитрился настолько упростить код что и слои оказались лишними.
Ну а без доменного слоя и репозитории это излишество.
Как упрощается код
Вот что помогает мне упростить код:
- Перепроектирование под изменённые требования
- Следование принципам чистой архитектуры, в том числе SOLID, и следование принципам чистого кода
- Использование шаблонов проектирования, таких как DTO и VO, посредники (“обёртки” в моей интерпретации)
- Разделение функциональности на модули “вертикальными срезами”
- Устранение техдолга не только в коде но и в БД
- Система “сущность-модель” которая позволяет не тащить детали общения с БД в код бизнес-логики
Каждый отдельный метод немного улучшает качество кода, а используя их все, качество и простота кода вырастает значительно.
Мой опыт с репозиториями
Как и большая часть опытных программистов, когда-то я впервые познакомился с репозиториями и был очень впечатлён мощностью этой концепции.
Надо же, можно отделить полностью хранилище данных от логики процессов и сделать код который будет независим от хранилища!
Это действительно круто. Но внедрив в один из своих проектов повсеместно репозитории, я убедился что они несут с собой очень много лишнего кода.
В большинстве случаев вам не требуется использовать одновременно разные типы хранилищ, а вследствие этого реализация репозитория будет в одном экземпляре.
Имея реализацию в одном экземпляре, встаёт вопрос, а зачем нам тогда вообще отделять этот код по общению с БД в репозиторий? Не лучше ли оставить его там где он был?
Минусы репозиториев
Основные минусы репозиториев:
- Нужно писать больше кода
- Код становится сложнее из-за увеличения количества абстракций
- Тратится больше времени на создание и сопровождение кода
Плюсы репозиториев
Основные плюсы репозиториев:
- При правильной реализации, код становится независимым от хранилища данных
- Код становится чище так как детали взаимодействия с БД переезжают в репозиторий
- DDD!
Отмечу, впрочем, что преимущество с очисткой кода от деталей взаимодействия с БД можно получить и без использования репозиториев.
Сервисный слой
Ещё до репозиториев, и до изобретения системы “сущность-модель” я практиковал метод создания сервисного слоя для БД.
Допустим, есть какой-то “заказ”. Тогда у меня будет OrderController
, OrderService
и Order
.
Внутри OrderService
будут находиться любые операции взаимодействия с БД: запросы на поиск, чтение, методы создания и измненения заказов.
При этом концентрируя в сервисе операции с БД, мы по возможности избавляем контроллер от этих деталей, а также сокращаем количество кода в модели.
Этот метод очень сильно упростил создание сложных проектов, но был не идеален.
Контроллер и вьюшки “знали” о полях модели, поэтому изменения в структуре БД всё же затрагивали их.
Стоп, а как же тестировать без репозиториев?
Очень просто, работайте на уровне “сущностей” если используете систему “сущность-модель”, обращайтесь к сервисам если у вас есть сервисный слой, или напрямую к моделям если его нет.
Но тогда мы будем обращаться к БД в тестах, а это плохо!
Почему же это плохо?
Сколько я ни спрашивал, убедительного ответа не получил.
Перечислю основные варианты ответов и мои возражения на эти ответы.
В книгах и статьях учат что это плохо — предпочитаю опираться на собственный опыт и логику, а не слепо доверять написанному. К тому же я слишком хорошо знаю примеры, когда авторы книг и статей “учат плохому” а потом приходится переучивать тех кто верит авторам на слово. Если автор вас убедил, приведите его аргументы, а не просто мнение.
Это медленно! — весомый аргумент, но при разумном подходе к тестированию, когда мы проверяем только необходимое, это уже не так важно. Если тесты выполняются менее минуты, я считаю их достаточно быстрыми.
А как тестировать без репозиториев?! — да вот так, использовать БД и всё.
У нас (в нашем проекте) так не получится — если структура вашего проекта не позволяет обойтись без репозиториев или моков в тестировании, вы можете преодолеть это повысив свои навыки тестирования или упростив проект. Конечно, можете остаться с репозиториями, ваше право. Встретив сложности в тестировании, я предпочитаю менять проект так, чтобы тестировать его было легко.
А что если БД выдала ошибку? И наш код не обеспечит надёжности в этом случае? Как мы это проверим? — при правильном проектировании кода такие проверки не требуются. Но если очень нужно, то решение найдётся и без репозитория. Если же применяем репозиторий с целью решения такой задачи, то держим в уме, что использование репозитория несёт свои издержки. Ради одного случая внедрять репозитории везде я бы не стал, слишком дорого обходится.
Зачем тогда нужны репозитории?
Если не для тестирования и не для упрощения кода, то зачем нужны репозитории?
Я бы стал использовать репозитории там, где изначально предполагается несколько вариантов хранилища.
Например, у нас есть модуль сессии и он в зависимости от настроек проекта хранит данные либо в БД, либо в файлах, либо в Redis.
В этом случае репозиторий уместен и полезен: он даст необходимое упрощение, так как изолирует основной код от каких-то знаний о хранилище.
Мы сможем добавить или удалить тип хранилища без изменения в основной логике, тем самым соблюдая “принцип открытости-закрытости”, OCP.
У тебя те же репозитории, ты просто их “сущностями” назвал!
Нет. Моя система “сущность-модель” отличается от репозиториев в первую очередь тем, что решает совершенно другую задачу.
Мои сущности полностью изолируют приложение от деталей реализации в БД.
Обычные “репозитории” — не книжные, а те которые мы видим повсеместно в проектах фанатов репозиториев — никак не изолируют код от БД, просто вводят ещё одну прослойку. Переименовал поле в БД или удалил таблицу — добро пожаловать, правь 100 мест в коде.
В моих сущностях изменения затронут только сами сущности и модели, причём модель является не более чем отражением таблицы. Прочий код приложения не поменяется.
Второе важное отличие: мои сущности содержат правила бизнес-логики, а репозитории призваны заниматься только операциями с БД на чтение и запись, сводя свои знания о бизнес-контексте к минимуму.
Они играют разные роли.
P.S.
Использовать репозитории или нет, решать вам.
Я лишь постарался подробно изложить свой взгляд на этот вопрос и поделиться тем что узнал.
Лучший способ узнать, нужны ли именно вам репозитории — просто попробовать.
Удачи!