Открывая книгу по «новомодной технике проектирования», такой как инверсия зависимостей ожидаешь увидеть описание очередной серебряной пули. Дескать, вот, до этого все мы жили неправильно, а теперь, вооружившись ломом контейнером и какой-то матерью мы сможем писать новые приложения за 10 минут.
Поскольку сам я к подобным новомодным инструментам отношусь с некоторой осторожностью, то я был приятно удивлен тем, что в книге Марк делает акцент на общепринятых практиках проектирования, роли стандартных паттернов проектирования, да и вообще, рассматривает принципы управления зависимостями в отрыве от конкретных инструментов.
ЦИТАТА
Если вы думаете, что DIтребует использование DI контейнера, то это еще один момент, который нужно переучивать. DI – это набор принципов и паттернов, и DI контейнер является хотя и полезным, но необязательным инструментом.
Глядя на типовое использование инверсии зависимостей во многих проектах складывается впечатления, что DI противоречит основным принципам проектирования, о которых так много пишут Мейер и Буч.
В угоду якобы «слабосвязанного дизайна» выделяются десятки ненужных интерфейсов, направо и налево используются сами контейнеры в роли Service Locator-ов, создаются классы с десятком параметров конструктора, обязательные зависимости классов передаются через свойства и т.д. Глядя на все это складывается впечатление, что DI-контейнеры противоречат таким вещам, как инварианты класса и четкий контракт между классом и его клиентами.
ЦИТАТА
DI – это не самоцель. Управление зависимостями ведет к слабой связанности (loosecoupling), что ведет к более сопровождаемому коду.
Марк начинает с того, что старается развеять основные мифы о DI, и лишь потом начинает описание основных концепций. Так, автор с первых страниц говорит о том, что Service Locator является анти-паттерном и контейнер должен использоваться лишь в одном месте, в «корне приложения» (в так называемом Composition Root), говорит о том, что IOC != DI, пишет о проблемах с использованием файлов конфигурации для управления содержимым контейнера и многом другом.
ЦИТАТА
Не ждите, что использование DI контейнеров волшебным образом сделает ваш код слабосвязанным. DI контейнер может сделать управление зависимостями более эффективным, но ваше приложение должно быть прежде всего спроектировано с учетом DI техник и принципов.
Очень порадовало то, что главной целью книги автор поставил не рассмотрение конкретных библиотек, а сделал акцент на общих принципах управления зависимостями и показал связь этих принципов со стандартными паттернами проектирования и ОО принципами (ведь большая часть классических паттернов проектирования используют управление зависимостями в том или ином виде: так, декоратор использует Constructor Injection, а стратегия – Method Injection или Constructor Injection и т.д.).
На протяжении первых трех частей вообще не используются никакие контейнеры и во всех примерах используются «самопальное» управление зависимостями (так называемый Poor Man’s DI).
ЦИТАТА
DI-контейнер – это лишь инструмент, и как любой инструмент, его можно использовать правильно, а можно и неправильно.
Очень порадовало, что помимо самих принципов и паттернов автор описывает и то, когда они применимы, а когда нет. У любого паттерна есть своя область применения, один из них подходит в одном случае и не подходит в другом. А некоторые паттерны вообще кажутся весьма привлекательными, а на деле оказывается, что их использование может привести к серьезным проблемам. Именно по этой причине целая часть книги посвящена основным DI-паттернам и анти-паттернам; и хотя это не гарантирует их правильного применения в наших проектах, это дает достаточно пищи для размышлений, и делает шансы на использование этого инструмента корректным образом максимально большими.
ЦИТАТА
Чрезмерное количество параметров конструктора (ConstructorOver-injection) не является проблемой управления зависимостей вообще, и передачи зависимостей через конструктор (ConstructorInjection), в частности. Скорее, это показатель того, что у рассматриваемого класса слишком много ответственностей. Этот душок (codesmell) идет от класса, а не от передачи зависимостей через конструктор; и мы, как обычно, должны использовать его, как стимул для улучшения нашего кода.
Если посмотреть на разные DI контейнеры, то можно обратить внимание, что одни и те же концепции во многих местах называются по разному. Любой контейнер поддерживает определенный набор стратегий управления временем жизни зависимости (lifetime management), и хотя многие из них аналогичны очень часто они называются по разному.
В этом плане, книга решает две дополнительные задачи. Во-первых, автор вводит согласованную терминологию (Auto Wiring, Composition Root, Bastard Injection etc), а во-вторых, дает знания основных принципов, которые можно использовать с любым контейнером или без него. Эти знания можно спокойно использовать повторно, что сэкономит время на изучение новых библиотек, а также позволит увидеть картину управления зависимостями целиком.
ЦИТАТА
Добавление Швов в приложение требует дополнительных усилий, поэтому добавлять их стоит только в случае необходимости.
(Марк о выделении интерфейсов и создании дополнительных швов приложения)
У этой книги есть один недостаток – это последняя четвертая часть, посвященная описанию шести DI-контейнеров. У меня сложилось впечатление, что автор посчитал, что книга из 350 страниц выглядит не солидно, либо же главным KPI для него было именно количество страниц.
В любом случае, КПД последних 200 страниц крайне мало. Первая проблема заключается в том, что каждый контейнер является достаточно серьезным монстром, и его невозможно описать на 50 страницах. Во-вторых, автор сделал разумную попытку унифицированного описания каждого контейнера, что привело к большому количеству «копи-пасты» (вплоть до одинаковых абзацев), и отсутствию описания уникальных возможностей контейнеров.
В результате, 200 страниц потрачены практически впустую, поскольку текущего описания хватает лишь для сравнения наиболее ключевых моментов, но их недостаточно даже для выбора контейнера для своего проекта, не говоря уже за их полноценное использование.
Подводя итог, хочу сказать, что “Dependency Injection in .NET” является наиболее полным и последовательным источником информации по управлению зависимостями. Я бы рекомендовал первые 3 части этой книги к обязательному прочтению всем командам, которые используют DI контейнеры в своих проектах.
Оценка: 5+ (для частей 1-3) и 2 (для части 4).
Автор: SergeyT