Inversion of Control IOC and Dependency Injection DI - Theory

Learning is endless, keep improving

Ten years of Hedong, ten years of Hexi, don't bully the poor

Yesterday was the first day of returning to work from the May Day holiday. I was physically tired and had no enthusiasm for work. So I read the news, drank tea, and wasted a day

Just yesterday, my colleague Zhang Jing from Kangmei asked me to learn the theory and implementation of IOC. After all, I was a good colleague and friend before, so I took the time to Baidu a lot of information.

In the process of consulting online materials, I found that most of the technical pages are the code implementation of IOC, and there is no space for introducing the theory of IOC! This is obviously not what I want.

I know that in order to understand IOC, you must understand what is IOC (Inversion of Control)? Why is it called IOC (Inversion of Control)? Why can it be called DI (dependency injection) later? What are the benefits of using the IOC pattern? How does he work? How to decouple the system? What disadvantages does IOC bring? Why is performance degraded? And so many questions.

With the above questions, I still read a lot of information, and finally found that an article was written very, very well, so I forwarded it for everyone to learn and reference!

as follows:

Abstract: Inversion of Control IOC container and dependency injection DI have been widely used not only in Java and .Net, but also gradually extended to JavaScript frameworks such as AngulaJS and Angular 2.

1. The background of IoC theory
We all know that in a software system designed with object-oriented method, its underlying implementation is composed of N objects, and all objects cooperate with each other to finally realize the business logic of the system.

Figure 1: Coupled objects in a software system

If we open the back cover of a mechanical watch, we see a situation similar to the above, with the respective gears driving the hour, minute and second hands clockwise to generate the correct time on the dial. One such gear set is depicted in Figure 1, which has multiple independent gears that mesh with each other and work together to accomplish a task. We can see that in such a gear set, if there is a problem with one gear, it may affect the normal operation of the entire gear set.
The meshing relationship between gears in a gear set is very similar to the coupling relationship between objects in a software system. The coupling relationship between objects is unavoidable and necessary, which is the basis of collaborative work. Now, with the increasing scale of industrial applications, the dependencies between objects are becoming more and more complex, and multiple dependencies between objects often appear. Therefore, architects and designers need to analyze and analyze the system. design, will face greater challenges. A system with too high coupling between objects will inevitably lead to a situation that affects the whole body.

Figure 2: Complex dependencies between objects

Coupling relationships not only appear between objects, but also between modules of software systems, and between software systems and hardware systems. How to reduce the coupling between systems, modules and objects is one of the goals that software engineering always pursues. In order to solve the problem of excessive coupling between objects , software expert Michael Mattson proposed the IOC theory to realize the "decoupling" between objects. At present, this theory has been successfully applied in practice, and many J2EE projects Both use the IOC framework product Spring.

2. What is Inversion of Control (IoC)
IOC is the abbreviation of Inversion of Control. Most books are translated as "Inversion of Control", and some books are translated as "Inversion of Control" or "Inversion of Control".
In 1996, Michael Mattson first proposed the concept of IOC in an article about exploring object-oriented frameworks. We have talked a lot about the basic ideas of object-oriented design and programming before, so I won't repeat them. In short, it is to decompose a complex system into objects that cooperate with each other. After these object classes are encapsulated, the internal implementation is transparent to the outside. , which reduces the complexity of solving the problem, and can be flexibly reused and extended. The point of view put forward by the IOC theory is roughly as follows: the decoupling between objects with dependencies is realized by means of a "third party", as shown in the following figure:

Figure 3: IOC decoupling process

As you can see, due to the introduction of the "third party" in the middle position, that is, the IOC container, the four objects A, B, C, and D have no coupling relationship, and the transmission between the gears all rely on the "third party". , the control of all objects is handed over to the "third party" IOC container. Therefore, the IOC container has become the key core of the entire system. It acts like a "glue" to glue all objects in the system. To function together, without this "glue", objects will lose contact with each other, which is why some people compare the IOC container to the "glue".
Let's do another experiment: remove the IOC container in the middle of the picture above, and then take a look at the system:

Figure 4: The system with the IoC container removed

