Dependency injection events (1)

Source: Internet
Author: User
Tags failover

. Net dependency injection (1)

Starting from a basic question, this article attempts to find the constant response to the changes in actual needs, to explain why we need to learn the dependency injection (dependency injection) to improve the design quality. Next, we will use a simple example to explain the difference between using di and changing it to Di, and discuss the time to use di. The purpose is to allow the author to have a general understanding of the related basic concepts, including the testability (maintainability) and coupling (loose coupling), control (inversion of control), dynamic Transaction processing, single-dollar transaction processing, and so on.


Why dependency injection?

Maybe you have read a similar question in a web forum: "How to Use strings to create objects ?」

To learn about the machine and solution of this issue, first let's take a look at what may happen to the normal programming method. Generally, the new operator is used to create objects. For example:

Zipcompressor OBJ = new zipcompressor ();

The above itinerary is used to create a zipcompressor object, or to create a zipcompressor instance ). As we can see from the absence of other names, zipcompressor does not provide the metadata function, and uses a zip algorithm. Assume that one day, the physical system has been deployed to the user end, later, because zipcompressor cannot be used for some reason (for example, it has fixed bugs or permission issues), it must be switched to another type, for example, rarcompressor or gzip. In this case, all zipcompressor programs must be modified and re-built and optimized, which leads to high cost of compaction.

In order to reduce the cost of future failover, we can design a program to align with "components that may need to be replaced in the future 」, keep the degree of parallelism in the program. Simply put, it is a design strategy that can adapt to future changes. Return to the example of the token, if changed to this:

VaR classname = configurationmanager. etettings ["compressorclassname"];
Type Atype = type. GetType (classname );
Icompressor OBJ = (icompressor) system. activator. createinstance (Atype );

That is to say, when creating an object, it first obtains the type of alias to be used from the application programming environment, and then passes through activator. the createinstance method is used to create an interface icompressor that can be implemented by different operators. Therefore, we can apply different names to the organization group:

<Deleetask>
<Add key = "compressorclassname" value = "mylib. zipcompressor, mylib"/>
<Deleetask>

In the future, if you need to compile the program into another aggregator, you do not have to modify or re-compile the Program program. Instead, you only need to modify the value of the program in the organizational unit, this allows you to switch between the categories used by the program when the program runs, and then change the program. Here we use the procedural skills for dynamic links.

In this example, the focus is not on the program skill of "creating objects by strings", but on the issue that when we compile a program, it may be because it is difficult to use the new operator without adding too many dependency keys in the program-that is 「Dependency(Dependency ). In the next step, each time we use new in a program to create a third-party (third party) component's personal experiences, our program was connected to another fixed category during the development period. This dependency may be in a single direction, or they may depend on each other to form a more secure 「Coupling"(Coupling) to increase the difficulty of programming later.

Scalability

For traditional systems ,「Scalability"(Maintainability) refers to the time needed to modify the program, we can say that it is highly reliable and highly reliable.

Those who have experienced experiences in development should agree that the changes in physical needs cannot be avoided. If your program will not be more dynamic after the first version is completed, you can naturally skip the issue after the test day. However, this situation is rare. In reality, even if the startup is just a small application program, it may also evolve into a large traditional system. In the beginning, it seems like a simple requirement, after the first version is completed, new requirements or changes will soon emerge, and the original design must be modified. Such modifications often do not just trigger a single function or similar orders, but also involve the cost of re-running a complete failover. This is strange. The overall cost of modifying a program is always beyond the peak period. This is also strange, developers are afraid that customers will change things to the west.

In addition, I think most people prefer new programming models and new processes, while few prefer to take over other programs, this is especially true for the modified program. However, once the program crashes, to some extent, it is already regarded as in the failover mode 1. In other words, most Program Programs are written in parallel. In this case, as developers, we have all provided programming programs that are easy to use, making ourselves and others better off. As stated by Damian Conway in Perl best practices:

「 When writing a program, imagine the person who finally wrote the program is a mentally ill patient with a violent attack and he knows where you live .」

Zookeeper Coupling

In. net (or some objects speak to the program 」, the features of the application are formed by the cooperation between various objects. For example, object a calls object B and object B calls Object C again. Coupling is used to call each other in a similar way ). The closer the relationship between objects is, the higher the coupling degree. The more complex the program is, the more likely the program will be. Because once there is any change, it is easy to trigger a response, it is not necessary to modify the multi-processing program, which leads to higher cost of concurrent users. To improve scalability, a common and effective strategy is to use 「Zookeeper CouplingLoose coupling (loose coupling), that is, to isolate various components of the application program, so that they do not have to listen too far to each other. Generally speaking, the larger your system is, the more you need to consider the design method of dynamic coupling.

When you write down the original coupling principle in the design process, you may not see the advantages of such a design method at the beginning, on the contrary, it is quite troublesome to find more program downloads. However, when you start to compile these existing programs, you will find that the speed of fixing the stinks is faster, in addition, these other methods are easier to implement than the previous encryption and password coupling methods. In addition, the changes to the program may cause an improvement in the image of "one-touch full body", reducing your fear of changing customer demand.

