212 похожих чатов

Окей. давай по другому скажу. для начала контекст: 1. у нас

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

Если наш контекст отличается (у нас там проект разделен на под проекты с динамической линковкой и артефакты могут независимо заменяться, пусть не в рантайме но без необходимости пересобирать все) - то там отдельный разговор и будут свои ограничения которые будут требовать больше внимания к DIP. но я хз кто сейчас так делает. Последнее что припоминаю - знакомые мобильщики так делали на больших проектах с целью распаралелить разработку. Но обычно люди которые таким занимаются уже понимают че куда зачем и как. Или как минимум "неверный выбор абстракций" начинает конфликтовать с тем ради чего динамическую линковку завозили и хоть какие-то явные сигналы что что-то не так идет.

Теперь дальше. "подменить репозиторий". В 90% ситуаций мы не будем этого делать. Ни в тестах (ибо не понятно что мы тестим) ни в чем-либо то нибыло. Да мы можем декорации какие применять, для этого нужен интерфейс но наличие интерфейса не означает соблюдение DIP (если у тебя направление зависимостей между модулями не меняется то какая разница).

Для оставшихся 10% или когда ситуация поменялась и понадобилось - выделяешь интерфейс и вперед.

Если мы говорим про то как большинство делает у тебя репозиторий это класс с 100500 методов выборок которые юзаются каждый в паре мест. И просто лепить на такое интерфейс уже как-то глупо. Да можно попытаться разбить интерфейс через ISP и тогда как бы уже интереснее и больше смысла. Но опять же для чего? В тестах подменять? Тут уже больше вариантов если разным модулям разное надо.

Если выше смотреть, "репозиторий" обычно не шарится между модулями. Тип если у тебя есть модуль какой-то подсистемы которая отвечает за свои аспекты системы, то репозиторий наружу мы никогда не будем отдавать. Вместо этого будут другие точки интеграции с другими модулями и там можно чет смотреть. Тип для организации каких-нибудь anti-corruption layers. и прочего. Обычно полезно между легаси частями приложений и новыми частями.

Потому и говорю что на примере репозитория просто не особо много пользы от DIP. Можно было бы говорить о какой-то пользе если бы у нас "репозиторий" был классический, тип просто key-value стор без выборок и прочего. Тогда это можно было бы представить какой-то более-менее понятной абстракцией которую удобно подменять и т.д. Тогда можно надежно говорить о том что мы стор базы подменили на in-memory стор и ничего не поменялось и мы все еще понимаем что тестим. Но ты много таких систем видел? Я не много.

12 ответов

45 просмотров
Sergey-P Автор вопроса

у тебя ситуация когда репозиторий это простой интерфейс для работы с коллекцией через ключ значение и больше ничего? Никаких методов save или find some very specific things? Если так - могу представить себе где это может быть нужно. Но большинство "репозиторием" называют просто точку взаимодействия с базой, где у тебя в каком-нибудь условном OrderRepository будет жирный кусок SQL или квери билдер или LINQ с джойнами на другие сущности и прочей хуйней. И подменять такое - обычно смысла нет ибо 50% того что может потенциально сломаться это сами запросы и взаимодействие с базой. А так как "база" это обычно managed out-process dependency то есть под нашим контролем хоть и вне границ процесса - нам не обязательно это дело отделять. Мы все еще можем достаточно легко обеспечить изоляцию тест кейсов даже с реальной базой.

Sergey P
у тебя ситуация когда репозиторий это простой инте...

Бывает и то, и то. В последнее время я пришел к разделению на write model и read model. Для write это обычно getById + save + delete, а для read уже сложные выборки. Первое я подменяю кастомной полноценной реализацией

Sergey-P Автор вопроса
Блья ✖️➕➖➗
Бывает и то, и то. В последнее время я пришел к ра...

ну вот я не встречал пока в природе ситуации где такие тесты дают хоть какой-то уровень уверенности в том что система работает как надо.

