Skip to content

Посты

Может ли внедрение зависимостей сделать меня лучшим программистом на Python?

16 февраля 2025 г. • 3 мин чтения

Может ли внедрение зависимостей сделать меня лучшим программистом на Python?

Внедрение зависимостей — это основной инструмент в статически типизированных языках, но имеет ли смысл использовать его в Python? Сделает ли это меня лучшим программистом на Python?

И, подождите, что такое внедрение зависимостей?

Сначала ответим на вопрос: Что такое внедрение зависимостей (DI)?

Внедрение зависимостей — это паттерн, который перемещает конструирование объекта за пределы класса. Вместо этого класс зависит от абстракции.

В статически типизированных языках, таких как C# и Java, внедрение зависимостей широко используется для снижения связанности и облегчения тестирования. На самом деле, вы найдёте фреймворки внедрения зависимостей, единственная цель которых — управлять зависимостями и их взаимосвязями.

Внедрение зависимостей служит двум основным целям:

Во-первых, оно снижает сложность, принимая зависимость от абстракции.

Во-вторых, зависимость от абстракции позволяет передавать в класс или функцию различные реализации, включая моки для тестирования.

Позвольте мне продемонстрировать это кодом:

# Before 
class User:
    def __init__(self):
        self.database = SqlServerDatabase()

    def get_details(self, user_id: int):
        self.database.get_user_details(user_id)

# After  
class User:
    def __init__(self, database: Database):
        self.database = database

    def get_details(self, user_id: int):
        self.database.get_user_details(user_id)

Это внедрение зависимостей в его простейшей форме. Хотя концепция проста, её сила заключается в возможности создания гибких проектов.

В примере Before класс User тесно связан с классом SqlServerDatabase. Если мы хотим протестировать класс User, нам нужно создать новый экземпляр SqlServerDatabase.

В примере After класс User слабо связан с абстракцией Database. Мы можем передать другую реализацию абстракции Database в класс User.

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

date_string = "2023-10-01"  # Example date string
date_format = "%Y-%m-%d"    # Input string format
birthday = datetime.strptime(date_string, date_format) 
turn_of_the_century = datetime.strptime('2000-01-01', date_format)

database = PostgresDatabase("")

if birthday < turn_of_the_century:
    database = SqlServerDatabase("")

user = User(database=database)
user.get_details(user_id=1)

На строке 6 (birthday < turn_of_the_century) внедрение зависимостей позволяет нам легко менять реализации в зависимости от различных условий. Хотя эта гибкость ценна для производственного кода, одним из наиболее распространённых применений внедрения зависимостей, особенно в статических языках, является тестирование.

Вот пример:

class UserTests(unittest.TestCase):
    def test_is_authenticated(self):
        database = MockDatabase('connection_string')
        
        is_authenticated = User(database).is_authenticated('user', 'pass')

        self.assertTrue(is_authenticated)

Это простой пример с использованием класса MockDatabase. В Python мы также можем использовать встроенный класс Mock для достижения того же результата.

Интересно, что внедрение зависимостей не было широко распространено в проектах на Python, над которыми я работал. Приходя из фона статически типизированных языков, я был удивлён — это казалось контринтуитивным.

Однако есть причина для такого ограниченного распространения. Встроенная функциональность патчирования Python уже обеспечивает отличные возможности тестирования, устраняя одно из основных преимуществ внедрения зависимостей. Хотя внедрение зависимостей всё ещё может помочь снизить сложность, Python имеет другие подходы для достижения той же цели.

Я не говорю, что внедрение зависимостей не следует использовать в Python. Напротив, как и все инструменты и паттерны, есть время и место для их использования. И внедрение зависимостей — это просто ещё один инструмент в вашем арсенале, который улучшит качество вашего кода.

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

Если вы заинтересованы в дальнейшем изучении внедрения зависимостей, я рекомендую ознакомиться с двумя популярными фреймворками Python:

  • Injector (github.com/python-injector/injector)
  • Dependency Injector (python-dependency-injector.ets-labs.org)

Автор: Chuck Conway — инженер AI с почти 30-летним опытом разработки программного обеспечения. Он создает практические системы AI — конвейеры контента, агенты инфраструктуры и инструменты, которые решают реальные проблемы — и делится тем, что он узнает на этом пути. Свяжитесь с ним в социальных сетях: X (@chuckconway) или посетите его на YouTube и на SubStack.

↑ Вернуться в начало

Вам также может понравиться