The picture we see now is all we need to do to implement the whole system. At this time, there is no coupling relationship between the four objects A, B, C, and D, and there is no connection with each other. In this case, when you implement A, you don't need to consider B, C, and D at all. Dependencies between objects have been reduced to a minimum. Therefore, if the IOC container can really be implemented, it will be a wonderful thing for system development. Every member participating in the development only needs to implement his own class, and it has nothing to do with others!
Let's take a look again. Why is Inversion of Control (IOC) so named? Let's compare:
before the software system introduces the IOC container, as shown in Figure 1, object A depends on object B, so when object A is initialized or runs to a certain point, it must actively create object B or use the existing Object B created. Whether object B is created or used, control is in its own hands.
After the introduction of the IOC container into the software system, this situation has completely changed. As shown in Figure 3, due to the addition of the IOC container, the direct connection between object A and object B is lost. Therefore, when object A runs to the point where object B is required At the time, the IOC container will actively create an object B and inject it into the place where the object A needs it.
Through the comparison before and after, it is not difficult to see that the process of object A obtaining dependent object B has changed from active behavior to passive behavior, and the control rights have been reversed. This is the origin of the name "inversion of control".

3. Aliases of IOC: Dependency Injection (DI)
In 2004, Martin Fowler discussed the same question, since IOC is inversion of control, then in the end it is "what aspects of control have been inverted?" After a detailed analysis and After the argument, he came to the answer: "The process of obtaining the dependent object is reversed". After control is reversed, the process of obtaining dependent objects is changed from self-management to active injection by the IOC container. So, he gave "Inversion of Control" a more appropriate name called "Dependency Injection (Dependency Injection)". His answer, in fact, gives the way to achieve IOC: injection. The so-called dependency injection is that the IOC container dynamically injects a certain dependency into the object during operation.

Therefore, Dependency Injection (DI) and Inversion of Control (IOC) describe the same thing from different perspectives, that is, by introducing an IOC container and using dependency injection to achieve decoupling between objects .
Let's take a real life example to help understand the process of dependency injection. Everyone should be familiar with USB interfaces and USB devices. USB provides us with great convenience in using computers. Now many external devices support USB interfaces.

Figure 5: USB interface and USB device

Now, we use the computer host and the USB interface to achieve a task: read a file from an external USB device.
When the host computer reads the file, it doesn't care at all what external device is connected to the USB interface, and it really doesn't need to know. Its task is to read the USB interface, as long as the connected external device conforms to the USB interface standard. Therefore, if I connect a U disk to the host computer, the host computer will read files from the U disk; if I connect an external hard disk to the host computer, the host computer will read files from the external hard disk. The power to connect external devices is up to me, that is, the control right belongs to me. As for what device is connected to the USB interface, the host computer cannot decide, it can only accept it passively. When the host computer needs an external device, I don't need it to tell me at all, and I will take the initiative to help it hook up the external device it wants. You can see how good my service is. This is a common example of dependency injection in our life. In this process, I played the role of the IOC container .
Through this example, the idea of ​​dependency injection is very clear: when the computer host reads the file, I hook the external device it depends on for him. The entire external device injection process is exactly the same as the process of a dependent object being injected into another object when the system is running.
We apply dependency injection to the software system, and then describe the process:
object A depends on object B. When object A needs to use object B, the IOC container will immediately create an object B and send it to object A. The IOC container is an object manufacturing factory. What you need, it will be sent to you, you can use it directly, and you no longer need to care about how the things you use are made or how they are destroyed in the end. , all of which are handled by the IOC container.
In traditional implementations, the relationship between components is controlled by code inside the program. We often use the new keyword to realize the combination of the relationship between two components, which will cause coupling between components. IOC solves this problem very well. It will realize the relationship between components from the inside of the program to the external container, that is to say, the container will dynamically inject some kind of dependency between components into the component during runtime.

4. What benefits do IOC bring us?

Let's start with the example of USB. What are the benefits of using a USB external device over an internal hard disk?
First, as an external device of the computer host, the USB device has nothing to do with the computer host before it is inserted into the host computer. Only after we connect it together, the two are connected and related. Therefore, no matter what happens to either side, it will not affect the operation of the other side. This feature is reflected in software engineering, that is, the maintainability is relatively good, it is very convenient for unit testing, and it is convenient for debugging programs and diagnosing faults. Each class in the code can be tested separately without affecting each other, as long as its own function is guaranteed to be correct, this is the benefit of low coupling or no coupling between components.
Second, the irrelevance between the USB device and the computer host brings another benefit. The manufacturer of the USB device and the manufacturer of the computer host can be completely unrelated to each other. The only thing that needs to be complied with is the USB interface standard. This feature is reflected in the software development process, and the benefits are too great. Each member of the development team only needs to care about implementing their own business logic, and does not need to care about the progress of other people's work, because your tasks have nothing to do with others, your tasks can be tested individually, and your tasks do not need to depend on Other people's components, no longer have to talk about the responsibility. Therefore, in a large and medium-sized project, team members have a clear division of labor and responsibilities. It is easy to divide a large task into small tasks, and the development efficiency and product quality will be greatly improved.
Third, the same USB external device can be plugged into any device that supports USB, can be plugged into a computer host, or can be plugged into a DV machine, and the USB external device can be used repeatedly. In software engineering, this feature is good reusability. We can isolate common common components and reuse them in other parts of the project or other projects. Of course, this is also the basic feature of object orientation. Obviously, IOC not only implements this principle better, but also improves the reusability of modules. Implementations that conform to the interface standard can be plugged into modules that support this standard.
Fourth, like the USB external device, the module has hot-swappable characteristics. The method of IOC generating objects is changed to an external method, that is, the object generation is defined in the configuration file. In this way, when we replace an implementation subclass, it will become very simple, just modify the configuration file. Hot swap feature.
Are the above benefits not enough to impress us and let us use the IOC framework in the project development process?

