.. _root_dependency_injection:

Внедрение зависимостей
=======================

Внедрение зависимостей (Dependency Injection, DI) — это паттерн проектирования, который помогает писать слабосвязанный, легко тестируемый и расширяемый код. Вместо того чтобы обработчики сами создавали нужные им объекты (зависимости), они получают их извне.

``Argenta`` использует библиотеку ``dishka`` для реализации DI, что позволяет декларативно объявлять зависимости прямо в сигнатурах ваших обработчиков.
Подробнее о DI, IoC и API для создания провайдеров можно прочитать в `официальной документации dishka <https://dishka.readthedocs.io/en/stable/di_intro.html>`_.

-----

Основная идея
-------------

Представьте, что вашему обработчику для работы нужен доступ к базе данных. Вместо импорта и инициализации соединения внутри функции, вы просто объявляете его как аргумент с аннотацией типа:

.. note::
   ``argenta.di.FromDishka`` является алиасом для ``dishka.FromDishka``, и они полностью взаимозаменяемы.

**Пример использования:**

.. literalinclude:: ../code_snippets/dependency_injection/snippet.py
   :language: python
   :linenos:

``Argenta`` с помощью ``dishka`` разрешит зависимость по типу ``Connection`` и внедрит её. Но прежде чем использовать зависимость, её необходимо объявить в провайдере:

**Пример использования:**

.. literalinclude:: ../code_snippets/dependency_injection/snippet2.py
   :language: python
   :linenos:
   
После создания провайдера его необходимо зарегистрировать в оркестраторе.

.. note::
   Провайдеры регистрируются в ``Orchestrator``, а не в ``App``, так как оркестратор отвечает за настройку DI-контейнера на уровне всего приложения. Вы можете передать список из нескольких провайдеров через параметр ``custom_providers``.

**Пример использования:**

.. literalinclude:: ../code_snippets/dependency_injection/snippet3.py
   :language: python
   :linenos:

-----

Как это работает?
-----------------

В основе DI в Argenta лежат **провайдеры** и **контейнер**.

*   **Провайдер (Provider)** — это "рецепт", который объясняет, как создавать и настраивать ту или иную зависимость (например, подключение к БД, API-клиент или любой другой сервис).
*   **Контейнер (IoC Container)** — это "фабрика", которая хранит все рецепты (провайдеры) и по запросу создаёт и выдаёт готовые зависимости.

-----

Встроенные провайдеры
-----------------------

``Argenta`` поставляется со встроенным провайдером, который даёт доступ к важным системным зависимостям без дополнительной настройки. Например, вы можете получить объект :ref:`ArgSpace <root_api_orchestrator_argspace>`, который содержит аргументы командной строки, переданные при запуске приложения.

**Пример использования:**

.. literalinclude:: ../code_snippets/dependency_injection/snippet4.py
   :language: python
   :linenos:
   
-----

Обмен данными между обработчиками
----------------------------------

Помимо DI, обработчики могут обмениваться данными в рамках сессии через **объект контекста**. В ``Argenta`` эту роль выполняет объект ``DataBridge``.

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

.. seealso::
   Подробнее об этом можно прочитать в разделе :ref:`root_api_bridge`.
