xml meta tags - Каковы преимущества контейнеров для инъекций зависимостей?




8 Answers

Для меня одной из основных причин использования IoC (и использования внешней конфигурации) является использование двух областей:

  • тестирование
  • Техническое обслуживание

тестирование

Если вы разделите свое тестирование на 3 сценария (что довольно нормально в крупномасштабной разработке):

  1. Единичное тестирование
  2. Интеграционное тестирование
  3. Испытание черного ящика

То, что вы захотите сделать, это для двух последних тестовых сценариев (Integration & Black box), не перекомпилирует какую-либо часть приложения.

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

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

производство

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

Резюме

Основные преимущества внешней конфигурации IoC связаны с предоставлением другим (не разработчикам) возможности настроить ваше приложение, по моему опыту это полезно только при ограниченном числе обстоятельств:

  • Приложение распространяется на несколько сайтов / клиентов, где среда будет отличаться.
  • Ограниченный контроль разработки / ввод в производственную среду и настройку.
  • Сценарии тестирования.

На практике я обнаружил, что даже при разработке чего-то, что у вас есть, контроль над средой, он будет запущен, со временем лучше дать кому-то возможность изменить конфигурацию:

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

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

list html

Я понимаю преимущества самой инъекции зависимости. Возьмем, к примеру, весну. Я также понимаю преимущества других функций Spring, таких как AOP, помощники разных типов и т. Д. Мне просто интересно, каковы преимущества конфигурации XML, такие как:

<bean id="Mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="John" class="foo.bar.Male">
  <property name="girlfriend" ref="Mary"/>
</bean>

по сравнению с простым старым java-кодом, например:

Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);

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

ОБНОВИТЬ:
В случае

IService myService;// ...
public void doSomething() {  
  myService.fetchData();
}

Как ядро ​​IoC может предположить, какую реализацию myService я хочу ввести, если ее несколько? Если есть только одна реализация данного интерфейса, и я позволяю контейнеру IoC автоматически решать использовать его, он будет прерван после появления второй реализации. И если есть намеренно только одна возможная реализация интерфейса, тогда вам не нужно вводить его.

Было бы действительно интересно увидеть небольшую конфигурацию для IoC, которая показывает, что это преимущества. Я использовал Spring некоторое время, и я не могу представить такой пример. И я могу показать отдельные строки, которые демонстрируют преимущества спящего режима, dwr и других фреймворков, которые я использую.

ОБНОВЛЕНИЕ 2:
Я понимаю, что конфигурация IoC может быть изменена без повторной компиляции. Это действительно такая хорошая идея? Я могу понять, когда кто-то хочет изменить учетные данные БД без перекомпиляции - он может быть не разработчиком. В вашей практике, как часто кто-то другой, кроме разработчика, меняет конфигурацию IoC? Я думаю, что для разработчиков нет усилий перекомпилировать этот конкретный класс вместо изменения конфигурации. А для не-разработчиков вы, вероятно, захотите сделать свою жизнь проще и предоставить более простой конфигурационный файл.

ОБНОВЛЕНИЕ 3:

Внешняя конфигурация отображения между интерфейсами и их конкретными реализациями

Что такого хорошего в том, чтобы сделать его extenal? Вы не делаете весь свой код внешним, в то время как вы определенно можете - просто поместите его в файл ClassName.java.txt, прочитайте и скомпилируйте вручную на лету - ничего себе, вы избежали перекомпиляции. Почему следует избегать компиляции ?!

Вы сохраняете время кодирования, потому что вы предоставляете сопоставления декларативно, а не в процедурном коде

Я понимаю, что иногда декларативный подход экономит время. Например, я объявляю только один раз, когда сопоставление между свойством bean и столбцом DB, а спящий режим использует это сопоставление при загрузке, сохранении, построении SQL на основе HSQL и т. Д. Именно здесь работает декларативный подход. В случае Spring (в моем примере) объявление имеет больше строк и имеет ту же выразительность, что и соответствующий код. Если есть пример, когда такое объявление короче кода - я бы хотел его увидеть.

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

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

mary = new FakeFemale();

Я понимаю преимущества DI. Я не понимаю, какие преимущества добавляются внешней конфигурацией XML по сравнению с настройкой кода, который делает то же самое. Я не думаю, что компиляции следует избегать - я собираю каждый день, и я все еще жив. Я думаю, что конфигурация DI является плохим примером декларативного подхода. Декларация может быть полезна, если объявлен один раз И используется много раз по-разному - например, hibernate cfg, где сопоставление свойств bean и столбца DB используется для сохранения, загрузки, построения поисковых запросов и т. Д. Конфигурация Spring DI может быть легко переведена на конфигурирование кода, как и в начале этого вопроса, не так ли? И он используется только для инициализации бина, не так ли? Что означает, что декларативный подход ничего здесь не добавляет, не так ли?

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