Sergey-P Автор вопроса
Блья ✖️➕➖➗
Бывает и то, и то. В последнее время я пришел к ра...

а ты уверен что в этом случае ты что-то тестишь а не просто фиксируешь текущую реализацию?

Sergey P
а ты уверен что в этом случае ты что-то тестишь а ...

На сложные запросы у меня есть тесты на сам репозиторий (реальный)

Sergey-P Автор вопроса
Блья ✖️➕➖➗
На сложные запросы у меня есть тесты на сам репози...

я про "моки которые ассертят что пришло в метод репозитория".

Sergey P
я про "моки которые ассертят что пришло в метод ре...

Я тестирую что код правильно составил запрос в репозиторий, и правильно использовал ответ). И этот код я пишу ещё до того как написал код реального репозитория.

Sergey-P Автор вопроса
Блья ✖️➕➖➗
Я тестирую что код правильно составил запрос в реп...

а можешь псевдокодом каким показать пример такого теста?)

Sergey P
а можешь псевдокодом каким показать пример такого ...

Сейчас у меня этими методами пользуется код, который отвечает за http api. Тест +- такой Дано: http запрос с такими-то урлой и телом Подменяем репозиторий, экспектим такие то параметры, возвращаем такой список сущностей Проверяем что http api правильно отрендерил ответ. Думал ещё это все сделать через query bus, чтобы апи не пользовался репозиторием напрямую, но пока и так норм)

Sergey-P Автор вопроса
Блья ✖️➕➖➗
Сейчас у меня этими методами пользуется код, котор...

ну то есть тест по факту фиксирует реализацию а не проверяет поведение

Sergey P
ну то есть тест по факту фиксирует реализацию а не...

Реализацию чего мы фиксируем, не понял

Похожие вопросы

Обсуждают сегодня

а зачем этот вопрос для удаления из чата?
Mёdkinson Medvezhkin
63
Эх кто-то пришел и весь праздник испортил :( You need complex FBX scene importing setup to change things on import? good luck with that. You need navigation and pathfinding? g...
Serg Gini
5
Всем привет! Подскажите. Я написал приложение на Delphi 10.2 Tokyo под Windows 10. И передо мной стал вопрос о том чтобы сделать это приложение кроссплатформенным (под Linux и...
Дмитрий Завгородний
24
Какого хера? /Sources/App/Modules/User/Models/UserLinkApple.swift:21:20: warning: stored property '_id' of 'Sendable'-conforming class 'UserLinkApple' is mutable @ID(...
Alexander Sherbakov
11
У тебя в конфиге нигде нет deny all; или вообще любого deny?
Alexander Sherbakov
10
Почему стало ломаться на D11? "739002.86400000' is not a valid timestamp" function IncDateTime(aStamp:TTimeStamp;aKind:TTriggerKind;aInterval:Integer):TDateTime; //aStamp = 2...
Катерина Свиридова
8
Привет всем. Подскажите где можно посмотреть, какая версия электрон, поддерживает версии windows? Некий changelog. Мне бы желательно, поддержку 7,8,10... latest, как понимаю и...
Anonym Squad
21
Портфолио: Зовут меня Александр, мне 36 лет. Город Пушкино. Общий рабочий стаж: ~14 лет Уровень квалификации: Senior Full-stack developer Где прочесть мой код? https://github....
Magic
10
думаешь я не смогу также сделать? мне это просто не удобно
int 💳 𝙖𝙞𝙧 𝙗𝙞𝙜 𝙗𝙤𝙗 🔫 check bio / spam block / AFK / nohello.com / GMT+3
9
Ребят, чет я уже не догоняю... Крч в коде на асм там происходит нечто вроде a+число (a+1, a+2 и т.д.). Но почему строка lea ecx, [edx+1] работает как a+1?? В edx берется адрес...
Alan 🔝 Бэброу
4
Карта сайта