The seven principles of C # object-oriented design _c# tutorial

Source: Internet
Author: User
Tags extend inheritance

In this article we will talk about the seven principles, namely: single duty, Richter replacement, Dimitri Law, Reliance reversal, interface isolation, synthesis/aggregation principle, open-closed .

1. Opening and closing principles (open-closed principle, OCP)

definition: software entities should be open to extensions and closed for modification. This is a bit of a professional, more popular point, that is: The software system contains a variety of components, such as modules (Modules), classes (Classes) and functions (functions), etc., should not modify the existing code based on the expansion of new features. The opening principle of the original "open"refers to the extension of the function of the component is open, is allowed to extend the function of the closure principle, "closed" refers to the code changes are closed, that is, should not modify the original code.

The origin of the problem: Everything happens for a reason. Let's take a look at the reason for the opening and closing principle. During the lifecycle of the software, changes, upgrades, and maintenance, for reasons such as the need to modify the original code of the software, may introduce errors in the old code, or we will have to refactor the entire functionality, and the original code needs to be tested again. This has a special impact on our entire system, which also fully shows the coupling of the system if too high, will greatly increase the later expansion, maintenance. In order to solve this problem, people have summed up the principle of opening and closing. The fundamental solution to the opening and closing principle is to decouple. Therefore, our most fundamental task in object-oriented development is to solve the coupling.

Workaround: When the software needs to change, try to change it by extending the behavior of the software entity, rather than modifying the existing code to make changes.

Summary: the opening and closing principle has the idealistic color, said is very abstract, it is the object oriented design ultimate goal. Several other principles can be regarded as the realization of the principle of opening and closing. We're going to build the framework with abstractions, and extend the details with the implementation.

2. Principle of sole responsibility (single responsibility principle)

Definition: A class that has only one reason to cause it to change. That is, there should be only one duty.

Each duty is an axis of change, and if a class has more than one duty, these responsibilities are coupled together. This can lead to fragile designs. When a duty changes, it may affect other responsibilities. In addition, multiple responsibilities are coupled to affect reusability. For example: to implement the separation of logic and interface. One point to note is that the principle of single responsibility is not only specific to object-oriented programming ideas, but as long as it is modular programming, it needs to follow this important principle.

The origin of the problem: class T is responsible for two different responsibilities: responsibility P1, Responsibility P2. When you need to modify the class T as a result of a change in the responsibility P1 requirements, it is possible that the functions that are normally functioning P2 fail.

Solution: Establish two classes T1, T2, make T1 complete responsibility P1 function, T2 complete duty P2 function. In this way, when the class T1 is modified, the responsibility will not P2 the risk of failure, and similarly, when the T2 is modified, it will not cause the responsibility P1 failure risk.

3. Richter Replacement principle (Liskov substitution principle)

definition: subtypes must be able to replace their parent types. Notice the ability to have two words here. Some people also jokingly call the mouse's son a hole in the principle.

The origin of the problem: There is a functional P1, completed by Class A. Now need to expand the function P1, the function of the expansion of P, where p by the original function P1 and the new function P2 composition. The new function p is completed by subclass B of Class A, then the subclass B may cause the original function P1 to fail while completing the new function P2.

Workaround: When Class B inherits Class A, in addition to adding new methods to complete the newly added functionality P2, try not to rewrite the method of parent class A and try not to overload the method of parent Class A

Summary: all references to the parent class must be able to transparently use objects of its subclasses. Subclasses can extend the functionality of the parent class, but you cannot change the original function of the parent class, that is, subclasses can implement abstract methods of the parent class, and subclasses can also add their own methods, but they cannot override non-abstract methods of the parent class. When a method of a subclass overloads a method of a parent class, the method's predecessor condition (that is, the method's formal parameter) is more relaxed than the input parameter of the parent class method. When a subclass's method implements an abstract method of the parent class, the method's post condition (the return value of the method) is stricter than the parent class.

4. Dimitri (Law of Demeter)

definition: the Dimitri rule is called the least known principle, namely: an object should keep the least understanding of other objects. If two classes do not have to communicate directly with each other, then these two classes should not have direct interaction. If one of the classes needs to invoke a method of another class, the call can be forwarded by a third party. Simply defined as communicating only with a direct friend. First, explain what a direct friend is: Each object has a coupling relationship with other objects, so long as the two objects are coupled, we say the two objects are friends. There are many ways of coupling, dependence, association, combination, aggregation and so on. Among them, we call the class in the member variable, method parameter, method return value as the direct friend, and the class appearing in the local variable is not a direct friend. In other words, unfamiliar classes are best not to appear as local variables inside the class.

The problem: The closer the relationship between classes and classes, the greater the degree of coupling, the greater the impact on another class when a class changes.

