TGViewer
Советы разработчикам (python и не только) Советы разработчикам (python и не только) @advice17 · 8.35K subscribers
Post #56 16.7K
Dependency Injection

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

Суть его в том, что когда у нас одному из объектов требуется другой, то он не создает или ищет его сам, а принимает извне. Например, если вашей функции нужно соединение с БД, то она не должна ни импортировать его, ни брать из глобальной переменной, ни создавать сама. Ей это соединение должны передать.

Само собой, какой-то код будет создавать эти зависимости, и тут мы стараемся отделять его от кода, использующего их. Благодаря этому:
во-первых, делаем этим зависимости более явными;
во-вторых, можем управлять тем, будет ли использован один экземпляр зависимости или разные;
в-третьих, можем использовать один и тот же код с разными реализациями зависимостей.

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

Можно выделить три способа внедрения зависимостей:
1. Внедрение через параметры функции/метода. Просто передаем зависимость как ещё один параметр:

 def clear_users(cursor):
cursor.execute("TRUNCATE users;")

cursor = connection.cursor()
clear_users(cursor)
clear_users(cursor)

2. Внедрение через параметры конструктора:

 class UsersDAO:
def __init__(self, cursor):
self.cursor = cursor
def clear_users(self):
self.cursor.execute("TRUNCATE users;")

dao = UsersDAO(connection.cursor())
dao.clear_users()
dao.clear_users()

3. Внедрение через атрибуты экземпляра (см. так же двухфазная инициализация):

 class UsersDAO:
def clear_users(self):
self.cursor.execute("TRUNCATE users;")

dao = UsersDAO()
dao.cursor = connection.cursor()
dao.clear_users()
dao.clear_users()

Популярные заблуждения:
Это что-то из мира java, в моем языке его нет. Неверно. Для того чтобы в языке можно было реализовать внедрение зависимостей, необходимо лишь иметь возможность передать ссылку на функцию или на объект. Это применимо как к Javascript и Python, так и к C и Golang.
Он нужен только большим enterprise приложениям. Скорее, он критичен для больших приложений. Небольшие приложения без автоматических тестов могут действительно существовать без внедрения зависимостей, но по мере усложнения необходимость в нем будет все более и более заметна.
Для него нужен специальный фреймворк/IoC-контейнер. Как показано выше, для DI не нужен никакой фреймворк, это возможность вашего языка. Фреймворки лишь помогут упростить построение графа зависимостей (когда у вас достаточно много разных связанных объектов) или решить какие-то прикладные задачи связанные с этим. Хуже, что неосторожное использование таких фреймворков может наоборот лишить вас DI, хотя вы будете думать что это не так.

Дополнительные материалы:
https://martinfowler.com/articles/dipInTheWild.html
https://www.jamesshore.com/v2/blog/2006/dependency-injection-demystified
  • 👍 110
  • 🔥 22
  • ❤ 8
  • 🐳 6
  • 👀 4
  • 🤮 2
  • 🤡 2
  • 😁 1
  • 🎅 1
  • 🗿 1
More from @advice17
  1. May 31, 2026Юзкейсы, сценарии и интеракторы Когда мы пишем наш код (программу, сервис, библиотеку), мы…
  2. Feb 17, 2026Меня позвали поговорить о разном: о проектах, опыте, программировании в целом. https://www…
  3. Jan 11, 2026SQLAlchemy и ORM SQLAlchemy в python предоставляет два набора API: 1. Возможность конструи…
  4. Nov 4, 2025Asyncio и колбэки В прошлом посте мы рассмотрели как asyncio взаимодействует с генераторам…
  5. Sep 27, 2025Стейт при работе с базами данных Подходы работы с БД можно разделить на две группы: • Орие…
  6. Aug 7, 2025Asyncio и цикл событий Чтобы понять, как рабоатет asyncio, давайте рассмотрим, как в Pytho…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →