Стоит ли интегрировать структуры зависимостей в дополнительный слой косвенности? - PullRequest
11 голосов
/ 17 февраля 2009

Считаете ли вы, что структуры внедрения зависимостей затрудняют выполнение кода? Переосмысление перевешивает выгоду?

Ответы [ 9 ]

13 голосов
/ 17 февраля 2009

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

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

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

5 голосов
/ 17 февраля 2009

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

Итак, я предполагаю, что большая проблема с внедрением зависимостей не в самом шаблоне, а в Fad, который он в настоящее время генерирует в сообществе разработчиков. Звучит круто, поэтому есть необходимость использовать его, даже если разработка не обусловлена ​​соразмерным требованием.

Мы склонны брать большой комар к комару, потому что пистолет выглядит круто.

P

5 голосов
/ 17 февраля 2009

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

Эти вызовы представляли необходимость для объектов обнаруживать / настраивать свои собственные зависимости. Инфраструктура DI устраняет весь этот код, поэтому ваши объекты становятся проще и, следовательно, легче тестируются.

Теперь из этого следует, что, если у вас нет большой изменчивости в зависимостях ваших объектов, значение косвенности (централизованная конфигурация) для вас меньше.

Для получения более подробной информации о противопоставлении DI и ServiceLocator см. Инверсия Контейнеров управления Фаулера и образец внедрения зависимости

3 голосов
/ 20 февраля 2009

Преимущества DI трудно понять с первого взгляда. Тестируемость является наиболее очевидной. Я попытаюсь привести очень короткий пример, чтобы проиллюстрировать эти преимущества. Представьте, что ваше приложение использует определенный поставщик базы данных. Если вы сохраняете весь свой код и видите только интерфейс провайдера БД, вы легко переключитесь с одной реализации на другую. Теперь, если вы создаете корпоративные приложения, не очень важно зависеть от конкретного поставщика БД, например, когда клиент уже приобрел лицензию БД. Это на самом деле выгодно в зависимости от интерфейса, а не от реализации. Все идет нормально. Теперь мне нужно как-то достать мой конкретный объект. Мой конкретный объект может быть только экземпляром конкретного поставщика. Как мне это сделать?

  1. Используйте new для создания объекта.
    я буду придется перекомпилировать проект в Для того, чтобы распространять его. Огромный недостаток: придется тестировать, развертывать, поддерживать новую ветвь кода и т. д.
  2. Используйте Фабрику.
    Мой код будет сбрызнут с кодом, который получает завод и получает экземпляр. Также я придется вернуть общий экземпляр и привести его к типу объект я ожидаю. Если нет, я буду иметь изменять интерфейс Factory каждый раз я добавляю новый объект, созданный завод.
  3. Использовать сервисный локатор.
    Похожие как 2. Только в зависимости от услуги Локатор не всегда может быть рядом, как Java JNDI.

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

2 голосов
/ 17 февраля 2009

Мне изначально понравилась идея внедрения зависимостей, но кроме поддержки модульного тестирования, я все еще не уверен в преимуществах его использования. Это означает еще один фреймворк / API / технику для тех, кто изучает мой проект и в некоторых случаях может быть более подробным. Вы можете найти отличную информацию о плюсах и минусах этих двух конкурирующих записей в блоге

Для DI Framework

Против DI Framework

Суть сводится к тому, что действительно уменьшает сцепление и увеличивает сцепление, или это просто выталкивает проблемы под поверхность. В моем проекте сейчас я не вижу особой необходимости, даже для поддержки модульного тестирования. Если вы собираетесь подобрать его для C #, я очень рекомендую Ninject. Это легкий, простой и свободно сконфигурированный ... без XML! Sweeet:)

1 голос
/ 17 февраля 2009

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

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

Вы не можете устранить зависимости, но вы наверняка сможете скрыть их в файле конфигурации XML. В какой-то момент что-то будет называть new. Вы действительно собираетесь поменять реализацию интерфейса без перекомпиляции или повторного тестирования приложения? Если нет, то будь проще. Приятно нажать «Найти определение» и увидеть, что что-то действительно создается в классе локатора службы с явным синглтоном или ThreadStatic или некоторым другим поведением.

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

1 голос
/ 17 февраля 2009

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

Однако, Инверсия Контроля - не единственный путь сюда. Коллега добился этого, написав собственную реализацию JNDI. Мне потребовалось немало времени, чтобы победить меня, но это фантастика, и она имеет долю конфигурации типичного Spring проекта.

1 голос
/ 17 февраля 2009

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

Если навигация по исходному коду слишком сложна, получите Resharper, и все в порядке.

0 голосов
/ 17 февраля 2009

Я думаю, что выгода зависит от того, как вы ее используете.

Например, в моем текущем проекте мы используем dep inj для ввода различных элементов в зависимости от конфигурации приложения, в частности модульного тестирования. Хорошим примером может быть то, что производственная система использует реальную реализацию «входа в систему», но в модульных тестах используется фиктивный «вход в систему», который всегда возвращает true / valid для известного входа в систему, но не для других.

...