It was first introduced in 1987 by Ian Holland of the United States Northeastern University. In layman's terms, it is a class that knows less about the classes it relies on. In other words, for the dependent classes, no matter how complex the logic is, try to encapsulate the logic within the class as much as possible and not disclose any information outside the public method provided. The Dimitri Law also has a simpler definition: only communicate with direct friends.

Workaround: reduce the coupling between classes and classes as much as possible. Since we began to contact programming, we know the general principles of software programming: low coupling, high cohesion. Whether the process-oriented programming or object-oriented programming, only to make the coupling between each module as low as possible to improve the code reuse rate.

The Dimitri principle is designed to reduce coupling between classes, and because each class reduces unnecessary dependencies, it does reduce the coupling. But everything has the degree, although may avoid with the indirect class correspondence, but must communicate, must pass through an "intermediary" to be contacted. Therefore, the excessive use of Dimitri principle, will produce a large number of such intermediary and transfer class, resulting in a greater complexity of the system. Therefore, the use of Dimitri rules to be weighed repeatedly, not only to achieve a clear structure, but also high cohesion low coupling.

5. Dependency inversion principle (dependence inversion principle)

definition: high-level modules should not rely on low-level modules, both should rely on their abstraction; abstraction should not depend on detail; detail should depend on abstraction. The central idea is interface-oriented programming

The problem: Class A is directly dependent on class B, and if you want to change class A to dependent Class C, you must do so by modifying the code for Class A. In this scenario, Class A is typically a high-level module, responsible for complex business logic, Class B and Class C are low-level modules responsible for basic atomic operations, and if Class A is modified, it poses an unnecessary risk to the program.

Workaround: Modify Class A to rely on interface I, Class B and Class C each implement interface I, Class A through interface I indirectly with Class B or Class C, will greatly reduce the chance to modify Class A.

In practical programming, we generally need to do the following 3 points:

1. Lower-level modules should have abstract classes or interfaces as much as possible, or both.

2. The declaring type of a variable is as much an abstract class or interface as possible.

3. Follow the Richter substitution principle when using inheritance.

The use of the principle of dependency inversion has brought great convenience to the cooperation of many people, the more people involved in collaborative development, the larger the project, the greater the significance of the principle of using reliance.

Summary: the principle of dependency inversion is to make us interface-oriented programming, understand interface programming, and understand dependency inversion.

6. Interface Isolation principle (Interface segregation principle)

definition: A client should not rely on interfaces that it does not need; A class's dependency on another class should be based on the smallest interface.

The problem: Class A through the interface I dependent class B, Class C through the interface I dependent Class D, if the interface I for Class A and Class B is not the smallest interface, then Class B and Class D must go to implement the methods they do not need

Workaround:1, use the delegate to separate the interface. 2, the use of multiple inheritance separation interface. 3. Split the bloated interface I into several separate interfaces, and Class A and Class C are dependent on the interfaces they need. That is to adopt the principle of interface isolation.

An example is provided:

Now let's take a look at the picture, and everything will be clear at a glance.

The meaning of this diagram is: Class A relies on interface I, Method 1, Method 2, Method 3, and Class B is the implementation of Class A dependency. Method 1, Method 4, method 5 in Class C dependency interface I, and Class D are implementations of Class C dependencies. For Class B and Class D, although they all have methods that are not in use (that is, the red font tag in the diagram), they have to implement the interface I so that they do not have to be implemented

After modification:

If the interface is too bloated, as long as the methods present in the interface are useless to the classes that depend on it, it is clearly not a good design to implement these methods in the implementation class. If you modify this design to conform to the interface isolation principle, you must split the interface I. Here we split the original interface I into three interfaces

Summary: We in the code writing process, the use of interface isolation principle, must be moderate, interface design too large or too small are not good. Refinement of the interface can improve the flexibility of programming is not a fact of earning, but if too small, it will cause too many interfaces, so that the design is complicated. So be sure to be modest. When designing an interface, you can accurately practice this principle only if you spend more time thinking and planning.

7. Synthesis/polymerization principle (composite/aggregate reuse Principle,carp)

definition: There are also people called the composite reuse principle, and try to use compositing/aggregation to try not to use class inheritance. In other words, where synthesis/aggregation can be used, no inheritance is used.

Why try to use compositing/aggregation instead of class inheritance?

1. Object inheritance is defined at compile time, so it is not possible to change the implementation of subclasses inherited from the parent class at run time

2. The implementation of the subclass has a very close dependency on its parent class, so that any changes in the parent implementation will inevitably result in a subclass change

3. When you reuse subclasses, if the inherited implementation is not appropriate to solve the new problem, the parent class must be overridden or replaced by a more appropriate class, which limits flexibility and ultimately limits reusability.

Summary: these principles are embodied in the design pattern of the dripping, the design pattern is to achieve these principles, so as to achieve code reuse, enhance the system scalability. So the design pattern is regarded as a classic by many people. We can take a good look at design patterns, to slowly experience these design principles.

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.