Единственный законный анти-шаблон внедрения зависимостей, о котором я знаю, - это шаблон Service Locator , который является анти-шаблоном, когда для него используется структура DI.
Все другие так называемые анти-паттерны DI, о которых я слышал, здесь или в другом месте, являются лишь немного более конкретными случаями общих анти-паттернов разработки ОО / программного обеспечения. Например:
Чрезмерная инъекция в конструктор является нарушением принципа единой ответственности . Слишком много аргументов конструктора указывает на слишком много зависимостей; слишком много зависимостей указывает на то, что класс пытается сделать слишком много. Обычно эта ошибка коррелирует с другими запахами кода, такими как необычно длинные или неоднозначные («менеджер») имена классов. Инструменты статического анализа могут легко обнаружить чрезмерную афферентную / эфферентную связь.
Внедрение данных, в отличие от поведения, является подтипом анти-паттерна полтергейста , в данном случае «геист» является контейнером. Если класс должен знать текущую дату и время, вы не вводите a DateTime
, который является данными; вместо этого вы вводите абстракцию через системные часы (я обычно называю мои ISystemClock
, хотя я думаю, что есть более общая в проекте SystemWrappers ). Это не только правильно для DI; это абсолютно необходимо для тестируемости, так что вы можете тестировать изменяющиеся во времени функции без необходимости их фактического ожидания.
Объявление каждого жизненного цикла Синглтоном является для меня отличным примером программирования культа грузов и, в меньшей степени, разговорно названной « выгребной ямы объектов ». Я видел больше злоупотреблений синглтоном, чем хотел бы вспомнить, и очень мало из них связано с DI.
Другой распространенной ошибкой являются специфические для реализации типы интерфейсов (со странными именами, например IOracleRepository
), которые делаются только для того, чтобы иметь возможность зарегистрировать его в контейнере. Это само по себе является нарушением принципа инверсии зависимостей (просто потому, что это интерфейс, не означает, что он действительно абстрактный) и часто также включает в себя раздувание интерфейса, которое нарушает принцип сегрегации интерфейса .
Последняя ошибка, которую я обычно вижу, это «необязательная зависимость», которую они сделали в NerdDinner . Другими словами, есть конструктор , который принимает инъекции зависимостей, но и другой конструктор , который использует реализацию « по умолчанию». Это также нарушает DIP и имеет тенденцию приводить к LSP нарушений , а также, как разработчики, в течение долгого времени, начинают делать предположения вокруг реализации по умолчанию, и / или начать новые-Инг до экземпляров с помощью конструктора по умолчанию.
Как гласит старая поговорка, вы можете писать на Фортране на любом языке . Dependency Injection не серебряная пуля , которая будет препятствовать разработчикам завинчивания их управления зависимостями, но это действительно предотвратить ряд распространенных ошибок / анти-шаблоны:
...и так далее.
Очевидно, что вы не хотите разрабатывать структуру, зависящую от конкретной реализации контейнера IoC , такой как Unity или AutoFac. То есть, еще раз, нарушая DIP. Но если вы даже задумываетесь над тем, чтобы сделать что-то подобное, то вы, должно быть, уже допустили несколько ошибок проектирования, потому что Dependency Injection - это универсальный метод управления зависимостями, который не связан с концепцией контейнера IoC.
Все может построить дерево зависимостей; может быть, это контейнер IoC, может быть, это юнит-тест с кучей насмешек, может быть, это тестовый драйвер, предоставляющий фиктивные данные. Ваша инфраструктура не должна заботиться, и большинство платформ, которые я видел, не заботятся, но они все еще интенсивно используют внедрение зависимостей, так что она может быть легко интегрирована в выбранный контейнер IoC конечного пользователя.
Я не ракетостроение. Просто старайтесь избегать new
и static
кроме случаев , когда есть веские причины , чтобы использовать их, например, метод полезности , который не имеет внешних зависимостей, или служебный класс , который не мог бы иметь какой - либо цели вне рамок (Interop оберток и ключи словаря являются общими примерами это).
Многие проблемы со средами IoC возникают, когда разработчики впервые изучают, как их использовать, и вместо того, чтобы фактически изменить способ обработки зависимостей и абстракций в соответствии с моделью IoC, вместо этого попробуйте манипулировать контейнером IoC, чтобы удовлетворить ожидания своих старый стиль кодирования, который часто подразумевал бы высокую связь и низкую когезию. Плохой код - это плохой код, использует ли он методы DI или нет.