DI анти-паттерны

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

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

Вот, что я думаю, произошло. Какому-то предприимчивому датскому туристу понравилась тальятелла алла болоньезе (tagliatelle alla bolognese) так сильно, что она решила попытаться приготовить ее, когда вернулась домой. (Я предполагаю, что это была женщина, потому что мужчины в то время много не готовили). Она сделала все, чтобы вспомнить, что входит в соус, но это было не так просто из-за долгой поездки на автобусе обратно в Данию.

Что касается ингредиентов, грудинка и красное вино были забыты, прежде чем она покинула Италию, мясной бульон и куриная печень были потеряны из памяти где-то в Австрии или Швейцарии, а овощи один за другим выпадали из головы во время долгого пути через (Западную) Германию. Когда она пересекла датскую границу, все, что осталось от оригинального рецепта, – это нарезанный лук и мясной фарш, и их подают только с одним типом пасты, которая легко доступна в Дании в то время - спагетти.

Мы ели блюдо, которое получилось в результате, в течение многих лет и любили его. В какой-то момент в 1980-х годах, в рецепт были добавлены томатная паста и орегано, чтобы сделать его более похожим на исходный. Это был рецепт, который я использовал более чем десять лет, пока кто-то не подсказал мне, что для улучшения вкусовых качеств можно добавить еще морковь, сельдерей, куриную печень, красное вино и так далее.

Смысл истории заключается в том, что я думал, что делаю рагу алла болоньезе (ragù alla bolognese), тогда как в действительности я не был даже близок к этому. Мне никогда не приходило в голову ставить под сомнение подлинность рецепта, потому что я вырос с ним. Хотя подлинность не является конечным критерием, блюдо, приготовленное по подлинному рецепту, намного вкуснее, и я не собираюсь возвращаться к моему старому рецепту.

В предыдущей главе я кратко сравнил паттерны проектирования с рецептами. Паттерн обеспечивает общий язык, который мы можем использовать, чтобы сжато обсудить сложное понятие, и рагу алла болоньезе – это такое понятие, потому что мы можем обсудить, как оно согласуется с тальятелле или лазаньей. С другой стороны, когда понятие (или, скорее, реализация) искривлено, мы получаем анти-паттерн.

Примечание

Анти-паттерн представляет собой описание часто встречающихся решений проблемы, которые несомненно приводят к негативным последствиям (William J. Brown et al., AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis (New York: Wiley Computer Publishing), 1998, 7).

Анти-паттерны часто бывают вызваны незнанием (как с моим соусом болоньезе), и их нужно избегать, а знание этих общих ловушек может помочь вам избежать их. Они являются более или менее формализованным способом описания распространенных ошибок, которые люди совершают снова и снова, независимо друг от друга.

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

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

Анти-паттерны могут быть исправлены путем рефакторинга кода к одному из DI паттернов, приведенных в главе 4. Сложность исправления в каждом отдельном случае зависит от деталей реализации, но для каждого анти-паттерна я предоставлю некоторые обобщенные рекомендации, как провести рефакторинг по направлению к паттерну.

Совет

В этой главе я не уделяю слишком много места рефакторингу от DI анти-паттерна к DI паттерну, потому что это не главная тема этой книги. Если вы заинтересованы в получении дополнительной информации о том, как вы можете переместить существующее приложение в направлении DI, есть целая книга, где обсуждается рефакторинг таких приложений: Working Effectively with Legacy Code (Michael Feathers, Working Effectively with Legacy Code (New York: Prentice Hall, 2004)). Хотя в ней не рассматривается исключительно DI, она охватывает многие из тех же понятий, что и я в данной книге.

Анти-паттерны, описанные в этой главе, приведены в таблице 5-1. Рисунок 5-1 иллюстрирует структуру главы.

Таблица 5-1: DI анти-паттерны
Анти-паттерн Описание
Control Freak Зависимости управляются напрямую, в отличие от инверсии управления (Inversion of Control, IoC).
Bastard Injection Foreign Default используются как значения по умолчанию для зависимостей.
Constrained Construction Предполагается, что конструкторы имеют особенную, индивидуальную сигнатуру.
Service Locator Неявный сервис может подавать зависимости потребителю, но нет гарантии, что он это сделает.
Рисунок 5-1: Структура этой главы принимает форму каталога анти-паттернов. Каждый анти-паттерн описан так, что вы можете прочитать о нем отдельно от других анти-паттернов.

Внимание

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

Так же, как внедрение в конструктор является наиболее важным DI паттерном, Control Freak является самым доминирующим анти-паттерном. Он всеми силами предотвращает вас от применения любого надлежащего и нужного внедрения зависимостей, так что вам придется сосредоточить свою энергию на этом анти-паттерне, прежде чем заняться другими. С другой стороны, наиболее опасным является Service Locator, потому что создается впечатление, что он на самом деле решает проблему.

Остальная часть этой главы описывает каждый анти-паттерн более подробно. Вы можете прочитать ее от начала до конца или только о том, в чем вы заинтересованы: каждый анти-паттерн занимает отдельный раздел. Тем не менее, если вы решили прочитать только об одном анти-паттерне, вы должны сосредоточить свое внимание на Control Freak.

Control Freak

Bastard Injection

Constrained Construction

Service Locator

Резюме

или RSS канал: Что новенького на smarly.net