Краткое введение во внедрение зависимостей: что это и когда это необходимо использовать

Sergey Ufocoder
4 min readNov 4, 2018

--

Вольный перевод статьи Bhavya Karia: A quick intro to Dependency Injection: what it is, and when to use it.

Введение

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

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

Перед тем как понять, что же это означает в программировании, давайте сначала разберемся, что это означает в общем смысле. Таким образом это поможет нам лучше разобраться с этим понятием.

Зависимость или зависимое — означает полагаться на что-то. Это все равно что, если сказать, что мы слишком много полагаемся на мобильные телефоны — это означает, что мы зависим от них.

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

Когда класс A использует некоторую функциональность из класса B, тогда говорят, что класс A зависим от класса B.

Демонстрация зависимости между классами

В Java, прежде чем мы сможем использовать методы других классов, нам необходимо для начала создать экземпляры этого класса (то есть класс А должен создать экземпляр класса В).

Таким образом, передавая задачу создания объекта чему-то другому и прямое использование этой зависимости называется внедрением зависимостей.

Если бы код умел разговаривать

Так почему следует использовать внедрение зависимостей?

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

Без использования внедрения зависимостей

Перед вами класс Car, отвечающий за создание всех объектов зависимостей. Теперь, что если мы решим избавиться колес компании MRFWheels и хотим использовать колеса от Yokohama в будущем?

Нам нужно будет воссоздать объект класса Car с новой зависимостью от Yokohama. Но при использовании внедрении зависимостей мы можем изменить колеса во время выполнения программы (потому что зависимости можно внедрять во время выполнения, а не во время компиляции).

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

Это делает наш класс автомобилей независимым от создания объектов таких как колеса, аккумулятор и т.д.

Существует три основных типа внедрения зависимостей:

  1. constructor injection: все зависимости передаются через конструктор класса.
  2. setter injection: разработчик добавляет setter-метод, с помощью которого инжектор внедряет зависимость
  3. interface injection: зависимость предоставляет инжектору метод, с помощью которого инжектор передаст зависимость. Разработчики должны реализовать интерфейс, предоставляющий setter-метод, который принимает зависимости

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

  1. Создание объектов;
  2. Представление о том, какие классы требуются этим объектам;
  3. И предоставление зависимостей этим объектам.

Если есть какие-либо изменения в объектах, то DI смотрит на него, и он не должен относиться к классу с использованием этих объектов.

Таким образом, если объекты будут меняться в будущем, тогда ответственность DI заключается в предоставлении соответствующих объектов классу.

Инверсия управления — концепция, лежащая в основе внедрения зависимости

Это означает, что класс не должен конфигурировать свои зависимости статистически, а должен быть сконфигурирован другим классом извне.

Это пятый принцип S.O.L.I.D из пяти основных принципов объектно-ориентированного программирования и разработки от дяди Боба, в котором говорится, что класс должен зависеть от абстракции, а не от чего-то конкретного (простыми словами, жестко закодированного).

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

Замечание: Если вы хотите узнать больше о принципах SOLID от дяди Боба вы можете перейти по этой ссылке.

Преимущества использования внедрения зависимостей

  1. Помогает в модульном тестировании
  2. Количество шаблонного кода сокращается, поскольку инициализация зависимостей выполняется компонентом инжектора;
  3. Расширение приложения становится еще проще;
  4. Помогает уменьшить связность кода, что важно при разработке приложений.

Недостатки использования внедрения зависимостей

  1. Это несколько сложновато для изучения, а чрезмерное использование может привести к проблемам управления или другим проблемам.
  2. Многие возможные ошибки из процесса компиляции перемещаются в процесс выполнения программы.
  3. Внедрения зависимостей во фреймворках реализовано с помощью рефлексии или динамического программирования. Это может помешать использованию автоматизации разработки с помощью IDE, например, будет сложно воспользоваться функциями «найти ссылки», «показать иерархию вызовов» и будет сложно заниматься безопасно рефакторингом.

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

Библиотеки и фреймворки, реализующие внедрение зависимостей

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

Надеюсь, это вам помогло!

--

--