Design patterns: Dependency Injection and its variations

Today, we will be talk about two design patterns, both are similar to the last solid principle, dependency inversion, in the sense that both are about the same problem, namely creating an instance of an object within a class, but they differ from themselves, more precisely about these patterns later in the article.

 

Both patterns relate to the dependencies between classes, I will use the example of the store in which we will create classes instances of the store parts, that is, roof, floor, walls. Dependency Injection is a really important topic because it relates to the dependencies between classes, so they are related with the last SOLID Dependency Inversion principle.

 

The problem of dependencies between classes

Let’s use the example of the store, let’s build it, but now in a different way not using the builder:

And call it:

Apparently everything is okay, in fact, it results from this simple example of a few problems:

  1. The Shop class is responsible for creating the Floor, Wall and Roof classes instances, it is hard-coded dependencies, if we would to modify name the Floor class on Floors, we will also have to change the Shop class code and this is a breach of the open-closed principle.
  2. If we would to add some other parameter to the Wall class, eg wall height, we will not only have to modify the Wall class, but also the Shop class.
  3. If these three classes Floor, Wall and Roof will have any dependencies from other classes, then the Shop class will also need to know about them and to pass them.
  4. Testing of the application is difficult, while the functions of the Floor, Wall and Roof classes are run on their real instances during the tests, you would have to intercept those calls somewhere at a higher level because there is no easy way to substitute dependencies for testing time.

Such a simple Shop class and so many problems, everything breaks the open-closed principle, the patterns that will be discussed are responsible to keep this principle. First is the Inversion of control design pattern.

 

Inversion of control

Just to not confuse Dependency Injection with Inversion of Control. The principle of Inversion of Control tells how classes should depend from themselves, more precisely it consists in transferring the program execution control function to the framework used, hence its name Inversion of control will be explained more directly, and Dependency Injection is just one example of the implementation of the Inversion of Control principle.

Often humorously, the Inversion of Control principle is described in this way:

Don’t call us, we’ll call you.

Speaking more clearly in a classic application, the programmer code invokes functions from external libraries, whereas in the IoC approach this external framework calls the programmer’s code.

I will give the simplest example without IoC:

In this example, the flow of information is completely dependent from the programmer. And now an example using IoC:

We see the difference, now we do not have control over this program, it calls our code itself, of course we entered these functions there, but it does not depend on us when they will be used. These are trivial examples, but the point is to understand the ideas of IoC. In IoC, this framework calls our code, not us. Hence the name Inversion of control.

Also calling the building function of our store is an example of IoC, of course this is not IoC in one hundred percent, because further in the shop class modules are dependent on each other, but this program calls our class. It is not up to us when something will happen.

 

Dependency Injection

We will now implement IoC in our store example with Dependency Injection. Only that the control will be reversed in the area of relationship between objects.

Implementation of Dependency Injection is so common sometimes even used unconsciously so it is common to use these concepts of Dependency Injection and Inversion of Control interchangeably which is not correct.

There are several ways to implement the Dependency Injection pattern:

  1. Constructor Injection
  2. Setter Injection
  3. Interface Injection

 

Constructor Injection

This method involves manually creating an instance and passing it to the constructor. In this way:

 

Setter Injection

Assumptions similar to Constructor Injection, only done in a slightly different way, first we create a store instance, and only then we set dependencies on the created object:

 

Interface Injection

The principle of operation is the same as in the previous example only through interfaces, it is best to see the example:

We create the IDependency interface with the appropriate methods that have variables with the interface types of individual parts of the store, we implement its methods in the Shop class and finally set the dependencies in the Main function.

 

Service Locator

A similar pattern to Dependency Injection is Service Locator, it consists in downloading dependencies when they are needed. In javascript you have to download dependencies depending on their names, but in C # there are extended types mechanisms, we will create our own container and in it we will register the classes that are in the project.

First, let’s see what the Shop class looks like with the Service Locator pattern implemented:

In the RegisterTypeInterface method, we only inform what classes have interfaces and in the constructor, we already write a specific instance of classes to interfaces, we can say that:

is equal to:

However, what happens inside the Resolve and Register methods? From this we have our container:

At first glance, it may look horribly twisted and complicated, but calmly 🙂 It is not that at all 🙂

In the generic Register method we give first the interface type and then the class to which this interface belongs, then using typeof key words we write these types to the dictionary, it is thanks to this dictionary after entered only the interface in the Resolve method, the compiler knows which instances should be created . If you do not remember how a dictionary works, I’ve made two articles about it in the C# language section.

Of course, the container can be used in various types of dependency injection, mainly so that you do not have to letter all of the dependencies after comma if they were, for example, 15 in the constructor, or not would have to write multi-level dependencies. In the Service Locator pattern, the container methods are static, but normally these are normal methods. Registering dependencies in a regular container in a normal the Dependency Injection would look something like this:

Of course Dependency Injection and Service Locator are not mutually exclusive, you can combine them both, then we will have to modify the Shop class a bit:

And its calling:

And one very important remark at the end, with the Service Locator is like with Singleton, is considered as an anti-pattern by many people and in a sense they are right, abusing it kills the whole project, because in the Service locator it’s about that the container was available in the whole project so its class must be static, and static methods are much more difficult to test, and the design is less readable because the global access to the container gets messy, so you have to be careful with this pattern.

However, it is usually not a good idea to combine Dependency Injection with Service Locator, because it breaks the consistency of the project. In general, using the Service Locator pattern is not a good idea, although it is worth knowing, because just like singleton it is useful in some cases. So when you use Service Locator in a project in the right place, if your colleague looks at all your code, then his reaction does not have to be the same as the reaction this Mr below. 🙂

 

DI – problems

The Dependency Injection pattern, like other patterns, if it is abused, then the effects may be counterproductive, the code will become more difficult to manage and expand and read. As Uncle bob once wrote:

IoC is a good idea. And like all good ideas, it should be used with moderation.

 

Big constructors

What if we meet with such a constructor below or write it ourselves?

Dependencies is here too many, in that way the Dependency Injection is overused. Such constructors should be reduced.

What if we really need so many dependencies? Each of them can be divided into five other parts, in which case it is worth being interested in the design pattern of the facade, which will also be mentioned in later lessons.

 

 

Summary

Dependency Injection is a very useful pattern, if we do not abuse it, then it can undoubtedly facilitate the development of the application, code management and testing, thanks to DI it is also easier to write the code in accordance with the SOLID principles, especially with the two first.

In this article are the most important things about Dependency Injection, on 99% percent will be in the future a separate section about Dependency Injection where it will be explained in detail, including, useful containers in dependency Injection, testing dependency injection logic and containers with unit tests, about how you can combine dependency Injection with a CQRS pattern (which also will be a separate section 🙂) and other patterns, etc., etc. 🙂

It’s worth learning about the design patterns, because regardless of whether the language or framework changes, the way the code is written and its readability will always depend on the knowledge of the SOLID principles and design patterns.

Link to github with the whole code from this article: https://github.com/Slaw145/ServiceLocatorTutorial

This content also you can find on my steemit blog https://steemit.com/design-patterns/@slawas/design-patterns-dependency-injection-and-its-variations

And on medium: https://medium.com/@sawomirkowalski/design-patterns-dependency-injection-and-its-variations-16007d0fa367

As a standard, I remind you about the newsletter, which I send notifications about new entries and additional information about the IT world in general.🙂

And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 🙂

– site on fb: Devman.pl-Sławomir Kowalski

– group on fb: DevmanCommunity

Ask, comment underneath at the end of the post, share it, rate it, whatever you want🙂.

 
If that post was useful for you share it with your friends :)

Post a comment

Be first!

avatar
  Subscribe  
Notify about