2009-10-16 2 views
39

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

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

+3

Мне нравятся все ваши причины до сих пор ... Я понимаю, что это в основном опытные программисты, которые «получают» DI. Насколько я понимаю, DI - это качество. Мы, как программисты, хотим выпускать самый высокий уровень программного обеспечения, который мы можем - и его тестирование помогает. На протяжении многих лет я написал код кода, и я рад сказать, что за 10 лет прошло более 50% его работы, и без DI. Может быть, это поможет вам понять, почему я немного зарезервирован за DI? – CodeMonkey

+0

Очевидно, что DI является относительно новым. Поэтому, конечно, вы можете писать высококачественное программное обеспечение без него - но с продвижением таких вещей, как тестирование фреймворков и TDD, DI может значительно упростить запись тестов, а также писать код, который можно сохранить в будущем (связь). – digiarnie

ответ

44

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

Одна из наиболее веских причин для DI заключается в том, чтобы упростить тестирование модулей без необходимости попадания в базу данных и беспокоиться о настройке «тестовых» данных.

+2

Итак, вы говорите об удалении базы данных и «подделке», используя некоторые поддельные объекты вместо того, чтобы менять мою БД во время моих модульных тестов ... хм ... звучит как разумный аргумент на самом деле! – CodeMonkey

+0

Но так как это тестовая база данных, действительно ли имеет значение, что моя база данных обновляется? – CodeMonkey

+5

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

1

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

+0

Не могли бы вы подробнее рассказать о терминах «заглушка» и «макет» ... Я предполагаю, что «макет» - это то, что я называл «поддельными» -объектами. – CodeMonkey

+2

. Остановившись, я имел в виду замену любой зависимости чем-то «else» для тестирование. Посредством макета я имею в виду использование библиотеки, такой как jmock или mockito (если вы используете java, конечно), чтобы создать прокси-сервер, где вы объявляете ожидания на этом «макетном» объекте. Вы также можете создать фиктивную версию класса, реализовав интерфейс зависимостей. – digiarnie

+0

Когда u mock object, зарегистрируйте его в регистре di или просто передайте объект-заглушку? через конструктор, например. – liang

5

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

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

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

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

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

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

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

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

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

6

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

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

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

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

+1

+1 для упоминания о том, как каркасы контейнеров DI/IoC могут заменить злой шаблон Singleton! – TrueWill

+0

В большинстве инфраструктур DI, которые я вижу, есть как минимум 2000 строк кода, которые выглядят как много кода. Кроме того, похоже, что вы не можете использовать фреймворк без изменения существующего кода. По вашему опыту, легко ли менять рамки DI для другого? – Boon

+0

@TrueWill Почему Синглтон зло, а версия DI, хорошо? – zehelvion

4

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 предоставляют входные данные для тестируемого приложения, так что тест может быть выполнен на другом. С другой стороны, макеты предоставляют вход для теста, чтобы принять решение об ошибке pass \ fail.

Martin Fowler has a great article on the difference between Mocks and Stubs

1

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

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

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

+0

+1 для упоминания servicelocator. Я думаю, что иногда DI кажется излишним, когда люди используют только «аспект обслуживания». –

0

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

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

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

+0

Я задал этот вопрос много лет назад, и с тех пор я многому научился. То, что вы описываете, будет эффективно решено с помощью контейнера IoC и введет созданный объект с помощью DI. Так, например, вы настраиваете свой «сложный» объект в реестре контейнера IoC и «запрашиваете» экземпляр того, который вы вводите в код, в котором он вам нужен. Я согласен с тем, что это также является веской причиной для использования DI. – CodeMonkey

9

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

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

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

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

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

+0

Это также полезно при быстром развитии, если вы ищете гибкость (потому что вы хотите провести эксперименты). Вы можете легко подключить разные виды, структуры данных, меню, схемы управления, а какие нет. В основном (если я правильно понимаю и использую его), вы можете более гибко и организованно управлять «зависимостями» с меньшим кодовым шумом котельной. Конечно, это может быть неправильно использовано и как-то сделать код более сложным потенциально. – zehelvion

Смежные вопросы