Basically, the coupling between "atomicity" and "dependency coupling" is the main reason why we learn "dependency injection. However, there are other advantages of this technology. For example, it can be used to facilitate the development of USD and parallel computing.

Scalability

I 've focused almost entirely on the value of dependency injection for unit testing and I 've even bitterly referred to using di as "mock driven design. "that's not the whole story though.2 -- Jeremy Miller
(For the value of dependency injection, I have stored all the values in the single-dollar billing method, some people have even complained that I used di in the form of "imitating robot motion design. But that is only part of the truth .)


When we say that a certain physical system is "writable" (testable), it means that 「Single-dollar renewalUnit Test (unit test), instead of the easy-to-use method that allows you to click something on a navigation window or a webpage. The billing method for a single dollar has the "renew once, do not renew again" Operation Point, and can use tools to automatically renew the operation. However, the cost required to write a single-unit program is not low, or even the application itself cannot be written. In some cases, the billing method is special, for example 「Zookeeper Development"(Test-driven devcelopment; TDD), it recommends that developers generate the zookeeper first, it also collects large amounts of RMB to cover the problems that can be addressed, so as to improve the quality of our products.

It is difficult to implement the "first-mover-hacker" statement. For example, some applications are deployed in a distributed multi-architecture, and some components or services need to run on the local server. At this time, if you need to first deploy these services on your terminal, deployment costs and time alone may leave the development staff out of the box. We can use 「Alimail substitutes(Test doubles) is used as a real component during the hour. In this way, you can begin to charge a single dollar for a different model. "Dependency injection" can also be used in the field to help us implement the camera system of our substitution.

Parallel Development

Divide and conquer is an effective method for the Fu Yun system. In practice, the software system is often divided into multiple parts and sent to multiple members to start component development at the same time, then, they are integrated with each other to form a complete system. To achieve this, the components of each part must have a clear interface in advance, just like the socket and plug-in head, the interface rules for mutual access are provided first. When the implementation of each part is completed, the interface can be smoothly connected. The basic principle of dependency injection is program-to-an interface. This feature also helps developers develop their work in parallel.

After learning about its dependency and purpose, we will then introduce what dependency injection is 」.

What is dependency injection?

If "easy to understand" is a major item in designing experiences, "elastic coupling" is the original principle for achieving this goal, so ,「Dependency Injection"(Dependency injection; Di) refers to the second battle. It contains a set of design modes and principles, it helps us design programs that are easier to compile.

Di often 「Control Anti-DDoS(Inversion of control; usually used IOC) is used in combination and discussion, but they are not completely equal. It is more accurate to say that IOC Han's comparative comparison is more accurate, including di, but not just di. In other words, Di is actually a form of IOC. So what exactly does IOC's anti-attack control mean? What kind of control is there? How to counter the issue? To answer this question, I would like to quote the famous traditional software technology to answer a wonderful answer on the website stack overflow, and then explain it in a conventional way.

The question in this post is: "How to explain di to children in wujia ?」 In many of my answers, John Munch, a friend of mine, gave the following answer:

When you go to the refrigerator to get things, it is very likely that you will fail. You may have forgotten about the refrigerator, or you may have taken things that dad doesn't want you to touch, or even no food in the refrigerator, or they have passed the retention period.
You should just say what you need. For example, "I want some food that can be used with lunch .」 Then, when you sit down and have a meal, we will try these things well.


A metaphor that is so refined and in place, naturally, has gained the popularity of netizens.

Next, according to the example, I plan to use a hello World and other types of Di to explain the example. The common Hello World Shopping examples only have a short schedule, but di cannot be as simple as that; even the simplest di shopping examples, it is also very difficult to use only two or three lines of program to reflect its spirit. As a result, there will be more program extensions and acronyms. Please be patient. We will first implement a non-di sort routine, and then change it to di version.

Import the deployment example-non-di version

In this example, the login function of the application must provide a two-factor authentication mechanism, the logon process includes the following steps:

  1. After the user logs in to the primary key, the system checks whether the primary key is correct.
  2. Without authentication, the system will immediately send a group of authentication certificates to the user's mailbox.
  3. After receiving the email, the user will receive a certificate and return to the logon page.
  4. The Verification Code does not allow users to log on to the system.



According to this description, we can design a type of service that provides the authentication factor: authenticationservice. Below is the compiled program example:

Class authenticationservice
{
Private emailservice msgservice;
Public authenticationservice ()
{
Msgsevice = new emailservice (); // create an object that is used to send a verification code
}

Public bool twofactorlogin (string userid, string PWD)
{
// Check your password. If it is correct, an object containing user information is returned.
User user = checkpassword (userid, PWD );
If (user! = NULL)
{
// Then, a certificate is issued to the user, and the certificate generated by the hypothetical machine is "123456 ".
This. msgservice. Send (user, "Your logon credential is 123456 ");
Return true;
}
Return false;
}
}

The authority of authenticationservice creates an emailservice object and sends it to the sender certificate. The twofactorlogin method checks the token secret entered by the user. If it is correct, call the send method of the emailservice object to send the token to the user's e-mail address. The sending method of the emailservice is to send the email in a single folder. The actual sending method is not important, so the program release is not listed; the checkpassword method and user-dependent program names are also omitted based on the same reason (the user object will contain the user's basic website information, for example, the email address, the mobile phone number, and so on ).

