Нужно ли вводить зависимость за счет инкапсуляции? - PullRequest
121 голосов
/ 17 июня 2009

Если я правильно понимаю, типичным механизмом внедрения зависимостей является внедрение либо через конструктор класса, либо через открытое свойство (член) класса.

Это обнажает вводимую зависимость и нарушает принцип инкапсуляции ООП.

Правильно ли я определил этот компромисс? Как вы справляетесь с этой проблемой?

Пожалуйста, смотрите мой ответ на мой собственный вопрос ниже.

Ответы [ 21 ]

0 голосов
/ 20 июля 2010

Я согласен, что доведенный до крайности, DI может нарушать инкапсуляцию. Обычно DI раскрывает зависимости, которые никогда не были действительно инкапсулированы. Вот упрощенный пример, заимствованный у Мишко Хевери Синглтоны - это патологические лжецы :

Вы начинаете с теста CreditCard и пишете простой модульный тест.

@Test
public void creditCard_Charge()
{
    CreditCard c = new CreditCard("1234 5678 9012 3456", 5, 2008);
    c.charge(100);
}

В следующем месяце вы получите счет на 100 долларов. Почему вы получили заряд? Юнит-тест затронул производственную базу данных. Внутренне, CreditCard звонит Database.getInstance(). Рефакторинг CreditCard таким образом, чтобы в его конструкторе заняло DatabaseInterface, показывает факт наличия зависимости. Но я бы сказал, что для начала зависимость никогда не заключалась в капсулу, поскольку класс CreditCard вызывает внешне видимые побочные эффекты. Если вы хотите протестировать CreditCard без рефакторинга, вы, безусловно, можете наблюдать зависимость.

@Before
public void setUp()
{
    Database.setInstance(new MockDatabase());
}

@After
public void tearDown()
{
    Database.resetInstance();
}

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

...