Подтвердить что ты не робот

Когда использовать инъекцию зависимостей

У меня было определенное чувство, что эти последние пару дней, что инъекция зависимостей действительно должна называться "Я не могу решить" - паттерна. Я знаю, что это может показаться глупым, но на самом деле это связано с тем, почему я должен использовать Dependency Injection (DI). Часто говорят, что я должен использовать DI, чтобы достичь более высокого уровня свободной связи, и я получаю эту часть. Но действительно... как часто я меняю свою базу данных, как только мой выбор упал на MS SQL или MySQL. Очень редко?

Есть ли у кого-то очень веские причины, по которым DI - это путь?

4b9b3361

Ответ 1

Два слова, модульное тестирование.

Одной из наиболее веских причин для DI является упрощение модульного тестирования без необходимости попадания в базу данных и беспокоиться о настройке "тестовых" данных.

Ответ 2

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

DI наиболее полезен, когда вы нацелены на повторное использование кода, универсальность и надежность изменений в проблемном домене.

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

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

DI больше относится к разработке корпоративных приложений, в которых у вас есть большой объем кода, сложные бизнес-требования и ожидания (или надежды), что система будет поддерживаться в течение многих лет или десятилетий.

Ответ 3

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

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

Кроме того, он также просто экономит много работы, написав код шаблона. Нужен ли мне синглтон? Я просто настраиваю класс как один. Могу ли я тестировать такой "синглтон"? Да, я все еще могу (так как я просто КОНФИГУРИРОВАЛ его существовать только один раз, но тест может создать альтернативную реализацию).

Но, кстати, до того, как я использовал DI, я действительно не понимал его достоинства, но старался, чтобы это стало для меня настоящим открытием: мои проекты намного объективны, как и раньше. Кстати, с текущим приложением я НЕ блок-тест (плохой, плохой я), но я НИКОГДА не мог жить с DI больше. Это намного легче перемещать вещи и держать классы маленькими и простыми.

Ответ 4

Пока я соглашаюсь с вами с примером DB, одна из больших вещей, которые я нашел полезной для использования DI, - это помочь мне протестировать слой, который я создаю поверх базы данных.

Вот пример...

У вас есть база данных.

У вас есть код, который обращается к базе данных и возвращает объекты

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

Если вы объедините доступ к данным с логикой вашего бизнес-домена, объекты вашего домена могут стать трудными для тестирования. DI позволяет вам вводить ваши собственные объекты доступа к данным в ваш домен, чтобы вы не зависели от базы данных для тестирования или, возможно, демонстраций (выполнялась демонстрация, в которой некоторые данные были извлечены из xml вместо базы данных).

Абстрактные сторонние компоненты и фреймворки, подобные этому, также помогут вам.

Помимо примера тестирования, есть несколько мест, где DI можно использовать с помощью подхода Design by Contract. Возможно, вам будет необходимо создать механизм обработки, который вызывает методы объектов, которые вы вставляете в него. Хотя это может и не по-настоящему "обрабатывать", он запускает методы, которые имеют различную реализацию в каждом объекте, который вы предоставляете.

Я увидел пример этого, где каждый объект бизнес-домена имел функцию "Сохранить", которую вызывал после того, как он был введен в процессор. Процессор модифицировал компонент с информацией о конфигурации, а Save обработал первичное состояние объекта. По существу, DI дополнял реализацию полиморфного метода объектов, соответствующих интерфейсу.

Ответ 5

Injection Dependency дает вам возможность изолировать отдельные единицы кода.

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

public class Foo
{
    private Bar _bar;

    public Foo(Bar bar)
    {
        _bar = bar;
    }

    public bool IsPropertyOfBarValid()
    {
        return _bar.SomeProperty == PropertyEnum.ValidProperty;
    }
}

Теперь скажем, что Bar создается и его свойства задаются данными из некоторого источника данных в его конструкторе. Как я могу протестировать метод IsPropertyOfBarValid() Foo (игнорируя тот факт, что это невероятно простой пример)? Ну, Foo зависит от экземпляра Bar, переданного конструктору, который, в свою очередь, зависит от данных из источника данных, для которого установлены свойства. Нам хотелось бы выделить способ отделить Foo от ресурсов, от которых он зависит, чтобы мы могли проверить его изолированно

Здесь вводится инъекция зависимостей. Мы хотим, чтобы какой-то способ подделать экземпляр Bar, переданный в Foo, чтобы мы могли управлять свойствами, установленными на этом подделке Bar, и добиваться того, что мы что реализация IsPropertyOfBarValid() делает то, что мы ожидаем от него, т.е. возвращает true, когда Bar.SomeProperty == PropertyEnum.ValidProperty и false для любого другого значения.

Существует два типа поддельных объектов: Mocks и Stubs. Stubs предоставляют входные данные для тестируемого приложения, так что тест может быть выполнен на другом. С другой стороны, Mocks обеспечивают ввод теста для принятия решения о прохождении \fail.

У Мартина Фаулера есть отличная статья о различии между Mocks и Stubs

Ответ 6

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

Ответ 7

Я думаю, что DI стоит использовать, когда у вас много служб/компонентов, реализация которых должна быть выбрана во время выполнения на основе внешней конфигурации. (Обратите внимание, что такая конфигурация может принимать форму XML файла или комбинации аннотаций кода и отдельных классов; выберите то, что более удобно.)

В противном случае я бы просто использовал ServiceLocator, который намного "легче" и понятнее, чем целая инфраструктура DI.

Для модульного тестирования я предпочитаю использовать насмешливый API, который может имитировать объекты по требованию, вместо того, чтобы требовать их "впрыскивания" в тестируемый блок из теста. Для Java одна такая библиотека является моей собственной, JMockit.

Ответ 8

Я просто понял сегодня. Для меня зависимая инъекция - это метод для объектов-экземпляров, которые требуют большого количества параметров для работы в определенном контексте.

Когда вы должны использовать инъекцию зависимостей? Вы можете использовать инъекцию зависимостей, если вы ставите объект статическим способом. Например, если вы используете класс, который может преобразовывать объекты в файл XML или JSON, и если вам нужен только файл XML. Вам нужно будет инициировать объект и настроить много вещей, если вы не используете инъекции зависимостей.

Когда вы не должны использовать инъекцию подкрепления? Если объект запрашивается с параметрами запроса (после формы заявки), вы не должны использовать инъекцию подкрепления, потому что объект не ставится статическим способом.