5. Technical Analysis of IOC Containers The
most basic technology in IOC is "Reflection" programming. Currently, languages ​​such as .Net C#, Java and PHP5 are supported. Among them, PHP5 technical books are sometimes translated as "Mapping". ". Everyone should be very clear about the concept and usage of reflection. Generally speaking, it is to dynamically generate objects according to the given class name (string method) . This way of programming allows the object to decide what kind of object it is when it is created. The application of reflection is very extensive. Many mature frameworks, such as Hibernate and Spring framework in Java, NHibernate and Spring.Net framework in .Net, all use "reflection" as the most basic technical means.
Reflection technology actually appeared very early, but it has been ignored and has not been further utilized. Reflective programming at the time was at least 10 times slower than normal object generation. The current reflection technology has been improved and optimized, and it has become very mature. The reflection method generates objects and the normal object generation method, the speed is not much different, about 1-2 times the gap.
We can regard the working mode of the IOC container as the sublimation of the factory mode. We can regard the IOC container as a factory. The objects to be produced in this factory are defined in the configuration file, and then use the reflection programming of the programming language. , generate the corresponding object according to the class name given in the configuration file. From the implementation point of view, IOC is to change the object generation code that was previously written in the factory method to be defined by the configuration file, that is, to separate the factory and object generation independently. The purpose is to improve flexibility and maintainability.
6. Some products of IOC container
The IOC containers under the Sun ONE technology system include: Spring, Guice, Pico Container, Avalon, HiveMind for lightweight; EJB for heavyweight; JBoss, Jdon, etc. As one of the three Musketeers of SSH (Struts, Spring, Hibernate) in Java development, Spring framework is used in large, medium and small projects. It is very mature and widely used. EJB is also used in key industrial projects, such as some telecommunications business.
The IOC containers under the .Net technology system include: Spring.Net, Castle, etc. Spring.Net is an IOC container transplanted from Java's Spring, and Castle's IOC container is the Windsor part. They are all lightweight frameworks and are relatively mature, among which Spring.Net has been gradually applied to various projects.
7. What should be paid attention to
when using the IOC framework The use of IOC framework products can bring great benefits to our development process, but we must also fully understand the shortcomings of introducing the IOC framework, be aware of it, and prevent abuse of the framework.
First, due to the introduction of a third-party IOC container in the software system, the steps of generating objects have become a bit complicated. It was originally a matter between the two, and an extra procedure was added out of thin air. Therefore, when we first started to use the IOC framework , the system will feel less intuitive. Therefore, the introduction of a new framework will increase the training cost for team members to learn and understand, and in the future operation and maintenance, new entrants must have the same knowledge system.
Second, because the IOC container generates objects through reflection, there is a certain loss in operating efficiency. If you're after operational efficiency, you have to balance this.
Third, specific to IOC framework products (such as Spring), a lot of preparation work is required, which is relatively cumbersome. For some small projects, it may objectively increase some work costs.
Fourth, the maturity of the IOC framework product itself needs to be assessed. If an immature IOC framework product is introduced, it will affect the entire project, so this is also a hidden risk.
We can generally draw the conclusion that some projects or products with a small workload are not suitable for using IOC framework products. In addition, if team members lack knowledge and ability, and lack in-depth understanding of IOC framework products, do not rashly introduce them. Finally, projects or products that emphasize operational efficiency are not very suitable for introducing IOC framework products, as is the case with WEB2.0 websites.

References:

http://jiwenke.iteye.com/blog/493965

Reprinted from: https://my.oschina.net/1pei/blog/492601

@chenwolong's blog

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325205393&siteId=291194637