Учитывая конструктор, который никогда не будет использовать какие-либо разные реализации нескольких объектов, которые он инициализирует, все еще практично использовать DI? В конце концов, мы все еще можем захотеть провести юнит тест.
Рассматриваемый класс инициализирует несколько других классов в своем конструкторе, и классы, которые он использует, довольно специфичны. Он никогда не будет использовать другую реализацию. Оправданы ли мы, избегая попыток запрограммировать интерфейс?
Ответы:
Это зависит от того, насколько вы уверены, что «никогда, никогда» правильно (во время использования вашего приложения).
В общем:
источник
В то время как преимущество кодирования перед интерфейсом довольно очевидно, вы должны спросить себя, что именно получается, если вы этого не сделаете.
Следующий вопрос: является ли частью ответственности рассматриваемого класса выбор реализаций или нет? Это может или не может иметь место, и вы должны действовать соответственно.
В конечном счете, всегда есть какое-то глупое ограничение, чтобы выйти из ниоткуда. Возможно, вы захотите запустить один и тот же фрагмент кода одновременно, и возможность внедрения реализации может помочь с синхронизацией. Или после профилирования вашего приложения вы можете обнаружить, что хотите использовать стратегию распределения, отличную от простой реализации. Или возникают сквозные проблемы, и у вас нет поддержки АОП под рукой. Кто знает?
YAGNI предполагает, что при написании кода важно не добавлять ничего лишнего. Одна из вещей, которую программисты склонны добавлять в свой код, даже не подозревая об этом, - это лишние предположения. Как «этот метод может пригодиться» или «это никогда не изменится». Оба добавляют беспорядок в ваш дизайн.
источник
Это зависит от различных параметров, но вот несколько причин, почему вы все еще можете использовать DI:
Итог: в этом случае вы, вероятно, можете жить без DI, но есть вероятность, что использование DI приведет к более чистому коду.
источник
Когда вы разрабатываете программу или функцию, частью мыслительного процесса должно быть то, как вы собираетесь его тестировать. Внедрение зависимостей является одним из инструментов тестирования, и его следует рассматривать как часть комплекса.
Дополнительные преимущества Dependency Injection и использования интерфейсов вместо классов также полезны при расширении приложения, но позже их также можно легко и безопасно перестроить на исходный код с помощью поиска и замены. - даже на очень крупных проектах.
источник
Многие ответы на этот вопрос можно обсудить как «вам это может понадобиться, потому что…», как YAGNI, если вы не хотите проводить юнит-тестирование.
Если вы спрашиваете, почему помимо юнит-тестов необходимо программировать интерфейс
Да , Dependency Injection стоит вне UnitTesting, если вам нужно инвертировать управление . Например, если одной реализации модуля нужен другой модуль, который недоступен на его уровне.
Пример: если у вас есть модули
gui
=>businesslayer
=>driver
=>common
.В этом сценарии
businesslayer
можно использовать,driver
ноdriver
не может использоватьbusinesslayer
.Если
driver
требуется некоторая функциональность более высокого уровня, вы можете реализовать эту функциональность, вbusinesslayer
которой реализует интерфейс наcommon
уровне.driver
нужно только знать интерфейс вcommon
слое.источник
Да, вы - во-первых, забудьте о модульном тестировании как о причине разработки кода с использованием инструментов модульного тестирования, никогда не стоит менять дизайн кода так, чтобы он соответствовал искусственному ограничению. Если ваши инструменты заставляют вас делать это, приобретите более совершенные инструменты (например, Microsoft Fakes / Moles, которые предоставляют вам гораздо больше возможностей для создания фиктивных объектов).
Например, вы бы разбили свои классы на общедоступные методы только потому, что инструменты тестирования не работают с закрытыми методами? (Я знаю, что превалирующая мудрость заключается в том, чтобы притворяться, что вам не нужно тестировать частные методы, но я чувствую, что это реакция на трудности, возникающие при работе с современными инструментами, а не настоящая реакция на отсутствие необходимости тестировать рядовых).
В общем, все сводится к тому, какой вы TDDer - «имитатор», как описывает их Фаулер , - нужно изменить код в соответствии с инструментами, которые они используют, в то время как «классические» тестеры создают тесты, которые более интегрированы по своей природе. (т. е. тестируйте класс как единое целое, а не как каждый метод), чтобы меньше было необходимости в интерфейсах, особенно если вы используете инструменты, которые могут издеваться над конкретными классами.
источник
Dependency Injection также делает его более ясным , что ваш объект ИМЕЕТ зависимости.
Когда кто-то собирается наивно использовать ваш объект (не глядя на конструктор), он обнаружит, что ему потребуется настроить службы, соединения и т. Д. Это было неочевидно, поскольку им не нужно было передавать их конструктору. , Передача зависимостей проясняет, что нужно.
Вы также можете скрыть тот факт, что ваш класс может нарушать SRP. Если вы передаете много зависимостей (более 3), ваш класс может делать слишком много и должен быть реорганизован. Но если вы создаете их в конструкторе, этот запах кода будет скрыт.
источник
Я согласен с обоими лагерями здесь, и этот вопрос все еще остается открытым для обсуждения YAGNI требует, чтобы я не занимался изменением своего кода в соответствии с предположением. Модульное тестирование здесь не проблема, потому что я твердо верю, что зависимость никогда не изменится. Но если бы я проходил модульное тестирование так, как задумывалось с самого начала, я бы так и не достиг этой точки. Как бы я в конечном итоге пробрался в DI.
Позвольте мне предложить другую альтернативу для моего сценария специально
С фабричным шаблоном я могу локализовать зависимости в одном месте. При тестировании я могу изменить реализацию в зависимости от контекста, и этого достаточно. Это не идет вразрез с YAGNI из-за преимуществ абстрагирования нескольких конструкций классов.
источник