Как реализована инъекция зависимостей между слоями в чистой архитектуре?
Что проверяют
Понимаете ли вы правило зависимостей: внутренние слои ничего не знают о внешних, а связь идёт через абстракции. Следом обычно спрашивают, где лежит интерфейс репозитория и в какой точке программы собираются реальные объекты.
Как отвечать
Опорная мысль: зависимости в коде направлены внутрь, к домену, а поток управления во время работы идёт наружу, к базе и сети. Противоречие снимает инверсия зависимостей:
- домен: сущности и правила на чистом Python, без импортов SQLAlchemy, FastAPI или
requests; - сценарии (use cases): оркестрируют домен и объявляют порты, то есть то, что им нужно от внешнего мира. В Python удобен
typing.Protocol: реализация подходит структурно, наследоваться не обязательно, а mypy или pyright проверят совместимость. Можно иabc.ABC, если нужна проверка при создании объекта; - инфраструктура: адаптеры, реализующие порты, например
SqlAlchemyOrderRepositoryили клиент платёжного шлюза. Они импортируют протокол из внутреннего слоя, а не наоборот; - корень композиции: одно место на внешнем краю (
main.py, фабрика приложения), где создаются адаптеры и передаются в конструкторы сценариев.
Внедрение обычно конструкторное: CreateOrder(repo: OrderRepository, uow: UnitOfWork). Для небольшого проекта хватит ручной сборки, для большого подойдут dependency-injector или dishka. Depends из FastAPI уместен в слое контроллеров: он собирает сценарий и отдаёт его обработчику, но внутрь сценария не проникает.
Главная выгода проверяется тестом: сценарий запускается с InMemoryOrderRepository на словаре, без базы и без моков из unittest.mock, и работает за миллисекунды.
Где спотыкаются
Кладут абстрактный репозиторий в пакет инфраструктуры. Тогда сценарий импортирует инфраструктуру, и правило зависимостей нарушено, хотя формально интерфейс есть.
Протаскивают Depends, Session или ORM-модели в доменный слой. Модель SQLAlchemy в роли сущности намертво привязывает бизнес-логику к базе.
Разводят контейнер, десять слоёв и протоколы на каждый класс в сервисе из трёх эндпоинтов. На собеседовании ценится умение сказать, где такая строгость окупается, а где нет.