Действительно ли Внедрение зависимости является шаблоном и, является этим он?

Я имел горячий спор с одним из моих коллег на внедрении зависимости и понял, что не вполне знал всех фактов на предмете.

Так, возьмите этот код (именно так, Вы знаете, мы используем замок Windsor),

IPlayerService service = Container.Resolve<IPlayerService>();

Вышеупомянутый код является, очевидно, примером DI с помощью МОК.

Однако см. код ниже (ОБНОВЛЕНИЕ: Предположите, что я передаю ВСЕ внешние зависимости через конструктора):

var playerClient = new PlayerClient();
var playerSkinClient = new PlayerSkinClient();
IPlayerService service = new PlayerService(playerClient, playerSkinClient);

Моя конкуренция была то, что вышеупомянутый код был примером шаблона DI, и что DI может существовать без МОК.

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

  1. Так, DI может использоваться как просто шаблон без какого-либо дополнительного frameworking?

  2. Если так, является вышеупомянутый код примером его?

  3. Наконец, что определяет шаблон DI, если он существует без понятия Контейнера.

ОБНОВЛЕНИЕ

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

13
задан andy 30 June 2010 в 07:19
поделиться

8 ответов

В мире Java внедрение зависимостей часто включает в себя фреймворк, контейнер и так далее. Но нет необходимости во всей этой машинерии.

Суть инъекции зависимостей заключается в том, что класс может быть назначен объектам, от которых он зависит, вместо того, чтобы жестко кодировать их в реализации. Если вы можете "внедрить" эти "зависимости" извне класса, то у вас есть инъекция зависимостей. Фреймворк может быть хорошим способом сделать это, но он не обязателен.

В мире Python нет культуры фреймворков для инъекции зависимостей, поэтому многие программисты недоумевают, к чему вся эта суета. Для них DI - это "просто" возможность передавать объекты или классы в конструкторы.

Чтобы ответить на ваш конкретный вопрос:

  1. Да, DI может быть реализовано без фреймворка.

  2. Да, приведенный выше код является примером этого: PlayerService не знает, откуда взялись PlayerClient или PlayerSkinClient. Они были инжектированы в класс. Обратите внимание, что другие здесь ответили на этот вопрос "Нет".

  3. См. выше.

3
ответ дан 1 December 2019 в 21:51
поделиться

Это действительно не пример DI.

Причина в том, что вы упорядочиваете зависимости ( PlayerClient и PlayerSkinClient в вашем случае) вместо того, чтобы упорядочивать зависимости для вас (передаваемые контейнером при создании бетонного объекта). IPlayerService ). Это «инверсия управления» - у вас вызывается конструктор, вместо того, чтобы вызывать его. Это основная причина использования шаблона DI, и наличие контейнера, который определяет, разрешает и помещает зависимости в объекты, которые их запрашивают, является конкретным способом сделать это.

Когда вы позволяете контейнеру управлять передачей зависимостей, вам не нужно писать и поддерживать код, который передает зависимости конкретному IPlayerService . Это позволяет вам выполнять другие реализации PlayerClient и PlayerSkinClient (например, когда вы хотите имитировать их для построения тестов) и не обновлять код, который инициализирует IPlayerService . Вот почему полезен шаблон DI.

0
ответ дан 1 December 2019 в 21:51
поделиться

Итак, можно ли использовать DI как шаблон без каких-либо дополнительных рамок?

Да, безусловно.

Если да, то приведенный выше код является примером этого?

Да, безусловно.

И наконец, что определяет шаблон DI, если он существует, без понятия Контейнера.

Объекту дано все, от чего он зависит; ему вводятся его зависимости.

4
ответ дан 1 December 2019 в 21:51
поделиться

Вот некоторые другие статьи, которые могут привести некоторые другие важные детали по этому вопросу в порядке «в первую очередь следует прочитать»:

  1. Dependency Injection Demystified ;
  2. ​​Внедрение зависимости .

Прочитав их, я обнаружил, что лучше понимаю предмет.

0
ответ дан 1 December 2019 в 21:51
поделиться

По словам Мартина Фаулера, который в некоторой степени является экспертом в этой области, внедрение зависимостей - это другое название конкретной реализации абстрактной концепции, известной как инверсия управления ( полная статья ).

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

IoC - это то же самое, но, как говорит Мартин Фаулер, выражение «инверсия управления» - очень тупой способ описания того, что происходит.

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

Пример не-IoC / не-DI:

class Foo
{
    void DoSomething()
    {
        DbConnection myConnection = new DbConnection(ConfigurationSettings...);
        myConnection.ExecuteCommand();
    }
}

То же самое с использованием IoC / DI:

class Foo
{
    private DbConnection myConnection;

    public Foo(DbConnection conn)
    {
        myConnection = conn;
    }

    void DoSomething()
    {
        myConnection.ExecuteCommand();
    }
}

Я с уважением не согласен с теми, кто утверждает, что это не настоящий IoC / DI, если у вас нет явного связующего / ассемблера / что-то, что связывает внедренные типы с конкретными реализациями, потому что класс, получающий зависимости, не знает разницы. Независимо от того, упорядочиваете ли вы зависимости во внешнем классе или во внешнем файле конфигурации, это детали реализации.

15
ответ дан 1 December 2019 в 21:51
поделиться
  1. Да, хотя по сравнению с чем-то вроде PicoContainer - или другими действительно крошечными контейнерами, все из которых протестированы и хорошо продуманы - в конечном итоге вы реализуете тот же набор функций. Лучшим примером этого является статья Ayende "Building an IoC container in 15 lines".

  2. Пересмотрев свой ответ, я решил ответить "да". Я думаю, что основной когнитивный диссонанс здесь заключается в том, что из-за того, что разработчики путают тот факт, что многие/большинство DI/IoC-фреймворков предлагают аккуратные способы построения объектов, которые не выглядят как new, именно это заставляет их придерживаться идей IoC.

  3. Как уже упоминалось, определение Мартина Фаулера является каноническим, и оно довольно хорошо освещено в других источниках.

1
ответ дан 1 December 2019 в 21:51
поделиться

Забавно то, что первый пример - это вообще не DI, а пример анти-паттерна Service Locator - ничего не вводится .

Ваш собственный пример - это чистый DI, а точнее реализация паттерна Constructor Injection .

DI - это не один шаблон, а набор шаблонов и принципов. Когда мы подключаем все зависимости вручную, мы обычно называем это Poor Man's DI . Другими словами, контейнеры DI не являются обязательными, но настоятельно рекомендуется:)

См. Также это описание того, что контейнер DI привносит в таблицу .

1
ответ дан 1 December 2019 в 21:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: