Software design – dependency inversion

Time:2022-1-24

catalogue

Blogger introduction

Software design - dependency inversion

Personal home page: Suzhou program white

Individual communities: procedural apes across the country

Author introduction: member of China DBA Alliance (acdu) and administrator of program ape (yuan) gathering places all over the country. Currently engaged in industrial automation software development. Good at c#, Java, machine vision, underlying algorithms and other languages. Qiyue software studio was established in 2019 and Suzhou Kaijie Intelligent Technology Co., Ltd. was registered in 2021

If the article is helpful to you, you are welcome to pay attention to, like, collect (three links with one button) and subscribe to some columns such as c#, Halcon, python + opencv, Vue, interviews with major companies, etc

ⅸ undertake software app, applet, website and other development, application development of key industries (SaaS, PAAS, CRM, HCM, bank core system, regulatory submission platform, system construction, artificial intelligence assistant), big data platform development, business intelligence, app development, ERP, cloud platform, intelligent terminal and product solutions. Testing software product testing, application software testing, testing platform and products, testing solutions. Operation and maintenance database maintenance (SQL server, Oracle, MySQL), operating system maintenance (windows, Linux, UNIX and other common systems), server hardware equipment maintenance, network equipment maintenance, operation and maintenance management platform, etc. Operation services, it consulting, it services, business process outsourcing (BPO), cloud / infrastructure management, online marketing, data collection and labeling, content management and marketing, design services, localization, intelligent customer service, big data analysis, etc.

If you have any questions, you are welcome to send a private letter and will reply in time

Micro signal: stbsl6, WeChat official account: Suzhou program whiten

preface

I saw a question yesterday“How to use dependency injection in JavaScript”, I’m just writing a series of software design essays recently. I’ll take this issue as an example and talk about the dependency inversion principle, an important principle in OOP theory.

We often hear the terms “dependency injection” and “inversion of control” in Java spring. What is their relationship with the “dependency inversion principle” and what do these terms mean?

What are dependency injection (DI) and inversion of control (IOC)?

Di and IOC are specific means to realize the principle of dependency inversion. Dependency inversion is the product of object-oriented programming (OOP). In one sentence, explain the principle of dependency inversion:

Abstraction should not depend on implementation, and implementation should not depend on implementation. Implementation should rely on abstraction.

What is “abstract” and “realization”?

Take a popular example:

Suppose you want to eat a bowl of beef noodles.

According to the thinking of process oriented programming, it is probably like this:

  • Input: flour, beef, chili sauce;

  • To make beef noodles, you should follow the recipe step by step;

  • Output: beef noodles.

If you don’t want to do it yourself, follow the thinking of object-oriented programming. It’s probably like this:

  • You are an object. Now you need a bowl of beef noodles;

  • “You” need a chef, because the chef has the method of “making beef noodles”, so you hire a chef;

  • You also called the purchase method of “supermarket object” to buy flour, beef and chili sauce;

  • Tell the chef the taste you want, give the ingredients you buy to the chef, and call the chef’s method of “making beef noodles” to complete the production.

So you didn’t find anything wrong?

  • I have to hire a cook to eat a bowl of beef noodles?

  • I hired a cook and bought my own ingredients?

The problem is that the “I” object depends on a chef object, which is called”Implementation depends on Implementation“。 Because of the dependence on the specific “implementation”, many details were exposed, so I tried to pass more details (buying ingredients) that I shouldn’t care about to the specific “implementation” (Chef).

The solution to eating beef noodles, instead of hiring a cook, go to a noodle shop, looking at the menu in the noodle shop: “a small spicy large beef noodles, thank you”.

here,”"Menu" is "abstract"”"Object"Is “realization”.

The “I” object only needs to rely on the abstract interface provided by the “menu” and call the “order” to eat beef noodles. It doesn’t care what the chefs behind it are, how they buy the ingredients and how they make them. This is called”Implementations should rely on abstraction“

If “I” thisObjectIf you rely onChef object, callednew Cook(), it is necessary to manage the whole process from initialization to dismissal.

In other words, when I call new, I have to take care of the complete life cycle of the object and how to create and destroy resources.

But in fact, according to the way of going out, the chef is the manager of the restaurant, which is very important:

  • The restaurant is the IOC container. There must be something to manage the concrete implementation of these abstractions. For example, the restaurant manages dozens of different chefs internally and provides 10 dishes externally.

  • The process that the restaurant injects the “I” object “into the” menu isDependency injection (DI)

  • I should rely on the abstract “menu” to place an order, rather than trying to pass the ingredients to the chef Zhang San and watch him do it. This is the principle of inversion.

Comparing the three methods of process oriented, primary object-oriented and object-oriented in accordance with the principle of dependency inversion, we find that things seem to be getting easier. I don’t need to buy my own ingredients to make noodles. I just go to the restaurant. This is the power of encapsulation and information hiding of object-oriented programming. The complexity of making beef noodles has not been reduced, but the coupling between the whole process and the “I” object has been untied.

Go back to the previous explanation of the dependency inversion principle:

Abstraction should not depend on implementation, and implementation should not depend on implementation. Implementation should rely on abstraction.

We’ll switch to the chef’s menu. Guest:

The menu should not rely on the chef, nor should the guest rely on the chef. The guest should rely on the menu

