Home  >  Article  >  Backend Development  >  Introduction to object-oriented principles in php

Introduction to object-oriented principles in php

黄舟
黄舟Original
2017-10-12 09:42:131247browse

It is very difficult to make software very flexible and easy to maintain. Flexible software has a complex structure and is difficult to maintain. There are gains and losses, and the key lies in how to deal with the two so that the losses outweigh the losses. The design and development of software should follow the following six principles:
1. OCP
Full name: "Open-Closed Principle" Open-Closed Principle

Description: Open for extension, closed for modification .
Advantages: The system designed according to OCP principles reduces the coupling between various parts of the program, and its adaptability, flexibility, and stability are relatively good. When new functions need to be added to an existing software system, there is no need to modify the abstraction layer that is the basis of the system. Only new modules need to be added to the original basis to realize the functions that need to be added. The added new modules have no or very little impact on the original modules, so there is no need to retest the original modules.
How to implement the "open-closed" principle
In object-oriented design, what is not allowed to change is the abstraction layer of the system, but what is allowed to be extended is the implementation layer of the system. In other words, define a once-and-for-all abstraction design layer that allows as much behavior as possible to be implemented at the implementation layer.
The key to solving problems lies in abstraction, which is the first core essence of object-oriented design.
Abstracting something is essentially summarizing its essence. Abstraction allows us to grasp the most important things and think from a higher level. This reduces the complexity of thinking and we don’t have to think about so many things at the same time. In other words, we encapsulate the essence of things and cannot see any details.
In object-oriented programming, through abstract classes and interfaces, the characteristics of concrete classes are stipulated as the abstract layer, which is relatively stable and does not need to be changed, thus satisfying "closed to modification"; while the concrete classes derived from abstract classes can be changed The behavior of the system so that it satisfies "openness for extension".
When extending the entity, there is no need to change the source code or binary code of the software. The key is abstraction.

2. LSP
Full name: "Liskov Substitution Principle" Liskov Substitution Principle

Explanation: Subtype must Ability to replace their base types. If a software entity uses a base class, then when the base class is replaced by a subclass that inherits the base class, the behavior of the program will not change. Software entities are unaware of the difference between base class objects and subclass objects.
Advantages: It is easy to realize the interchange of subclasses under the same parent class without the client being aware of it.

3. DIP
Full name: "Dependence Inversion Principle" Dependency Inversion Principle

Description: Depend on abstraction, not concreteness. Clients rely on abstract coupling.
Abstraction should not depend on details; details should depend on abstraction;
Programming should be for interfaces, not for implementation.
Advantages: Using the dependencies created by traditional procedural programming, the strategy depends on the details, which is bad because the strategy is affected by changes in the details. The dependency inversion principle makes details and strategies dependent on abstraction, and the stability of the abstraction determines the stability of the system.
How to achieve dependency inversion?
Coupling in an abstract manner is the key to the dependency inversion principle. Abstract coupling relationships always involve concrete classes inheriting from abstract classes, and it is necessary to ensure that any reference to the base class can be changed to its subclass. Therefore, the Liskov substitution principle is the basis of the dependency inversion principle.
Although coupling at the abstract level is flexible, it also brings additional complexity. If the possibility of a specific class changing is very small, then the benefits of abstract coupling will be very limited. In this case, you can It would be better to use concrete coupling.
Hierarchy: All well-structured object-oriented architectures have clear layer definitions, and each layer provides a set of cohesive services to the outside through a well-defined, controlled interface.
Depend on abstraction: It is recommended not to rely on concrete classes, that is, all dependencies in the program should terminate at abstract classes or interfaces. Try to do the following:
1. No variable should hold a pointer or reference to a specific class.
2. No class should be derived from a specific class.
3. No method should override the implemented method in any of its base classes.

4. ISP
Full name: "Interface Segregation Principle" Interface Segregation Principle

Explanation: It is always better to use multiple dedicated function interfaces than to use one total interface. From the perspective of a client class: the dependence of one class on another class should be based on the minimum interface. An overly bloated interface is a pollution of the interface and should not force clients to rely on methods they do not use.
Advantages: When a software system function is expanded, the pressure of modification will not be transmitted to other objects.
How to implement the interface isolation principle
Users should not be forced to rely on methods they don't use.
1. Use delegation to separate interfaces.
2. Use multiple inheritance to separate interfaces.

5. CARP or CRP
Full name: “Composit
e/Aggregate Reuse Principle” Synthesis/Aggregation Reuse Principle or “ Composite Reuse Principle"
Composite Reuse Principle
Explanation: If some functions of the new object have been implemented in other already created objects, try to use other objects Provide functionality so that it becomes part of the new object rather than recreating it yourself. New objects achieve reuse of existing functionality by delegating to these objects.
In short, try to use composition/aggregation and try not to use inheritance.
Advantages:
1) The only way for a new object to access component objects is through the interface of the component object.
2) This kind of reuse is black box reuse, because the internal details of the component objects are invisible to the new object.
3) This kind of reuse supports packaging.
4) This kind of reuse requires fewer dependencies.
5) Each new class can focus on a task.
6) This kind of reuse can be performed dynamically during runtime, and new objects can dynamically reference objects of the same type as the component objects.
7) As a means of reuse, it can be applied to almost any environment.
Disadvantages:
There will be more objects in the system that need to be managed.

6. LOD or LKP
Full name: “Law of Demeter” Demeter Principle or “Least Knowledge Principle” Least Knowledge Principle

Explanation : Objects should be related in as few ways as possible to avoid inextricable relationships.
How to implement Dimit's Law
The main purpose of Dimit's Law is to control the overload of information. When applying it to system design, you should pay attention to the following points:
1) In terms of class division, Classes should be created with weak coupling. The weaker the coupling between classes, the easier it is to reuse them.
2) In terms of class structure design, each class should minimize the access rights of members. A class should not make its properties public, but should provide methods for obtaining and assigning values ​​to allow the outside world to access its properties indirectly.
3) In class design, whenever possible, a class should be designed to be an immutable class.
4) In terms of references to other objects, the references of a class to other objects should be minimized.


There is also a single responsibility principle:

Introduction to SRP (SRP--Single-Responsibility Principle): As far as a class is concerned, it should only focus on Do one thing and have only one reason for its change
. The so-called responsibilities can be understood as functions, which means that the designed function should have only one function, not two or more. It can also be understood as the reason for the reference change. When you find that there are two changes that will require us to modify this class, then you should consider withdrawing this class. Because responsibility is an axis of change, when requirements change, the change will reflect changes in the class's responsibilities. Points to note when using SRP: 1. A reasonable class should have only one reason for its change, that is, a single responsibility;
2. It is unwise to apply SRP or other principles without signs of change;
3. When the requirements actually change, principles such as SRP should be applied to refactor the code;
4. Using test-driven development will force us to separate unreasonable code before the design smells;
5. If the test If you cannot force separation of responsibilities, the smell of rigidity and fragility will become very strong, then you should use Facade or Proxy mode to refactor the code; SRP advantages: eliminate coupling and reduce code rigidity caused by changes in requirements.


You do not have to strictly adhere to these principles, and there are no religious penalties for violating them. But you should think of these principles as alarm bells. If one of them is violated, the alarm bell will sound.
-----Arthur J.Riel
(1) All data should be hidden inside the class where it is located.
(2) Users of a class must rely on the public interface of the class, but a class cannot rely on its users. p15
(3) Minimize the messages in the class protocol.
(4) Implement the most basic public interface that all classes understand [for example, copy operations (deep copy and shallow copy), equality judgment, correct output content, parsing from ASCII description, etc.]. p16
(5) Do not put implementation details (such as private functions that place shared code) into the public interface of the class.
If two methods of a class have a common code, then you can create a private function that prevents these common codes.
(6) Do not disturb the public interface of the class with things that users cannot use or are not interested in. p17
(7) There should be zero coupling between classes, or only exported coupling relationships. That is, one class either has nothing to do with another class, or it only uses operations in the public interface of another class. p18
(8) Classes should only represent one key abstraction.
All classes in the package should be jointly closed for changes in the same type of properties. If a change affects a package, it will affect all classes in the package, but will not have any impact on other packages.
(9) Centralize related data and behaviors.
Designers should pay attention to objects that obtain data from other objects through operations such as get. This type of behavior implies that this empirical principle is violated.
(10) Put irrelevant information in another class (that is, the behavior of not communicating with each other). p19
Dependencies towards stability.
(11) Make sure that the abstract concept you model is a class, not just the role played by an object. p23
(12) Distribute system functions as uniformly as possible in the horizontal direction, that is: according to the design, top-level classes should share work uniformly.
(13)Do not create omnipotent classes/objects in your system. Be especially careful with classes whose names include Driver, Manager, System, and Susystem.
Plan an interface rather than implement an interface.
(14) Be careful with classes that define a large number of access methods in the public interface. The large number of access methods means that relevant data and behavior are not stored centrally.
(15) Be careful with classes that contain too many behaviors that do not communicate with each other.
Another manifestation of this problem is that a lot of get and set functions are created in the public interface of the class in your application.
(16) In an application composed of an object-oriented model that interacts with the user interface, the model should not depend on the interface, but the interface should depend on the model.
(17) Model as much as possible according to the real world (we often violate this principle in order to comply with the principle of system function distribution, avoid the all-purpose class principle, and centrally place related data and behaviors).
(18) Remove unnecessary classes from your design.
Generally speaking, we will downgrade this class to an attribute.
(19) Remove classes outside the system.
The characteristic of classes outside the system is that in abstract terms they only send messages to the system domain but do not accept messages from other classes in the system domain.
(20)Don’t turn operations into classes. Question any class whose name is a verb or derived from a verb, especially a class with only one meaningful action. Consider whether that meaningful behavior should be moved to a class that already exists or has not yet been discovered.
(21)We often introduce proxy classes when creating analysis models of applications. During the design phase, we often find that many agents are useless and should be removed.
(22) Try to reduce the number of collaborators of the class.
The number of other classes used by a class should be as small as possible.
(23) Minimize the number of messages passed between classes and collaborators.
(24) Minimize the amount of collaboration between classes and collaborators, that is: reduce the number of different messages passed between classes and collaborators.
(25) Minimize the fan-out of the class, that is: reduce the product of the number of messages defined by the class and the number of messages sent
(26) If the class contains an object of another class, then the containing class should be The contained object sends the message. That is: an inclusion relationship always implies a use relationship.
(27) Most methods defined in a class should use most data members most of the time.


