2008-08-26 3 views
16

Я использую StructureMap недавно и наслаждался опытом. Тем не менее, я могу видеть, как можно легко увлечься взаимодействием всего и заканчивать тем, что классы, которые используют лодку интерфейсов в своих конструкторах. Несмотря на то, что это действительно не проблема, когда вы используете инфраструктуру инъекций зависимостей, она по-прежнему считает, что есть определенные свойства, которые действительно не нужно связывать друг с другом только ради их взаимодействия.Когда вы используете инъекцию зависимостей?

Где вы рисуете линию, на которой нужно взаимодействовать, а не просто добавлять свойство к классу?

ответ

9

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

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

2

Что вы подразумеваете под "просто добавлением собственности в класс?"

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

РЕДАКТИРОВАНО: Вы указываете лодку интерфейсов в конструкторе. Я бы посоветовал вместо этого использовать сеттеры/геттеры. Я нахожу, что это упрощает работу в долгосрочной перспективе.

2

Я делаю это только тогда, когда это помогает с разделением проблем.

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

Но вот об этом ... всех остальных случаях это просто сделало бы систему излишне сложной

1

Даже все факты и процессы в мире .. каждое решение сводится к суждению вызова - Забыл, где я читал, что
Я думаю, что это больше времени вызова опыта/полета. В принципе, если вы видите зависимость в качестве объекта-кандидата, которую можно заменить в ближайшем будущем, используйте инъекцию зависимости. Если я увижу 'classA и его зависимости' как один блок для подстановки, то я, вероятно, не буду использовать DI для депо.

1

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

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

0

Другой предмет, с которым я сталкиваюсь, - это , где я должен использовать инъекцию зависимостей? Где вы берете свою зависимость от StructureMap? Только в стартовом приложении? Означает ли это, что все реализации должны передаваться от самого верхнего слоя до самого нижнего слоя?

22

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

Что вы действительно делаете, так это перемещение этой связи из времени компиляции во время выполнения, но если класс A нуждается в некотором интерфейсе B для работы, то должен быть предоставлен экземпляр класса, который реализует интерфейс B.

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

использует, что я видел, полезно для выворачивания шаблона управления:

  • плагин архитектуры. Таким образом, делая правильные точки входа, вы можете определить контракт на услугу, которая должна быть предоставлена.
  • Workflow-подобная архитектура. Если вы можете подключить несколько компонентов, динамически подключающих выход компонента к входу другого.
  • Приложение для каждого клиента. Предположим, у вас есть разные клиенты, которые оплачивают набор «функций» вашего проекта. Используя инъекцию зависимостей, вы можете легко предоставить только основные компоненты и некоторые «добавленные» компоненты, которые предоставляют только те функции, которые заплатил клиент.
  • Перевод. Хотя это обычно не делается для целей перевода, вы можете «вводить» различные языковые файлы по мере необходимости в приложении. Это включает в себя пользовательские интерфейсы RTL или LTR по мере необходимости.
+1

Сегодня у меня закончились голоса, поэтому я не могу проголосовать за вас, но мне нравится ваш ответ. Вы правы - только потому, что вы используете DI, это не значит, что ваш код слабо связан. – 2008-10-05 16:47:47

8

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

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

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

0

Я использую Castle Windsor/Microkernel, у меня нет опыта ни с чем другим, но мне это очень нравится.

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

Что касается того, следует ли создавать интерфейс, а просто создавать свои методы и свойства виртуальные, я думаю, что вы должны идти по интерфейсу, либо если вы либо a) можете видеть, что класс имеет некоторый уровень повторного использования в другом приложении (т. Е. logger) или b) если либо из-за количества параметров конструктора, либо из-за того, что в конструкторе существует значительная логика, класс иначе сложно высмеять.

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