Инъекция зависимостей с использованием инъекции метода против инъекции конструктора

Инъекция зависимостей с использованием инъекции метода против инъекции конструктора
Инъекция зависимостей с использованием инъекции метода против инъекции конструктора - lucabravo @ Unsplash

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

Основной способ, которым я бы определил, что является более подходящим, будет основан на том, насколько жизненный цикл объекта выровнен с его ассоциацией с объектом saver. Если экземпляру TextWriter когда-либо потребуется использовать только один saver, то я, вероятно, назначу его в конструкторе, если он доступен во время построения. С другой стороны, если хранитель потенциально специфичен для каждого вызова метода, для меня имеет смысл передать его в метод, а не создавать несколько объектов ни по какой другой причине.

Это все довольно просто и относительно независимо от языка. Есть еще несколько нюансов в этом роде. Во-первых, ничто не мешает вам делать и то, и другое, например:

class TextWriter:
    def __init__(self, saver): # dependency injected in the constructor
        self.text = ""
        self.saver = saver
        
    def write_text(self, text):
        self.text += text
        
    def save_text(self, saver=None):
        if saver is None:
           saver = self.saver

        saver.save_text(self.text)

Я считаю, что приведенное выше довольно идиоматично для Python. Этот подход можно более или менее адаптировать для работы на любом объектно-ориентированном языке. Например, в Java вы можете использовать перегруженные методы для достижения аналогичного результата. В двух словах, если вы передаете saver, он используется, если нет, используется внедренный конструктор saver.

Как указывает candied_orange, если сайт, на котором вызывается метод сохранения, не знает о хранителях (например, о сторонней библиотеке), то использование метода внедрения метода может показаться проблематичным. Однако существуют функциональные подходы к решению этой проблемы. В пакете functools есть много полезных вспомогательных функций, и одна из них — partial . Функция partial принимает метод и некоторые параметры и возвращает функцию-оболочку, которая неявно их применяет. Или, если вы предпочитаете, вы можете сделать что-то подобное в коде, как описано в начале принятого ответа на этот вопрос.

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

Прикрепляю к посту несколько видео по теме:

Прикрепленное видео 1 - Dependency injection в Python простыми словами, Dependency Injector

Прикрепленное видео 2 - Spring Framework. Урок 5: Внедрение зависимостей. Dependency Injection (DI). Введение

Прикрепленное видео 3 - Dependency Injection, Внедрение зависимостей, Вопросы на собеседовании по программированию


LetsCodeIt, 24 апреля 2023 г., 02:12