(28) The number of objects contained in a class should not exceed the capacity of the developer's short-term memory. This number is often 6.
When a class contains more than 6 data members, you can divide logically related data members into a group, and then use a new containing class to include this group of members.
(29) Let system functions be distributed vertically in a narrow and deep inheritance system.
(30)When implementing semantic constraints, it is best to implement them based on class definitions. This often leads to class overflow, in which case the constraints should be implemented in the behavior of the class, usually but not necessarily in the constructor.
(31) When implementing semantic constraints in the constructor of a class, place the constraint test in the deepest inclusion level allowed by the constructor field.
(32) If the semantic information that constraints rely on changes frequently, then it is best to place it in a centralized third-party object
(33) If the semantic information that constraints rely on rarely changes, then it is best Distributed among the various classes involved in the constraints.
(34)A class must know what it contains, but it cannot know who contains it.
(35) Objects that share literal scope (that is, contained by the same class) should not have a usage relationship with each other
(36) Inheritance should only be used to model specialization hierarchies.
(37) Derived classes must know the base class, and base classes should not know any information about their derived classes.
(38) All data in the base class should be private, do not use protected data.

The designer of a class should never put things in a public interface that are not needed by users of the class.
(39)In theory, the inheritance hierarchy should be deeper, the deeper the better.
(40)In practice, the depth of the inheritance hierarchy should not exceed the short-term memory capacity of an average person. A widely accepted depth value is 6
(41) All abstract classes should be base classes
(42) All base classes should be abstract classes
(43) Put data, behavior and/or interface commonality as high as possible in the inheritance hierarchy.
(44) If two or more classes share common data (but no common behavior), then the common data should be placed in a class, and each class that shares this data contains this class.
(45) If two or more classes have common data and behavior (that is, methods), then each of these classes should inherit from a common base class that represents these data and methods. (46) If two or more classes share a common interface (referring to messages, not methods), then they should inherit from a common base class only if they need to be used polymorphically. (47) Case-by-case analysis of the display of object types is generally wrong. In most such cases, designers should use polymorphism.
(48) The situational analysis of the display of attribute values ​​is often wrong. Classes should be decoupled into an inheritance hierarchy, with each attribute value transformed into a derived class.


(49) Do not model the dynamic semantics of a class through inheritance relationships. Attempting to model dynamic semantics with static semantic relations results in switching types at runtime.
(50)Do not turn class objects into derived classes. Be careful with any derived class that has only one instance.
(51)If you think you need to create a new class at runtime, take a step back and realize that you are creating objects. Now, generalize these objects into a class.
(52) It should be illegal to use an empty method (that is, a method that does nothing) in a derived class to override a method in the base class.
(53)Don’t confuse optional inclusion with the need for inheritance. Modeling optional inclusion as inheritance leads to a proliferation of classes.
(54)When creating an inheritance hierarchy, try to create reusable frameworks rather than reusable components.
(55) If you use multiple inheritance in your design, assume you made a mistake. If you didn't make a mistake, you need to try to prove it.
(56) As long as inheritance is used in object-oriented design, ask yourself two questions: (1) Is the derived class a special type of the thing it inherits? (2) Is the base class part of the derived class?
(57) If you find multiple inheritance relationships in an object-oriented design, make sure that no base class is actually a derived class of another base class.
(58)In object-oriented design, if you need to choose between inclusion and association, please choose inclusion.
(59) Do not use global data or global functions for bookkeeping of class objects. Class variables or class methods should be used.
(60)Object-oriented designers should not let physical design principles undermine their logical designs. However, we often use physical design criteria in making decisions about logical design.
(61)Do not bypass the public interface to modify the state of the object.

The above is the detailed content of Introduction to object-oriented principles in php. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn