Технический термин для обозначения противоположности внедрения зависимости?

12

Это скорее номенклатура (техническое письмо), а не чисто технический вопрос. Я пытаюсь написать предложение по рефакторингу (и назначить его себе), сосредоточенное на расширении внедрения зависимостей в нашем приложении. Хотя мы используем Spring для автоматического подключения bean-компонентов, все еще существуют экземпляры, использующие экземпляры bean-компонентов MyClass obj = new MyClass(...), которые могут быть полностью внедрены. Я хотел бы, чтобы мое предложение использовало элегантную номенклатуру и ссылалось на шаблон проектирования напротив DI с подходящим термином.

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

amphibient
источник
1
Да, связывание описывает как использование явных имен классов в других классах, так и результирующее состояние кодовой базы.
Килиан Фот
11
Нет, тесная связь описывает только свойство результирующего кода, а не противоположность DI. Вы можете использовать DI и по-прежнему иметь тесную связь по совершенно другим причинам.
Док Браун
@EricKing хвастаться. +1 кстати.
candied_orange
1
«Зависимость отсоса» .
SeldomNeedy

Ответы:

30

Нет. Тесная связь - это гораздо больше, чем то, с чем имеет дело внедрение зависимостей.

Внедрение зависимостей экстернализует решение о реализации. Это имеет большое значение для разъединения, но связь - это не только это.

Хороший антоним для внедрения зависимости - это жесткое кодирование зависимости . Когда вы создаете (используете new или непосредственно используете какую-то фабрику) внутри объекта поведения, вы смешали две разные проблемы. Сервисный локатор помогает отделить, но оставляет вас связанным с самим сервисным локатором.

Сцепление - это больше, чем просто разделение конструкции и поведения. Если у меня есть 101 метод, который нужно вызывать в определенном порядке от класса A до класса B, я тесно связан. Не имеет значения, насколько чудесно разделены конструкция и поведение.

Связь является мерой взаимозависимости двух объектов. Все, что затрудняет внесение изменений в одно без влияния на другое, способствует соединению. Внедрение зависимости помогает в этом, но это еще не все.

candied_orange
источник
Да, жесткое кодирование (зависимость), а не его внедрение (во время выполнения) - это именно то, что я собирался предложить, вы просто были немного быстрее меня.
Док Браун
7
@DocBrown Я иногда хотел бы, чтобы это место не уделяло особого внимания быстроте. Я хотел бы услышать, как бы вы это выразили.
candied_orange
Хороший ответ - внедрение зависимости не подразумевает развязки. Вера в противном случае ведет к плохой дороге
Муравей P
1
@CandiedOrange Может быть, кто-то должен предложить в мета, чтобы ответы оставались скрытыми в течение некоторого времени. И / или чтобы голоса были скрыты от публичного просмотра в течение Nнескольких часов ... Или до тех пор, пока не будет выбран ответ. Я знаю, что я не совсем объективен, когда один ответ уже имеет 10 голосов, а остальные 5 не имеют ни одного!
svidgen
1
@svidgen поиск "самый быстрый пистолет на западе" по мета. Проблема уже имеет долгую историю.
candied_orange
6

Строго говоря, внедрение зависимостей только противостоит НЕ внедрению зависимостей - и, следовательно, любой стратегии управления зависимостями, которая не является внедрением зависимостей.

[Нежелательная] связь, хотя и не совсем ортогональная, может либо возникнуть, либо быть смягчена в любом случае. Они оба связаны с DependencyClass:

public DependencyInjectedConstructor(DependencyClass dep) {
  dep.do();
}

public DependencyLookupConstructor() {
  var dep = new DependencyClass();
  dep.do();
}

DependencyLookupConstructorсвязан с конкретным DependencyClassв этом случае. Но они оба связаны с DependencyClass. Настоящее зло, если оно есть, не обязательно связано, это то, что DependencyLookupConstructorнужно изменить, если DependencyClassвнезапно понадобятся свои собственные зависимости 1 .

Однако этот конструктор / класс еще более слабо связан:

public DependencyLocatingConstructor() {
  var dep = ServiceLocator.GetMyDoer();
  dep.do();
}

