Каждый раз, когда кто-то приходит ко мне и просит меня концептуально определить Dependency Injection и объяснить реальные плюсы и минусы использования DI в разработке программного обеспечения. Признаюсь, у меня есть некоторые трудности с объяснением понятий DI. Каждый раз, когда мне нужно рассказать им историю о едином принципе ответственности, составе по наследству и т. Д.
Кто-нибудь может помочь мне объяснить лучший способ описания DI для разработчиков?
design
design-patterns
software
Тьяго Сампайо
источник
источник
Ответы:
Внедрение зависимостей - ужасное имя (IMO) 1 для довольно простой концепции. Вот пример:
DbContext
). Этот внутренний ресурс называется зависимостью.DbContext
) Из метода и возлагаете на вызывающего абонента ответственность за предоставление этого ресурса (в качестве параметра метода или при создании экземпляра класса).[1] : Я родом из низшего уровня, и мне потребовались месяцы, чтобы сесть и выучить внедрение зависимостей, потому что название подразумевает, что это будет что-то гораздо более сложное, например, внедрение DLL . Тот факт, что Visual Studio (и мы в целом разработчики) ссылается на библиотеки .NET (библиотеки DLL или сборки ), от которых зависит проект в качестве зависимостей , не помогает вообще. Существует даже такая вещь, как Ходок Зависимости (зависимость.exe) .
[Править] Я подумал, что какой-то демонстрационный код пригодится для некоторых, так что вот один (в C #).
Без внедрения зависимости:
Ваш потребитель будет делать что-то вроде:
Тот же класс, реализованный с помощью шаблона внедрения зависимостей, будет выглядеть так:
Это теперь ОТВЕТСТВЕННОСТЬ абонента создать экземпляр
DbContext
и передать (errm, инъекционные ) ему в класс:источник
Абстрактные понятия часто лучше объяснить с помощью реальной аналогии. Это моя аналогия:
Это не идеально, но подчеркивает ключевую особенность: предоставление контроля потребителю . Неотъемлемой выгодой является то, что вам больше не нужно приобретать свои собственные зависимости, и ваш потребитель беспрепятственно выбирает зависимость.
источник
Простой ответ на это:
.Net Core - довольно хороший пример, который вы можете привести, потому что в этой среде много внедрения зависимостей. Как правило, сервисы, которые вы хотите внедрить, находятся в
startup.cs
файле.Конечно, студент должен знать некоторые понятия, такие как полиморфизм, интерфейсы и принципы ООП-дизайна.
источник
Вокруг этого, по сути, простого понятия, много пуха и пустышек.
Также очень легко увязнуть в том, « какую инфраструктуру мне следует использовать », когда вы можете сделать это довольно просто в коде.
Это определение, которое я лично использую:
Некоторые примеры могут быть, где Y - файловая система или соединение с базой данных.
Фреймворки, такие как moq, позволяют определять двойные значения (симулировать версии Y) с помощью интерфейса, так что можно внедрять в экземпляр Y, где Y, например, соединение с базой данных.
Легко попасть в ловушку, полагая, что это чисто проблема модульного тестирования, но это очень полезный шаблон для любого фрагмента кода, где изменения ожидаются и, возможно, в любом случае являются хорошей практикой.
источник
Мы предоставляем поведение функции во время выполнения с помощью метода вставки этого поведения в функцию через параметр.
Стратегия Pattern является отличным примером внедрения зависимости.
источник
Чтобы сделать это правильно, мы должны сначала определить зависимости и внедрение.
Примитивным примером будет метод, который добавляет два значения. Очевидно, что этот метод нуждается в добавлении значений. Если они предоставляются путем передачи их в качестве аргументов, это уже будет случай внедрения зависимости. Альтернативой может быть реализация операндов в качестве свойств или глобальных переменных. Таким образом, никакие зависимости не будут внедрены, зависимости будут доступны извне заранее.
Предположим, вы используете вместо этого свойства и называете их A и B. Если вы измените имена на Op1 и Op2, вы нарушите метод Add. В противном случае ваша IDE обновит все имена для вас, суть в том, что метод также должен быть обновлен, поскольку он имеет зависимости от внешних ресурсов.
Этот пример является базовым, но вы можете представить более сложные примеры, когда метод выполняет операцию над объектом, таким как изображение, или когда он читает из потока файлов. Вы хотите, чтобы метод достиг изображения, требуя, чтобы он знал, где он находится? Нет. Вы хотите, чтобы метод открыл сам файл, требуя, чтобы он знал, где искать файл, или даже знал, что он будет читать из файла? Нет.
Дело в том, чтобы свести функциональность метода к его основному поведению и отделить метод от его среды. Вы получаете первое, выполняя второе, вы можете считать это определением внедрения зависимости.
Преимущества: так как зависимости для среды метода были устранены, изменения в методе не будут влиять на среду и наоборот. => Приложение становится проще в обслуживании (изменении).
источник