Должно ли использование DI / IoC удалить все вхождения ключевого слова «new»?

21

Должно ли использование Dependency Injection и контейнера Inversion of Control удалить все вхождения newключевого слова " " из вашего кода?

Другими словами, должен ли каждый объект / зависимость, независимо от того, простой ли он или недолговечный, быть «зарегистрирован» в вашем контейнере IoC и внедрен в метод / класс, который должен их использовать?

Если нет, то где вы проводите линию, между которой зависимости / объекты регистрируются в контейнере IoC, по сравнению с тем, что создается с помощью newключевого слова в виде конкретной ссылки "in-line" ?

CraigTP
источник
У меня была та же мысль, в духе "новое" слово из 4 букв? "
Майкл Пасха

Ответы:

27

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

Я предпочитаю использовать «новый» для структур данных, которые не имеют поведения.

Если у класса действительно есть поведение, я тогда смотрю на область этого поведения. Если он не имеет состояния и не имеет никаких зависимостей, я склоняюсь к «новому». Я начинаю рефакторинг в сторону DI только тогда, когда мне нужно добавить зависимость от ресурсов с состоянием (таких как база данных или файл) или других классов с такими ресурсами.

Алекс Бейненсон
источник
15
+1 за "избежать догмы". Слишком легко попасть в ловушку, просто следуя движениям, не понимая, что происходит и где это следует использовать должным образом.
Уэйн Молина
@ Алекс, мне это нравится. Очень прагматичный подход. Как ни странно, я собирался добавить некоторый код в свой вопрос, показывающий newзависимость ed в моем собственном коде, который вызвал мой вопрос. Это был простой класс без функциональности или «поведения» как таковой, только с простыми свойствами.
CraigTP
11

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

Имейте в виду, что применение DI не должно полагаться на DI-контейнер . В случае использования DI Бедного Человека никакие newключевые слова не удаляются - они просто перемещаются в Корень Композиции .

Некоторые люди на самом деле предпочитают DI Бедного Человека, а не DI Контейнеры. Стоимость обслуживания может быть выше, но вы получите взамен безопасность при компиляции. Как я недавно слышал, Дэн Норт говорит: « newэто новое new» :)

Под этим подразумевается просто то, что вместо реализации Composition Root с DI-контейнером он просто содержит целую кучу вложенных newоператоров.

Марк Симанн
источник
Марк, чтобы немного расширить мой комментарий в Твиттере , Программисты - это подходящее место для концептуальных, досочных вопросов, которые не связаны с конкретной ошибкой в ​​реализации.
Адам Лир
3
Переполнение стека содержит более 2000 вопросов в теге внедрения зависимостей, и многие из них похожи на этот. У программистов 23 вопроса в одном теге. Исходя из этих цифр, куда должен пойти разработчик, чтобы получить наибольший шанс получить ответ на такой вопрос?
Марк Симанн
1
Многие из этих вопросов полностью предшествуют программистам. Этот сайт был создан для того, чтобы снять концептуальные вопросы с SO и дать им специальный дом. И мы все еще растем. Это незавершенная работа, но в идеале вопросы, которые не связаны с конкретными проблемами реализации, будут перенесены сюда. Тем временем мы делаем то, что можем.
Адам Лир
3

"новый" не является запрещенным ключевым словом. Мои личные правила:

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

Все бины или модели должны создаваться с ключевым словом "new" или с фабрикой, зарегистрированной IOC, когда мне нужно, чтобы у них были включены некоторые свойства по умолчанию. Существует также частный случай вспомогательных классов, содержащих только статические методы (например, математическая служебная служба). Если они полностью автономны и не нуждаются в подключении к базе данных или другой зарегистрированной IOC службе, я оставляю их вне IOC, и они должны вызываться статически. Однако, если один такой класс должен использовать существующую службу, зарегистрированную IOC, я изменяю ее на одноэлементный класс и регистрирую в IOC.

Jalayn
источник
2

Я просто хотел бы добавить к существующим ответам, которые были подняты ранее, newпрекрасно подходит для создания объектов, которые являются объектами с чистой ценностью (т.е. имеют только свойства / getters / setters). Смотрите блог тестирования Google для более подробной информации.

Джек
источник
+1 за ссылку. Пункт 9 в этом блоге отвечает на вопрос и предусматривает прагматичный различие между тем, что должно и не должно быть new«эд
CraigTP
1

Очевидно, зависит от языка, который вы используете. Если ваш язык вынуждает вас использовать объекты для представления как реального объекта, так и записей (объекта значения, структур), то ответ, скорее всего, отрицательный.

Говоря чисто о «реальных» объектах, нет ничего плохого в том, чтобы явно создавать экземпляр. Однако вы должны иметь в виду, что все классы должны следовать принципу единой ответственности. Класс не должен отвечать за выбор разработчика службы, на которую он полагается. Однако есть классы, которые несут такую ​​ответственность, т.е. предоставляют разработчиков определенных услуг. IoC может быть таким классом. Фактически любой тип фабрики - это такой класс.

Итак, подведем итог: только такие классы должны непосредственно создавать экземпляры объектов, кто несет ответственность за выбор того, какие классы создавать.
Вам могут быть полезны эти критерии: http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator

back2dos
источник
1

Одно слово: нет

Больше слов: инъекция зависимостей - это как раз то, что нужно. Это средство, с помощью которого вы вводите ресурсы, от которых зависит другой объект, но не должны знать сложные детали из другого источника. Использование DI не означает, что НИЧТО в вашей программе не должно знать, как создать любой другой объект; на самом деле, я утверждаю, что для нетривиальной программы крайне невозможно полностью избежать «нового» ключевого слова (или альтернатив, основанных на отражении). Однако DI действительно означает, что объекты, которые НЕ ДОЛЖНЫ знать, как создавать сложные объекты, требующие большого количества зависимостей, которые будут тесно связывать этот объект с другим, не должны обладать всеми этими тесно связанными знаниями.

Я хотел бы изучить две основные теории разработки программного обеспечения O / O, GRASP и SOLID. GRASP скажет вам изучить цель объекта и спросить себя: «Должен ли этот объект отвечать за создание новых объектов этого другого типа? Это часть« описания работы »этого объекта?» SOLID идет на один шаг дальше: «S» обозначает «Принцип единой ответственности», который однозначно утверждает, что объект должен иметь одну работу, и это должен быть единственный объект в программе, который выполняет эту конкретную работу.

Таким образом, GRASP, как правило, побуждает вас просматривать существующие классы, для которых создаются эти новые объекты, и находить класс, для которого задача создания этого объекта соответствует тому, что объект уже делает, сохраняя при этом желаемый уровень «сплоченности». SOLID скажет вам, что сплоченность является ключевым фактором; Задача создания этих объектов должна быть передана какой-то фабрике, которая должна быть внедрена в ваш класс. Я думаю, что по мере роста сложности вашей программы вы обнаружите, что соблюдение любой из этих методологий с готовностью к рефакторингу приведет к созданию очень похожих архитектур.

Keiths
источник