This is the 28th day of my participation in the August Text Challenge.More challenges in August
Code that follows these six principles is generally considered scalable and reusable:
The six principles of any object-oriented language should follow, to make your code easy to expand to take as far as possible to meet the six principles, not strictly in accordance with some design patterns, but if your code in accordance with the six principles, then your code is good, good code may not necessarily be in strict accordance with the design pattern to write code.
1. Single responsibility
Definition: Do not have more than one cause of a class change. In layman’s terms, a class has only one responsibility.
Scenario: Class T is responsible for two different responsibilities: responsibility P1 and responsibility P2. When class T needs to be modified due to a change in the requirements of responsibility P1, it is possible that the function of responsibility P2, which is normally functioning, will fail.
Modification: Follow the single responsibility principle. Establish two classes T1 and T2 respectively, so that T1 completes the function of responsibility P1 and T2 completes the function of responsibility P2. This way, when class T1 is modified, responsibility P2 is not at risk of failure; Similarly, when T2 is modified, there is no risk of failure in responsibility P1.
Advantages:
1) Can reduce the class complexity, a class is only responsible for one responsibility, simple logic;
2) Improve the readability of classes and the maintainability of the system;
3) Risk reduction caused by change, change is inevitable.
2. Richter’s substitution principle
Definition: All references to a base class must transparently use the objects of its subclasses, that is, subclasses can extend the functionality of the parent class without changing the functionality of the parent class
Scenario: There is A function P1, which is done by class A. Function P1 needs to be extended, and the expanded function is P, where P consists of the original function P1 and the new function P2. If new function P is completed by subclass B of class A, subclass B may fail original function P1 while completing new function P2. The CountPriceByJKL class inherits from the CountPrice class, and CountPriceByJKL overrides the Count() method, which may affect the functionality of the original Count method.
Modification: Follow the Richter substitution principle when using inheritance. When class B inherits from class A, do not overwrite the methods of the parent class A or override the methods of the parent class A, except adding new methods to complete the new function P2.
3. Dependency inversion principle
Definition: a high-level module should not depend on a low-level module; both should depend on its abstraction; Abstraction should not depend on details; Details should depend on abstractions.
To understand here is the most difficult, and usually used in the construction of the project framework when, for example, business logic layer relative to the data layer is a high-level modules, because the business logic layer needs to call the data layer to connect to the database, but to do high extensible reuse, try not to let the business logic layer depends on the data layer, can be in the data layer abstracts an interface, Make the business logic layer depend on this abstract interface.
Scenario: Class A (high level module) depends directly on class B (low level module). If you want to change class A to depend on class C (low level module), you must modify the code of class A to do so. In this scenario, class A is typically A high-level module responsible for complex business logic. Classes B and C are low-level modules responsible for basic atomic operations; If class A were modified, it would introduce unnecessary risk to the program.
The AutoSystem class directly depends on HondaCar and FordCar, which results in a high coupling. If the AutoSystem class wants to control HondaCar or FordCar, it must directly create corresponding objects.
Modification: Change class A to depend on interface I. Class B and C implement interface I. Class A indirectly connects to class B or C through interface I, which will greatly reduce the probability of modifying class A.
After this change, Honda and Ford implemented the ICar interface, providing Run, Stop, and Turn functions. AutoSystem relies on the ICar interface, which forces AutoSystem to rely on the abstract interface, which enables the AutoSystem class to cope with more changes in requirements.
Advantages:
1) As far as possible, low-level modules should have abstract classes or interfaces, or both.
2) Declaration types of variables should be abstract classes or interfaces.
3) Follow the Richter substitution principle when using inheritance.
4. Interface isolation principle
Definition: a client should not rely on interfaces it does not need; The dependency of one class on another should be based on the smallest interface.
Scenario: Class A depends on class B through interface I, and class C depends on class D through interface I. If interface I is not the minimum interface for classes A and B, then classes B and D must implement methods they do not need.
Modified: Split bloated interface I into several independent interfaces, and set up the dependency relationship between class A and class C respectively. That is, the interface isolation principle is adopted.
Note:
1), the interface as small as possible, but to have a limit. It is true that refinement of interfaces can increase programming flexibility, but if it is too small, it can result in too many interfaces and complicate the design. So do it in moderation.
2) Customize the service for classes that depend on the interface, exposing only the methods that the calling class needs and hiding those that it doesn’t. Only by focusing on providing custom services for a module can minimal dependencies be established.
3) Improve cohesion and reduce external interaction. Make the interface do the most with the fewest methods.
5. Demeter’s Rule (Least Know Rule)
Definition: An object should have minimal knowledge of other objects.
Scenario: The closer the relationship between classes, the greater the degree of coupling, and when one class changes, the greater the impact on the other class.
The simple definition is high cohesion, where a class minimizes its dependence on other objects, and the class’s methods and attributes are as private as possible.
Note:
1) Only correspond with direct friends, don’t talk to strangers.
2) Excessive use of this principle will lead to greater system complexity. Therefore, Demeter’s rule should be repeatedly weighed in order to achieve both clear structure and high cohesion and low coupling.
6. Open and close principle
Definition: software entities such as classes, modules, and functions should be open for extension and closed for modification.
Scenario: During the software life cycle, when the original software code needs to be modified due to changes, upgrades, and maintenance, errors may be introduced into the old code, or the entire function may have to be reconfigured, and the original code needs to be retested.
Suggestion: When software requirements change, try to achieve the change by extending the behavior of software entities rather than modifying existing code.