
When opening a book on “new-fangled engineering design”, such as dependency inversion, you expect to see a description of another silver bullet. Say, here, before that, we all lived wrong, and now, armed with a
crowbar container and some mother, we can write new applications in 10 minutes.
Since I myself treat such modern tools with some caution, I was pleasantly surprised that Mark focuses on conventional design practices, the role of standard design patterns, and in general, considers the principles of dependency management in isolation from specific tools.
QUOTEIf you think that DI requires the use of a DI container, then this is another point that needs to be retrained. DI is a set of principles and patterns, and a DI container is a useful but optional tool.Looking at the typical use of dependency inversion in many projects, one gets the impression that DI contradicts the basic design principles that
Meyer and Butch write about so much.
')
For the sake of supposedly “loosely coupled design”, dozens of unnecessary interfaces are allocated, containers themselves are used to the right and left as Service Locators, classes with a dozen constructor parameters are created, the required class dependencies are passed through properties, etc. Looking at all this, it seems that DI containers contradict such things as class invariants and a
clear contract between the class and its customers.
QUOTE
DI is not an end in itself. Dependency management leads to loose coupling ( loose coupling ), which leads to more followed code.Mark begins by trying to dispel the main myths about DI, and only then begins to describe the main concepts. So, the author from the first pages says that the Service Locator is an anti-pattern and the container should be used only in one place, in the “application root” (in the so-called
Composition Root ), says that IOC! = DI, writes problems with using configuration files to manage container content and more.
QUOTEDo not expect that using DI containers will magically make your code loosely coupled. A DI container can make dependency management more efficient, but your application should primarily be designed with the DI technician and principles in mind .I was very pleased that the main goal of the book was not to consider specific libraries, but focused on general principles of dependency management and showed the connection of these principles with standard design patterns and OO principles (because most classical design patterns use dependency management in one form or another. : so, the decorator uses
Constructor Injection , and the strategy - Method Injection or Constructor Injection, etc.).
During the first three parts, no containers are used at all, and all examples use “self-made” dependency management (the so-called Poor Man's DI).
QUOTEA DI container is only a tool, and like any tool, it can be used correctly, and you can use it incorrectly.I was very pleased that in addition to the principles and patterns themselves, the author also describes when they are applicable and when not. Any pattern has its own scope, one of them is suitable in one case and not in the other. And some patterns in general seem very attractive, but in fact it turns out that their use can lead to serious problems. It is for this reason that the whole part of the book is devoted to basic DI-patterns and anti-patterns; and although this does not guarantee their correct use in our projects, it provides enough food for thought, and makes the chances of using this tool in the right way as large as possible.
QUOTEAn excessive number of constructor parameters ( Constructor Over - injection ) is not a problem of managing dependencies in general, and passing dependencies through a constructor ( Constructor Injection ), in particular. Rather, it is an indicator that the class in question has too many responsibilities. This code smell comes from the class, not from passing dependencies through the constructor; and we, as usual, should use it as an incentive to improve our code.If you look at different DI containers, you can notice that the same concepts are called differently in many places. Any container supports a certain set of life-time dependency management strategies, and although many of them are very similar, they are often called differently.
In this regard, the book solves two additional tasks. First, the author introduces consistent terminology (Auto Wiring, Composition Root, Bastard Injection etc), and second, it gives knowledge of basic principles that can be used with or without any container. This knowledge can be safely
reused , which will save time on learning new libraries, and also allow you to see the whole picture of dependency management.
QUOTEAdding stitches to an application requires extra effort, so adding them is only necessary.(Mark on the allocation of interfaces and the creation of additional
seams of the application)
This book has one drawback - this is the last fourth part, devoted to the description of six DI-containers. I got the impression that the author thought that a book of 350 pages does not look solid, or else the main KPI for him was exactly the number of pages.
In any case, the efficiency of the last 200 pages is extremely small. The first problem is that each container is a serious enough monster, and it can not be described on 50 pages. Secondly, the author made a reasonable attempt to unify the description of each container, which led to a large number of “copy-paste” (up to the same paragraphs), and the absence of a description of the unique capabilities of the containers.
As a result, 200 pages are almost wasted, since the current description is only enough to compare the most key points, but not enough even to select the container for your project, not to mention their full use.
Summing up , I want to say that
“Dependency Injection in .NET” is the most complete and consistent source of information on dependency management.
I would recommend the first 3 parts of this book for mandatory reading to all teams that use DI containers in their projects.Rating : 5+ (for parts 1-3) and 2 (for part 4).