ПОСЛЕДНЕЕ ОБНОВЛЕНИЕ:
Ребята, много ответов рассказывают мне об инъекции зависимостей, которые я ЗНАЮ ХОРОШО. Вопрос заключается в цели конфигурации DI вместо инициализации кода. Я склонен думать, что код инициализации короче и яснее. Единственный ответ, который я получил до сих пор на мой вопрос, заключается в том, что он избегает перекомпиляции при изменении конфигурации. Думаю, я должен опубликовать еще один вопрос, потому что это большой секрет для меня, почему в этом случае следует избегать компиляции.




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

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

Я думаю, что это немного зависит от стиля, и с чем вам комфортно ... вы любите летать самостоятельно и можете знать это наизнанку или использовать существующие решения, которые могут оказаться трудными, когда конфигурация не является " t правильно? Это все компромисс.

Тем не менее, конфигурация XML - это немного мое домашнее животное ... Я стараюсь избегать его любой ценой.




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

Например, Spring позволяет реализовать интерфейс InitializingBean и добавить метод afterPropertiesSet (вы также можете указать «init-method», чтобы избежать связывания вашего кода с Spring). Эти методы позволят вам убедиться, что любой интерфейс, указанный как поле в экземпляре вашего класса, правильно настроен при запуске, а затем вам больше не нужно проверять ваши получатели и сеттеры (если вы разрешаете вашим синглонам оставаться в потоковом режиме ).

Кроме того, гораздо проще выполнять сложные инициализации с контейнером DI вместо того, чтобы делать их самостоятельно. Например, я помогаю использовать XFire (не CeltiXFire, мы используем только Java 1.4). Приложение использовало Spring, но, к сожалению, он использовал механизм конфигурации XFire services.xml. Когда в коллекции элементов необходимо объявить, что у нее были ZERO или больше экземпляров вместо ONE или более экземпляров, мне пришлось переопределить некоторые из предоставленного кода XFire для этой конкретной службы.

Существуют определенные значения по умолчанию XFire, определенные в его схеме Spring beans. Итак, если мы использовали Spring для настройки сервисов, бобы могли быть использованы. Вместо этого произошло то, что я должен был предоставить экземпляр определенного класса в файле services.xml вместо использования bean-компонентов. Для этого мне нужно было предоставить конструктор и настроить ссылки, объявленные в конфигурации XFire. Реальное изменение, которое мне нужно было сделать, чтобы перегрузить один класс.

Но, благодаря файлу services.xml, мне пришлось создать четыре новых класса, установив их значения по умолчанию в соответствии с их значениями по умолчанию в конфигурационных файлах Spring в своих конструкторах. Если бы мы могли использовать конфигурацию Spring, я бы только что сказал:

<bean id="base" parent="RootXFireBean">
    <property name="secondProperty" ref="secondBean" />
</bean>

<bean id="secondBean" parent="secondaryXFireBean">
    <property name="firstProperty" ref="thirdBean" />
</bean>

<bean id="thirdBean" parent="thirdXFireBean">
    <property name="secondProperty" ref="myNewBean" />
</bean>

<bean id="myNewBean" class="WowItsActuallyTheCodeThatChanged" />

Вместо этого он выглядел примерно так:

public class TheFirstPointlessClass extends SomeXFireClass {
    public TheFirstPointlessClass() {
        setFirstProperty(new TheSecondPointlessClass());
        setSecondProperty(new TheThingThatWasHereBefore());
    }
}

public class TheSecondPointlessClass extends YetAnotherXFireClass {
    public TheSecondPointlessClass() {
        setFirstProperty(TheThirdPointlessClass());
    }
}

public class TheThirdPointlessClass extends GeeAnotherXFireClass {
    public TheThirdPointlessClass() {
        setFirstProperty(new AnotherThingThatWasHereBefore());
        setSecondProperty(new WowItsActuallyTheCodeThatChanged());
    }
}

public class WowItsActuallyTheCodeThatChanged extends TheXFireClassIActuallyCareAbout {
    public WowItsActuallyTheCodeThatChanged() {
    }

    public overrideTheMethod(Object[] arguments) {
        //Do overridden stuff
    }
}

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




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




В мире .NET большинство инфраструктур IoC обеспечивают как конфигурацию XML, так и код.

StructureMap и Ninject, например, используют бесплатные интерфейсы для конфигурирования контейнеров. Вам больше не нужно использовать файлы конфигурации XML. Spring, которая также существует в .NET, сильно зависит от файлов XML, так как это его исторический основной интерфейс конфигурации, но по-прежнему можно программировать контейнеры программно.




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

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




Spring also has a properties loader. We use this method to set variables that are dependant on the environment (eg development, testing, acceptance, production, ...). This could be for example the queue to listen to.

If there is no reason why the property would change, there is also no reason to configure it in this way.




Initializing in an XML config file will simplify your debugging / adapting work with a client who has your app deployed on their computers. (Because it doesn't require recompilation + binary files replacement)




Related