Что такое внедрение зависимостей
Что проверяют
Понимаете ли вы, что в этом языке внедрение зависимостей редко требует контейнера, и умеете ли делать код тестируемым без тотальной подмены модулей. Разговор быстро сворачивает в практику: как вы заменяете клиент базы или внешний сервис в тестах.
Как отвечать
Зависимость передаётся объекту снаружи, а не создаётся внутри. Подойдёт всё, что можно вызвать: класс, функция, частично применённая функция. Типизировать удобно через протокол, наследование при этом не требуется.
from typing import Protocol
class Storage(Protocol):
def save(self, key: str, blob: bytes) -> None: ...
class ReportPublisher:
def __init__(self, storage: Storage) -> None:
self._storage = storageВ тесте подставляется простой объект с методом save, и подменять модуль целиком не нужно.
Про экосистему полезно сказать своими словами: в популярных веб-фреймворках механизм зависимостей встроен, в тестах роль контейнера играют фикстуры pytest, для больших графов есть отдельные библиотеки. Контейнер оправдан, когда объектов много и у них разное время жизни; для сервиса из десятка классов хватает одной функции сборки в точке входа.
Главная мысль, которую ценят: внедрение зависимостей убирает из кода жёстко зашитые обращения к внешнему миру. Модуль, который открывает соединение с базой прямо на импорте, невозможно ни протестировать, ни переиспользовать.
Где спотыкаются
Подменяют зависимости патчем по строковому пути к модулю. Такой тест ломается от переименования и проверяет расположение кода, а не поведение. Явный параметр надёжнее и заодно показывает, что класс зависит от слишком многого.
Создают зависимости в значениях аргументов по умолчанию или на уровне модуля. Значение по умолчанию вычисляется один раз при импорте, и клиент с открытым сокетом переживёт ветвление процесса, после чего воркеры начнут делить одно соединение.
Тащат тяжёлый контейнер в маленький проект по привычке из других языков. Читаемость падает, граф собирается неизвестно где, и на вопрос, откуда взялся объект, ответ звучит как «его приносит декоратор».