Комментарии 6
Статья неплохая, есть ряд вопросов:
1. container - это глобальный объект?
2. Можем ли иметь несколько контейнеров?
3. Насколько эффективно ресолвятся зависимости?
4. Не совсем понял пример с тем, что меняется входная схема. Да, мы не привязываемся к неймингу, отдаем сырые данные , там под капотом происходит магия. Но в таком случае получается, что мы ничего как клиент не знаем о контракте, если контракт поменяется мы бы в любом случае получили проблему совместимости, но когда явно указываешь схему передачи, ide подсветит тебе, что у тебя синус с косинусом не сходятся или ту же проблему получишь при запуске линтов. Как бы никто не защищен, если от того, что у тебя и исходную схему модернизируют, так что она перестанет работать у клиентов сервиса. Но тут мы это прячем на слой поглубже.
DI в целом очень хорош, нужен ли он в django проекте?
Да
Технически — да, можно создавать контейнеры на уровне app-ки в Django. Вопрос насколько это будет удобно и не понадобится ли какой-то сервис из одной аппки в сервисе другой аппки. Можно легко запутаться если контейнеров много.
Я не проводил бенчмарк-тесты, но это одна из самых легких DI-либ + 100% покрытие тестами. Минимальный шанс, что где-то выстрелит.
4)
Да, мы не привязываемся к неймингу, отдаем сырые данные , там под капотом происходит магия. Но в таком случае получается, что мы ничего как клиент не знаем о контракте, если контракт поменяется мы бы в любом случае получили проблему совместимости, но когда явно указываешь схему передачи, ide подсветит тебе, что у тебя синус с косинусом не сходятся или ту же проблему получишь при запуске линтов
В моем примере я использовал dict потому что это было удобно в случае с сериализатором. Можно написать более явный контракт и передавать именнованные аргументы (а в фабрике соответственно их принимать и маппить в DTO):
service = container.resolve("SomeService", id=1, price=2, amount=3)Как бы никто не защищен, если от того, что у тебя и исходную схему модернизируют, так что она перестанет работать у клиентов сервиса. Но тут мы это прячем на слой поглубже.
Это правда, что никто не защищен. Однако в данном случае при изменении исходной схемы мы не зависим от внутренней реализации сервиса. Что-то менять нужно и там, и там, однако, при использовании фабрики — многие вещи становятся гораздо удобнее. Взять то же версионирование сервисов — мы можем реализовать его в фабрике, и не выносить этот if-код наружу. Опять же - скрываем детали реализации.
2) Думаю, речь не про уровень аппки, а про то чтобы контейнер создавался при старте и передавался во вьюхи. Чтобы его можно было, в частности, в тестах подменить
4) все ещё не понимаю зачем вы передаете данные при резолвинге сервиса. Ну передайте вы при вызове его методов, предвариательно заложив в интерфейс. Если же это конфигурационные параметры - передавайте при настройке контейнера, а не во вьюхе опять же
Не раскрыта тема внедрения зависимостей. Ваш сервис по факту ни от чего не зависит - ни от адаптера для доступа к БД, ни от вспомогательных объектов, реализующих БЛ. Вместо этого почему-то он принимает продукт в init, а не как данные. Это немного странно
С другой стороны, у вас есть глобальный контейнер. Вы его используете напрямую, а не получаете сервисо во вьюхе.
Суммарно, это больше выглядит как паттерн ServiceLocator, а не Dependency Injection.
Что же касается самого punq, меня в нем в своё время остановила одна вещь - отсутствие явных скоупов. Вы не можете ему сказать, что всё время пока вы обращаетесь к контейнеру внутри обработчика запроса надо возвращать один и тот же экземпляр конкретного класса, а при выходе - почистить (иногда вызвав доп функции финализации).
Приветствую
Не раскрыта тема внедрения зависимостей. Ваш сервис по факту ни от чего не зависит - ни от адаптера для доступа к БД, ни от вспомогательных объектов, реализующих БЛ.
Может я не совсем понял о чем речь — есть пример, где для работы сервиса нужно передать другой сервис который работает с CRM и инжектится внутри фабрики.
С другой стороны, у вас есть глобальный контейнер. Вы его используете напрямую, а не получаете сервисо во вьюхе.
Суммарно, это больше выглядит как паттерн ServiceLocator, а не Dependency Injection.
Я понимаю что вы имеете в виду — скорее всего использование контейнера внутри вьюхи. Да, эта часть выглядит как ServiceLocator и это единственное место где сервис инжектится подобным образом, но! По моему скромному мнению для джанги и его вьюшек - это допустимое поведение. Использование всяких декораторов над методом или переопределение конструктора вьюхи — совсем печально выглядит. Но и это относится только к вьюхам — остальные зависимости попадают через фабрику.
Что же касается самого punq, меня в нем в своё время остановила одна вещь - отсутствие явных скоупов. Вы не можете ему сказать, что всё время пока вы обращаетесь к контейнеру внутри обработчика запроса надо возвращать один и тот же экземпляр конкретного класса, а при выходе - почистить (иногда вызвав доп функции финализации).
Что есть — то есть. Насколько знаю в punq-е можно определять два поведения глобально для каждого объекта - singletone и создавать новый объект. Но при использовании это поведение определить на ходу нельзя. Однако для нас это не играет большой роли.
Спасибо, что прокомментировал, для меня это действительно важно.

Сервисы — место, где живет бизнес-логика II