The main program uses the authenticationservice to process user logon programs. In this example, we use a simplified mainapp class. The Program program runs as follows. I don't want to explain it more.

Class mainapp
{
Public void login (string userid, string password)
{
VaR authservice = new authenticationservice ();
If (authservice. twofactorlogin (userid, password ))
{
If (authservice. verifytoken ("user-defined authentication "))
{
// Log on successfully.
}
}
// Logon error message.
}
}

This example currently involves four types: mainapp, authenticationservice, user, and emailservice. Their dependencies are shown in the following diagram. arrows in the diagram represent the dependency direction.



It can be easily seen from this example that the mainapp type of the main program does not need to use the authentication service provided by authenticationservice, the service is different depending on the user and emailservice. In terms of their role relationship, authenticationservice is a service role for mainapp, for user and emailservice, it is the role of "using client" (also called client.

The current design can basically meet the functional requirements. But there is a question: how can users receive the verification code by using a mobile phone license later? Later, you will see that this question highlights a flaw in the current design: it reversed 「Original principles of opening/sealing」.

Original principles of opening/sealing

"Open/close principle; OCP" refers to the units (types, models, and functions) of the program) it is necessary to activate and release the program so that the function can be fully functional. At the same time, you need to seal up the program to avoid modifying the existing program. In other words, the purpose of this principle is to add new functions without modifying the existing program quota. It should be noted that, following the principle of opening/sealing, new abstract libraries are usually introduced, making program programming difficult and increasing the program programming complexity. During the design period, this principle should be used in the areas where changes are most likely in the future, rather than making the entire system conform to this principle.

In general, it was first proposed by the public that the OCP was Bertrand Meyer, followed by Robert C. martin (also known as uncle [Uncle Bob]) re-designs an item, becoming one of the currently well-known design principles. In his agile software development: Principles, patterns, and practices documents, Dr. Chen introduced five original design principles, and give them a good example: S. o. l. i. D .. Their differences are:
  • SRP (single responsibility principle): a single component serves as the principle. A category should have only one role.
  • OCP (Open/closed principle): original principle of opening, releasing, and sealing. Fill in the opening and modifying mails.
  • LSP (liskov substitution principle): the original principle of rith's replacement. The object should be replaced by its Sub-objects without affecting the existing behavior of the program.
  • ISP (interface segregation principle): interface isolation principle. Multiple well-defined small interfaces are better than a large interface in the bag of mountains and sea.
  • Dip (dependency inversion principle): Dependent inverse principle. It depends on the abstract type rather than the concrete type.

If you encounter these principles in the subsequent chapter, we will further explain them. You can also refer to the original documents mentioned in the examination. The traditional Chinese edition is named agile development: Principles, formats and practices. Publishing House: qefeng. Author: Lin Kun and jing zi.


When this demand changes, a naive and fast solution is to add a category that provides the sending and sending services: Invalid messageservice, and then modify the authenticationservice, convert the program that originally used emailservice into a new type, like this:

Class authenticationservice
{
Private parameter messageservice msgservice;

Public authenticationservice ()
{
Msgsevice = new inclumessageservice (); // create an object that is used to send a verification code
}

Public bool twofactorlogin (string userid, string PWD)
{
// It is omitted because there is no change.
}
}

The twofactorlogin method is completely unchanged because the messageservice class does not have a send method, and this method is the same as the send method of emailservice: accept two incoming records. One is the user object and the other is the internal content. The following table lists two primitive types at the same time.

Class emailservice
{
Public void send (User user, string MSG)
{
// Send a email to the specified user (omitted)
}
}

Class program messageservice
{
Public void send (User user, string MSG)
{
// Send a response to the specified user (omitted)
}
}

As you can see, this solution changes the two places of the authenticationservice class:

  • The msgservice type of the Private member.
  • In the constructor, the original object is an emailservice object, which is now changed to invalid messageservice.


All you have to do is compile the entire application case, and then deploy the new version of the application. This solution was quickly changed, and program changes were rare. However, the solution did not solve the fundamental problem. As a result, the trouble was coming soon: users reported that they sometimes wanted to use e-mail to receive the login token and sometimes wanted to use their mobile phones to renew the token. This indicates that the application must provide an option on the logon page to allow the user to select the method in which the certificate is received. This also means that the internal program must be able to dynamically switch between the categories that provide the sending Certificate Service during the specified period 」. In order to switch between the primary and secondary stages, the results of dependency cannot be determined during the primary stage, however, you must manually use the dynamic route.

Next, we need to explain how to use di to make the delivery routines have the ability to switch between real-time and non-similar operations.

(Waiting for Renewal)

From: https://leanpub.com/dinet

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.