Agile Software Development-11 principles of Object-Oriented Design
"You do not have to strictly abide by these principles, and violation of them will not be punished by religion.
However, you should regard these principles as warning bells. If you violate one of them, the warning bells will ring ."
1. Single SRP responsibility principle [applicable to Class Functions]
(For a class, there should be only one reason for its change .)
Detailed description:
If a class has too many responsibilities, these responsibilities are coupled.
A change in responsibility may weaken or restrain this class from fulfilling other responsibilities.
This coupling will lead to a fragile design. When changes occur, the design will suffer unexpected damages.
Conclusion:
It is the simplest and most difficult to use in all class design principles.
We naturally combine our responsibilities. What we really need to do in software design is to discover responsibilities and separate them.
2. OCP open-closed principle [applicable to Class abstraction]
(Software entities (classes, modules, functions...) should be extensible, but cannot be modified .)
Detailed description:
OCP = is open to extensions and closed to modifications.
If a change in the program produces a chain reaction, resulting in a series of related module changes, the design will smell bad.
We recommend that you add new code without modifying the code that is running normally if you want to refactor the system.
Conclusion:
In many aspects, OCP is the core of object-oriented design.
It can bring great benefits (flexibility, reusability and maintainability of the program ).
It is not a good idea to use OCP in code.
The correct method is: developers only abstract the frequently changed parts of the program! Rejecting immature abstraction is just as important as abstraction!
3. LSP liskov replacement principle [applicable to Class layers]
(Child types must be able to replace their base types .)
Detailed description:
Barbara liskov said in 1988:
Liskov replacement property: if there is a T-type object O2 for the object O1 of each type S,
In all program P compiled for type T, after O2 is replaced with O1, the behavior function of program P remains unchanged, and type S is the sub-object of type T.
Conclusion:
LSP is one of the main principles that can be implemented by using the OCP open-closed principle,
Only child-type replicas can be extended without modifying the module of the base class type (base class reference or pointer.
This alternative is something that developers can implicitly depend on.
Therefore, if there is no explicit contract to force the base class type, the Code must be good and clearly express this point.
The term "IS-A" cannot be defined as a child type,
The correct definition of child types is "Replaceable", and "Replaceable" can be achieved through explicit or implicit (dynamic binding must use the base class type) contracts.
4. Dip Dependency inversion principle [applicable to Class levels]
(Abstraction should not depend on details. Details should depend on abstraction .)
Detailed description:
A. High-level modules should not depend on low-level modules. Both of them should depend on abstraction (using interfaces or virtual classes to connect ).
B. abstraction should not depend on details, but on abstraction.
Conclusion:
The dependency structures and policies created using the traditional procedural programming method depend on the details.
Dip makes the details and policies depend on abstraction, and often customizes service interfaces for customers.
In fact, the inversion of this dependency is a good marker of object-oriented programming.
Correct dip application is required for reusable frameworks, and it is also important to build flexible code in the face of changes.
Abstract and details are isolated by DIP, so the code is very easy to maintain.
5. ISP interface isolation principle [applicable to Class interfaces]
Customer programs should not be forced to rely on methods they do not need.
An interface belongs to a customer and does not belong to its class hierarchy.
Detailed description:
The separated customer is the separated interface. The separated interface has two methods: Delegate and multi-inheritance.
The interface isolation principle is used to deal with the disadvantages of the fat interface.
If the class interface is not cohesive, it indicates that the class interface is fat and requires weight loss.
The principle of losing weight is that the interface is divided into multiple groups of methods, each of which serves a different set of customer programs!
The client program is faced with multiple abstract base classes with cohesion interfaces.
Conclusion:
Fat classes may lead to abnormal and harmful Coupling Relationships between their customer programs.
When the customer program requires a change to the fat class, it will affect all other household programs.
Therefore, the program should only rely on the methods actually called.
This goal can be achieved by decomposing the fat class interface into multiple specific customer program interfaces.
Each client-specific interface only declares the functions it calls.
Removed the dependency between client programs of the class so that they do not depend on each other.
6. Rep reuse release equivalence principle [applicable to packages]
(The granularity of reuse is the granularity of Release)
Detailed description:
What do you expect when you reuse another class library?
Of course it is a good document, code that can work, and clear interface specifications!
You want the author to maintain the class library code all the time. When the author changes the class library interfaces and functions, you want to be notified.
Code authors organize their software into a package (DLL, jar,...), so the granularity of reuse is the package release granularity.
Conclusion:
The reuse granularity of a package is as large as that of the release. Because the reusability is based on the package, reusable packages must contain reusable classes.
7. Common CCP blocking principle [applicable to packages]
(All classes in the package should be closed for changes to the same class nature.
If a change affects a package, it will affect all classes in the package, but it will not affect other packages .)
Detailed description:
This is the re-provision of the SRP single responsibility principle for the package. This specifies the reason why a package should not contain multiple referenced packages.
In most applications, maintainability exceeds reusability.
Code Change: if the code is to be changed, the original changes are concentrated in one package, rather than distributed in multiple packages.
Code release: We only release the changed package!
Conclusion:
The CCP encourages us to aggregate all classes that can be modified for the same reason in the same package.
8. Common CRP Reuse Principle [applicable to packages]
(All classes in a package should be reused together.
If a class in the package is reused, all classes in the package must be reused .)
Detailed description:
All classes in a package should be reused together.
Conclusion:
If a class in the package is reused, all classes in the package must be reused.
This principle helps us decide which classes should be put into the same package.
9. ADP dependency principle [applicable to packages]
(Loops are not allowed in the dependency graph of the package .)
Detailed description:
If many developers change the same source code file set in the development environment,
Because someone is later than you, and has changed some of the things you depend on (classes or methods), the next day to go to work,
The feature you completed yesterday is not working properly today, so there will be "post-morning syndrome "!
There are two solutions to this problem: "weekly build" and "eliminate dependency ring"
Weekly build: It is applied to medium-sized projects. It works in the following way: 1-4 per week. Developers work in private code spaces and can perform joint debugging on 5-6 every week!
Eliminate dependency loops: You can resolve dependency loops by dividing the development environment into release packages.
Conclusion:
There are two main methods to solve the dependency loop between packages:
1. Use the Dependency inversion principle to add a dependency interface or abstract class before the class and dependency class to remove the dependency ring.
2. Add a new class, move the dependency between the class and the dependent class to a new class, and remove the dependency ring.
10. SDP stable dependency principle [applicable to packages]
(Dependency in a stable direction .)
Detailed description:
The design is not completely fixed. To make the design maintainable, it is necessary to make a program variable.
With this principle, we can create packages that are sensitive to certain change types.
Other packages do not depend on the package to be changed.
The software package can be divided into a stable package and a variable package!
How to identify stable and variable packages? If many other packages depend on this package, it is a stable package, otherwise it is a variable package!
When the package is placed in different locations, its stability is different.
How to calculate the instability of a package? (Input coupling ca, output coupling CE)
Unstable value = Ce/(Ca + Ce). The lower the value, the more stable it is!
Conclusion:
The method to reduce the variable package's unstable value is: add an abstract coat (interface/abstract class) to it, and call the abstract coat for other packages!
The variable package is the implementation of the abstract coat!
11. SAP stable abstraction principle [applicable to packages]
(The abstract program of the package should be consistent with other stable programs .)
Detailed description:
This principle links the stability and abstraction of the package.
A stable package should be abstract, so that its stability will not make it unable to expand;
An unstable package should be specific, so its instability makes the code easy to modify.
Conclusion:
It points out that a package is sometimes abstract and unstable.