Если вы работаете в C #, вышеприведенное позволит вам ServiceLocatorвозвращать что-либо при GetMyDoer()вызове, если оно имеет do()то, что DependencyLocatingConstructorимеет do(). Вы получаете преимущество проверки подписи во время компиляции, даже не будучи подключенным к полному интерфейсу 2 .

Итак, выбери свой яд.

Но в принципе, если есть конкретная «противоположность» внедрения зависимостей, это будет нечто другое в сфере «стратегий управления зависимостями». Среди прочего, если бы вы использовали в разговоре что-либо из перечисленного ниже, я бы узнал, что это НЕ внедрение зависимости:

  • Шаблон сервисного локатора
  • Зависимость локатор / местоположение
  • Прямое построение объекта / зависимости
  • Скрытая зависимость
  • «Внедрение не зависимости»

1. Как ни странно, некоторые из проблем, которые DI решает на более высоких уровнях, являются своего рода результатом [чрезмерного] использования DI на более низких уровнях. Я имел удовольствие работать над кодовыми базами с ненужной сложностью повсюду в результате приспособления к горстке мест, где эта сложность действительно помогла ... По общему признанию, я предвзятый из-за плохой экспозиции.

2. Использование местоположения услуг позволяет также легко определить различные зависимости одного и того же типа, их функциональной роли из кода вызывающего , в то же время в значительной степени агностик о том , как строится зависимость. Предположим, вам нужно решить Userили IUserдля разных целей: например, Locator.GetAdministrator()против Locator.GetAuthor()- или как угодно. Мой код может запрашивать, что ему нужно функционально, даже не зная, какие интерфейсы он поддерживает.

svidgen
источник
2
Спасение DependencyInjectedConstructor(DependencyClass dep)заключается в том, что DependencyClass может быть интерфейсом или абстрактным классом. Вот почему меня огорчает, что кодеры C # используют префикс интерфейса, как в IDependency. Как клиент, это действительно не мое дело, что это за Зависимость. Пока я не создаю это, все, что я должен знать, - как говорить с этим. Что это, это чужая проблема.
candied_orange
Очки быть, DI еще пары вас к этому интерфейсу, и не требует , что DependencyClassбыть абстрактным интерфейсом на всех. Требуется только, чтобы логика построения / конфигурации / размещения существовала «где-то еще». ... Ну, и, что более важно, вопрос в том, что DI не является "противоположностью жесткой связи" :)
svidgen
На самом деле ... я могу быть немного за пределами, говоря, что DI обязательно связывает вас с интерфейсом, даже в C #. Хотя я избегал их в C #, у меня сложилось впечатление, что я мог бы также принимать dynamicпараметры. (Но не varпараметры, если память служит.) Так что, с DI в C #, я думаю , что я должен либо кодировать интерфейс, либо я должен полностью отказаться от проверки во время компиляции.
svidgen
Объекты связаны с интерфейсами. Используете ли вы ключевое слово интерфейса или нет. Вот что такое правильный интерфейс. Все, что вы должны быть связаны с. Что вы кипите, так это детали реализации и дополнительные вещи, которые вам не нужны. Мы можем формализовать это, используя ключевое слово интерфейса, чтобы позволить клиенту сказать миру: «Все, что мне нужно, это это». Но мы не должны. Черт возьми, мы можем печатать на уток, ну на некоторых языках.
candied_orange
Я не уверен, что мы полностью не согласны. Но, чтобы уточнить ... Объекты внутренне связаны с их собственными интерфейсами, да. Но сам интерфейс навязывает зависимость только в том случае, если интерфейс имеет явное имя. В C # использование dynamicили varполучение объекта из локатора позволяет игнорировать интерфейс и использовать любой класс, который может do()вам нужен, независимо от того, реализует ли этот класс какой-либо IDoerинтерфейс. Другими словами, если у нас A-> B <-C, DI отделяет A от C, но требует, чтобы A и C были связаны с B, и предотвращает использование D, даже если D будет do().
svidgen
2

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

mcknz
источник
2
Мне нравится, instance creationно это не достаточно конкретно. DI создает экземпляры, но с помощью контроллера, а не на уровне приложения. возможноinternal instance creation
амфибия
1

Я бы пошел с инкапсуляцией зависимостей . Это выражает зависимость заблокирована, а не посещать и снова уйти.

Мартин Маат
источник