Я обнаружил, что мои конструкторы начинают выглядеть так:
public MyClass(Container con, SomeClass1 obj1, SomeClass2, obj2.... )
с постоянно увеличивающимся списком параметров. Поскольку «Контейнер» является моим контейнером внедрения зависимостей, почему я не могу просто сделать это:
public MyClass(Container con)
для каждого класса? Каковы недостатки? Если я делаю это, я чувствую, что использую прославленную статику. Пожалуйста, поделитесь своими мыслями о безумии IoC и Dependency Injection.
c#
java
dependency-injection
inversion-of-control
ioc-container
JP Richardson
источник
источник
Ответы:
Вы правы в том, что если вы используете контейнер в качестве локатора службы, это более или менее прославленная статическая фабрика. По многим причинам я считаю это анти-паттерном .
Одним из замечательных преимуществ использования Constructor Injection является то, что он делает нарушения принципа единой ответственности совершенно очевидными.
Когда это произойдет, пришло время провести рефакторинг в Facade Services . Короче говоря, создайте новый, более грубый интерфейс, который скрывает взаимодействие между некоторыми или всеми мелкозернистыми зависимостями, которые вам требуются в настоящее время.
источник
Я не думаю, что ваши конструкторы классов должны иметь ссылку на ваш период контейнера IOC. Это представляет ненужную зависимость между вашим классом и контейнером (тип зависимости, которую IOC пытается избежать!).
источник
MyClass myClass = new MyClass(IDependency1 interface1, IDependency2 interface2)
(параметры интерфейса). Это не связано с постом @ производного, который, как я понимаю, говорит, что контейнер внедрения зависимостей не должен внедрять себя в свои объекты, т.MyClass myClass = new MyClass(this)
Трудность передачи параметров не является проблемой. Проблема в том, что ваш класс делает слишком много, и его нужно больше разбивать.
Внедрение зависимостей может служить ранним предупреждением для классов, становящихся слишком большими, особенно из-за усиливающейся боли во всех зависимостях.
источник
Я натолкнулся на похожий вопрос о внедрении зависимостей на основе конструктора и о том, насколько сложным было передать все зависимости.
Один из подходов, который я использовал в прошлом, заключается в использовании шаблона фасада приложения с использованием сервисного уровня. Это будет иметь грубый API. Если этот сервис зависит от репозиториев, он будет использовать метод установки частных свойств. Это требует создания абстрактной фабрики и перемещения логики создания репозиториев в фабрику.
Подробный код с объяснением можно найти здесь
Лучшие практики для IoC на уровне сложных сервисов
источник
Я прочитал всю эту ветку дважды, и я думаю, что люди отвечают тем, что они знают, а не тем, что спрашивают.
Исходный вопрос JP выглядит так, как будто он строит объекты, отправляя распознаватель, а затем группу классов, но мы предполагаем, что эти классы / объекты сами по себе являются сервисами, готовыми для внедрения. Что, если они не?
JP, если вы хотите использовать DI и хотите , чтобы у вас была возможность смешивать инъекции с контекстными данными, ни один из этих паттернов (или предполагаемых «анти-паттернов») специально не решает эту проблему. Это на самом деле сводится к использованию пакета, который будет поддерживать вас в таких усилиях.
... этот формат редко поддерживается. Я считаю, что сложность программирования такой поддержки, добавляемая к жалкой производительности, которая может быть связана с реализацией, делает ее непривлекательной для разработчиков с открытым исходным кодом.
Но это должно быть сделано, потому что я должен иметь возможность создавать и регистрировать фабрику для MyClass'а, и эта фабрика должна иметь возможность получать данные / ввод, которые не превращаются в «службу» только для передачи данные. Если «анти-паттерн» связан с негативными последствиями, то форсирование существования искусственных типов сервисов для передачи данных / моделей, безусловно, является негативным (наравне с вашим чувством оборачивания ваших классов в контейнер. Применяется тот же инстинкт).
Однако существуют рамки, которые могут помочь, даже если они выглядят немного некрасиво. Например, Ninject:
Создание экземпляра с использованием Ninject с дополнительными параметрами в конструкторе
Это для .NET, популярно и еще нигде не так чисто, как должно быть, но я уверен, что есть что-то на любом языке, который вы выберете.
источник
Внедрение контейнера - это быстрый путь, о котором вы в конечном итоге пожалеете.
Чрезмерная инъекция не является проблемой, это, как правило, является признаком других структурных недостатков, в первую очередь разделения проблем. Это не одна проблема, но она может иметь много источников, и что делает это так трудно исправить, это то, что вам придется иметь дело со всеми из них, иногда в одно и то же время (подумайте о спагетти без сплетений).
Вот неполный список вещей, которые нужно посмотреть
Плохой дизайн домена (агрегированные корни… и т. Д.)
Плохое разделение интересов (состав службы, команды, запросы). См. CQRS и Sourcing Event.
ИЛИ Mappers (будьте осторожны, эти вещи могут привести к неприятностям)
Просмотр моделей и других DTO (никогда не используйте повторно и старайтесь свести их к минимуму !!!!)
источник
Проблема:
1) Конструктор с постоянно увеличивающимся списком параметров.
2) Если класс наследуется (например:),
RepositoryBase
то изменение сигнатуры конструктора вызывает изменения в производных классах.Решение 1
Перейти
IoC Container
к конструкторуЗачем
Почему нет
Решение 2
Создайте класс, который группирует весь сервис и передайте его конструктору
Производный класс
Зачем
A
зависит класс , эта информация накапливается вA.Dependency
Почему нет
X.Dependency
отдельно)IoC Container
Решение 2 просто необработанное, хотя, если есть веские аргументы против него, то желательно иметь описательный комментарий
источник
Это подход, который я использую
Вот грубый подход, как выполнить инъекции и запустить конструктор после введения значений. Это полностью функциональная программа.
В настоящее время я работаю над проектом хобби, который работает следующим образом: https://github.com/Jokine/ToolProject/tree/Core
источник
Какую инфраструктуру внедрения зависимостей вы используете? Вы пробовали использовать инъекцию на основе сеттера?
Преимущество внедрения на основе конструктора состоит в том, что это выглядит естественным для Java-программистов, которые не используют DI-инфраструктуры. Вам нужно 5 вещей для инициализации класса, тогда у вас есть 5 аргументов для вашего конструктора. Недостатком является то, что вы заметили, это становится громоздким, когда у вас много зависимостей.
В Spring вы можете вместо этого передавать требуемые значения с помощью сеттеров и использовать аннотации @required, чтобы обеспечить их внедрение. Недостатком является то, что вам нужно переместить код инициализации из конструктора в другой метод и иметь вызов Spring, который после внедрения всех зависимостей помечает его как @PostConstruct. Я не уверен насчет других фреймворков, но я предполагаю, что они делают нечто подобное.
Оба способа работают, это вопрос предпочтений.
источник