It’s much clearer next time.

I deliberately avoid the concept of class here to illustrate that OOP thinking does not necessarily need the concept of “class”. The focus is to decouple through information hiding so that complex software systems can be divided and ruled.

Di and IOC in Java spring

The spring framework providesXMLandJava ConfigThere are two ways to tellSpringthisIOC container, which abstract interfaces need to be managed. Nowadays, few people use XML, and annotations declare oneClassyes@Bean @Component @Service @Controller @RepositoryWhen you wait for this,SpringInitialize a singleton of this class to manage the whole declaration cycle, and provide some functions such as@PostConstruct @PreDestroyWait for the hook to customize the bean. Directly through the relying party@Resource ``@AutowiredWait for the annotation, or directly declare the constructor, and you can get oneBeanThe concrete implementation of.

Usually theseBeanIs asInterface type, which makes it easy to expand differentImplementation, use@QualifiedOr pressName injection dependency, you can choose different implementations.

SpringthisIOC containerAdministrationBeanRefer to the following figure for the life cycle process of:
Software design - dependency inversion

How to use IOC in JavaScript?

In fact, several mainstream componentsMVVM frameworkAngularVueReact, we have used dependency injection. The framework itself isIOC container

I don’t know the true face of Lushan Mountain. I only live in this mountain.

Take Vue as an example:

  • We use it in components”components“When a dependent component is declared, it is also a dependency injection. Some people may say that the injection is clearly a concrete component “implementation” rather than “abstraction”? Component B depends on component A, but it doesn’t go to new component A in component B at all, and it doesn’t care when a is created, destroyed or initialized, just to tellVuethisIOC containerComponent B depends on component A, and component A:init compile mount destroyThe management of these specific processes and implementations does not need B to care about, so this statement can be regarded as an “abstraction” that relies on a. The “abstraction” here is not necessarily similar"Interface" of JavaThis form.

  • Control inversion (IOC) container, which is a super housekeeper that uniformly manages the initialization of each implementation and the whole process from birth to death. Vue framework itself does this thing when you useVue.componentVue.useWhen registering a component in Vue, when and where the instance of this component is mounted can be regarded as controlled by the IOC container Vue.

  • As mentioned above, the parent and child components of Vue are directly declaredcomponentsIt’s a dependency injection, and there’s a more obvious oneinject provideInject dependencies directly into all descendant components. Again,inject/provideInjected into descendant components, and these descendants don’t care how the ancestor components are created and destroyed.

Angular from 1 X’s angularjs directly passes the strings of dependent components in the parameters. Later, the new angularjs framework has very obvious characteristics of IOC and di. And require JS tools do not solve the coupling problem between objects, so they are not completely dependent injection and control inversion.

Another example of a non front end is node JS server-side framework nest JS, which is very similar to the usage of Java spring and angular. You can read the official documents, as well as the explanations and specific use examples of IOC and Di, which are very detailed.

See this for detailsarticle

Therefore, if the project is relatively complex and you start to use these front-end and back-end frameworks, when few new non dto / VO / PO objects in the constructor code come out, you are already using dependency injection happily, and the IOC container is the boss who manages the life and death of these concrete implementation objects for you.

Problems and limitations of dependency injection

Must dependency injection be a “good model”?

Not exactly. Today, I went to a restaurant and asked for a non spicy beef noodle. As a result, I came up with a very spicy beef noodle. This is the price of “information hiding”. In Java,SpringBootIOC and di have been developed incisively and vividly. A @ enableautoconfiguration annotation does a lot of black box things behind it. Various agreed configurations directly tell spring container what to do without even writing a line of code. Extreme events will turn against each other, which makes the project prone to excessive redundant dependencies, a large number of beans in the spring container are difficult to control behind, too many implementation classes exist in an interface, uncertain interaction, dependency loading order, etc.

Although these problems may exist, I think it is still necessary to introduce IOC container and di into complex systems dominated by object-oriented programming. There are also ways to avoid or solve these problems. Let the object manage the life cycle of the dependent object by itself, which is as simple and rough as directly hiring a cook to make beef noodles, but it is easier to violate other OOP concepts such as Demeter’s law, and the scalability and maintainability of the project will be more restricted. The premise here is the suggestion under OOP. Of course, OOP also has some limitations. It is not necessary to use OOP as the programming paradigm.

In another scenario, if there are only some simple pages or services and there is no complex interaction between components / services, it is not necessary to use Di in order to use di.

ending

Dependency injection (DI) and inversion of control (IOC) are concrete means and the embodiment of the dependency inversion principle in OOP theory. Information hiding is used to reduce the coupling between objects, which is the problem solved by dependency inversion. The application of this idea is not limited to language and framework. For example, Java spring implements the IOC container with a series of design patterns and related technologies such as factory / template method / proxy / singleton pattern,, annotation, reflection and dynamic proxy. When this idea is applied in a language and framework similar to spring, there is no need to implement such a complex framework, as long as the decoupling effect of relying on inverted “implementation” and “implementation” can be achieved.

Click to get the data directly

Software design - dependency inversion

There are all kinds of learning materials, interesting programming projects and hard to find resources. ​ ​

❤️ Pay attention to the official account of Suzhou procedures ❤️

👇 👇👇