Обновить
2
0
Ageev Maxim@ApostolFet

Пользователь

Отправить сообщение

Оставили чатик в телеграмме, там можно и связаться)

Вдохновляющая история, спасибо за статью

Отвечу на второй вопрос. inject - эта декораторы созданные под конкретные фреймворки, это интеграции, которая предоставляет dishka (в данной статье интеграция с fastapi) и используется для удобного внедрения зависимостей в контроллер. В остальном же резолвинг зависимостей настраивается в специальных классах провайдерах. Сами зависимости ничего не знают о библиотеке.
Приведу пример на псевдокоде:
Есть достаточно типичная ситуация, когда мы вызываем в контроллере интерактор (use case), который в свою очередь зависит от репозитория, а наша реализация репозитория зависит от сессии базы данных.

В таком случае в контролере мы укажем с помощью аннотации FromDishka, что хотим получить интрактор и используем декоратор inject (на самом деле это не обязательно, для многих интеграций есть функция autoinject). И просто вызовем у него соответствующий метод.

@router.get("/command")
@inject
def my_controller(interactor: FromDishka[MyInteractor]):
  interactor.execute()

Код нашего интерактора и репозитория будут выглядеть так:

class Repo(Protocol):
  def get_user(self) -> User: ...

class MyInteractor:
  def __init__(self, repo: Repo):
    self._repo = repo

  def execute(self):
    # тут код использующий репозиторий

А наша реализация репозитория:

class MyRepo(Repo):
  def __init__(self, session: Session):
    self._session = session

  def get_user(self) -> User: ...
    # конкретная реализация

Обратите внимания ни реализация репозитория, ни интерактор ничего не знают о дишке

Далее мы напишем провайдер, в котором опишем, то какие зависимости должны подставляться:

class MyProvider(Provider):
  scope = Scope.REQUEST

  @provide
  async get_session(self) -> AsyncIterator[Session]:
    session = make_session()
    try:
      yield session
    finally:
      await session.close()

  my_repo = provide(MyRepo, provides=Repo)
  my_interactor = provide(MyInteracotor)


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

Остается лишь настроить дишку с данным с использованием данного провайдера, как показано в статье.
Это базовый пример использования, который встречался мне на практике.

Дишка позволяет нам писать код, зависящий от абстракций, а также имеет достаточно удобный интерфейс связывания зависимостей (есть Autowiring, а также валидация графа, которая поможет выявить ошибке при старте приложения, и многое другое)


Информация

В рейтинге
Не участвует
Откуда
Санкт-Петербург, Санкт-Петербург и область, Россия
Дата рождения
Зарегистрирован
Активность

Специализация

Бэкенд разработчик