Когда не использовать IoC и DI?
Я вижу много статей, в которых говорится о том, насколько велики IoC и DI, и нет ни о чем, почему это не так здорово, потому что это может сделать код более сложным. Я также вижу, что IoC не должен находиться в основной части вашего кода, но больше для библиотек и плагинов. Статьи обычно представляют собой небольшую ссылку на то, как два шаблона могут сделать код более сложным, но не слишком подробным. Это мой вопрос - где конкретно вы не должны использовать эти шаблоны?
Это хороший поток: Что такое инверсия управления?. Если вы посмотрите дальше, появится сообщение о проверке орфографии и другое сообщение о том, что IoC, вероятно, не очень хорошо там используется, если это всего лишь один инструмент проверки орфографии. Как правило, если IoC не будет использоваться, у меня будет только один конкретный класс для интерфейса? Смысл, у меня есть IMyClass. И тогда есть только конкретный MyClassA, который реализует IMyClass. Почему я хочу там IoC?
Если у меня были MyClassA, MyClassB и MyClassC, каждый из которых реализует IMyClass, это, вероятно, хорошие кандидаты для IoC правильно?
Из того же потока кто-нибудь знает, что означает этот пост:
- Инверсия контроля = брак
- Контейнер IOC = Жена
Ответы
Ответ 1
О вашем вопросе о наличии только одной реализации интерфейса. Когда вы используете IoC, все же полезно использовать интерфейс. Намного проще создавать реальные модульные тесты (которые не зависят от реализации интерфейса для правильной работы) с использованием mocks для этих интерфейсов. Ядро использования IoC упрощает тестирование кода. Таким образом, не используйте IoC, если вы не хотите тестировать или у вас уже есть лучший план тестирования без него.
ИМХО, Увеличение и увеличение уровня IoC по сложности достигается за счет более легкого тестирования и менее связанного кода. Легче изолировать проблемы и вносить будущие изменения. Вы также можете лучше контролировать свое поведение.
Я могу видеть, когда не использовать контейнер IoC (поскольку это приводит к накладным расходам конфигурации). Это произойдет в небольших проектах, где вы можете сделать это вручную, вместо использования контейнера. Но я не вижу больших потерь при использовании DI, если вы не планируете тестировать свой код...
Ответ 2
Инверсия контроля = брак
IOC Container = Wife
Брак - это определение известного шаблона - Жена - это реализация этого шаблона; -)
Bernard.
Ответ 3
Использование контейнера IoC или нет - это не решение сделать на уровне отдельных классов - в любом проекте у вас будут типы, которые созданы и не созданы контейнером.
Компромисс сложности заключается в следующем:
- Для небольшого количества компонентов контейнер IoC добавляет некоторые служебные данные
- По мере увеличения количества компонентов в приложении:
- Без контейнера IoC добавление новых компонентов или рефакторинг становится все труднее.
- С контейнером IoC добавление новых компонентов или рефакторинг остается неизменным: вам всегда нужно беспокоиться о непосредственных зависимостях компонента, который вы добавляете или меняете.
Если вы когда-либо сталкивались с тем, что даже хорошо продуманная и поддерживаемая кодовая база становится неуправляемой с размером, вы столкнулись с проблемой, которую разрешают контейнеры IoC.
Ответ 4
От Проект Замка:
Почему бы мне не использовать его?
Вы не должны использовать инверсию Контрольный контейнер, если вы не знакомы с концепциями, и если вы не осознавайте проблем, которые они пытаются решить.
Кроме того, в зависимости от размера и сложность проекта, IoC контейнер может быть излишним. Предпочитаю используйте его на средних и крупных проектах.
Ответ 5
Жалобы на IoC легко понять: IoC превращает что-то просто в нечто сложное. Скажем, вы хотели что-то сделать для каждого элемента списка (в псевдокоде):
for each i in list:
do_something(i)
IoC, по сути, переносит ответственность за итерацию цикла на кого-то другого. Таким образом, мы получаем нечто большее:
ioc = new IocContainer()
ioc.register_callback(do_something)
ioc.go()
Обратите внимание, что даже в этой простой форме код длиннее оригинала... и не учитывает реализацию IocContainer.
Затем, в своей самой причудливой форме, IocContainer может быть инициализирован статически или статической функцией Main() или где-то еще скрытым, а функции register_callback() автоматически вызываются на основе другого кода, который итерации через XML файл который перечисляет все ваши функции do_something() и (иногда) даже содержимое списков для итерации.
Yay, файл XML сделал ваше программное обеспечение более настраиваемым! Правильно? Вы можете изменить, какие дела делаются в вашем списке, просто изменив простой текстовый файл!
Кроме того, по иронии судьбы, ваш исходный код теперь длиннее и сложнее понять, он зависит от всех видов новых, возможно, багги, библиотек (включая IocContainer и XML-парсер), и вам на самом деле было сложнее поддерживать: XML-код сложнее понять и редактировать, чем исходный простой цикл исходного кода (независимо от того, на каком языке написан цикл). У вас также меньше контроля над тем, как вы хотите выполнять итерацию (отсортированную или несортированную? Глубину-сначала или ширину?), Поскольку IocContainer отнимает эту ответственность от вас.
Для таких вещей, как плагины, может иметь смысл использовать IoC, поскольку логично для основного приложения контролировать процесс выполнения и просто запрашивать плагин для справки здесь и там. Это называется "предоставление перехватчиков" и существует гораздо дольше, чем терминология IoC.
Для таких вещей, как модульные тесты (которые я обычно видел, как их выбрасывают), IoC обычно оказывается бесполезным, потому что ваши тесты должны быть способны моделировать большое количество нечетных ситуаций, а IoC просто постоянно мешает этому.
Основополагающее предположение IoC заключается в том, что загрузка данных и прохождение через них каким-то образом сложны и должны быть отбракованы; это предположение просто неверно, потому что в любом случае это не более чем пара строк (или вы можете перенести его на отдельную функцию), и даже если он сохранит код, это уменьшит вашу гибкость.
Ответ 6
IoC/DI не являются технологиями, они являются парадигмами. Ваш вопрос сродни запросу "Когда я не должен использовать объектно-ориентированное программирование?" Это решение, которое больше, чем отдельные единицы вашей кодовой базы.
Чтобы ответить на ваш конкретный вопрос, если у вас достаточно нескольких классов, где вы можете разумно построить графы объектов вручную, и вы не повторяете одни и те же экземпляры экземпляров объектов несколько раз, вам может не понадобиться контейнер IoC.
Ответ 7
Думаю, я бы сказал, что простой ответ использует только IoC на объектах, которые вы хотите unit test.
Если это кажется легкомысленным, я извиняюсь, это из-за разочарования в коде, написанном буквально без внимания к модульному тестированию. Я не понимаю, почему добавлена сложность - если мне нужно знать фактический тип объекта, я всегда могу распечатать класс во время выполнения.
Ответ 8
В этой статье рассматривается ваш вопрос "где конкретно вы не должны использовать эти шаблоны?" и дает подробные примеры, касающиеся вашего комментария, что "два шаблона ([IoC и DI]) могут сделать код более сложным":
http://java.dzone.com/articles/beyond-injection-concerns-ioc.
Подводя итог двум пунктам этой статьи:
- Вам не следует использовать IoC/DI, где важна инкапсуляция.
- Вам не следует использовать IoC/DI, где вы не можете продемонстрировать конкретные примеры того, как сложность, добавленная посредством использования IoC/DI, взвешивается преимуществами использования IoC/DI.