SoFunction
Updated on 2025-03-03

The empirical principles of PHP object-oriented analysis design

(1) All data should be hidden inside the class it is located.
(2) The user of a class must rely on the shared interface of the class, but the class cannot rely on its user.
(3) Minimize messages in the protocol of the class.
(4) Implement the most basic public interfaces that all classes understand [for example, copy operations (deep copy and shallow copy), equality judgment, correct output content, parsing from ASCII description, etc.].
(5) Do not put implementation details (such as private functions that place common code) into the public interface of the class.
If the two methods of the class have a piece of public code, then you can create a private function that prevents these public codes.
(6) Do not disrupt the public interface of the class with something that the user cannot use or is not interested in.
(7) There should be zero coupling between classes, or only the exported coupling relationship. That is, one class either has nothing to do with another class, or uses only operations in the public interface of another class.
(8) Classes should represent only one key abstraction.
All classes in the package should be jointly enclosed for changes in the properties of the same class. If a change affects a package, it will affect all classes in the package, and will not have any impact on other packages.
(9) Centralize the relevant data and behavior.
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 has been violated.
(10) Put irrelevant information in another category (that is, behavior that does not communicate with each other).
Reliance in a stable direction.
(11) Make sure that the abstract concept you model is a class, not just the role that objects play.
(12) Distribute system functions as uniformly as possible in the horizontal direction, that is, according to the design, the top-level classes should work in a unified manner.
(13) Do not create all-around classes/objects in your system. Be especially careful with classes whose names include Driver, Manager, System, and Susystem.
Plan an interface instead of implementing an interface.
(14) Be careful with classes that define a large number of access methods in public interfaces. A large number of access methods means that relevant data and behavior are not stored centrally.
(15) Be careful with categories that contain too many behaviors that do not communicate with each other.
Another manifestation of this problem is that many get and set functions are created in the public interface of the class in your application.
(16) In applications composed of object-oriented models interacting 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 in real-world models (we often violate this principle in order to adhere to the principle of system function distribution, avoid the principle of all-round class, and concentrate on placing relevant data and behaviors).
(18) Remove unwanted classes from your design.
Generally speaking, we will downgrade this class to a property.
(19) Remove classes outside the system.
The characteristic of classes outside the system is that they only send messages to the system domain but do not accept messages sent by other classes within the system domain.
(20) Do not turn operations into classes. Question any class whose names are verbs or derived verbs, especially if there is only one meaningful behavior. Consider whether that meaningful behavior should be moved to a class that already exists or has not been discovered.
(21) We often introduce proxy classes when creating analytical models for applications. During the design stage, we often find that many agents are useless and should be removed.
(22) Minimize the number of collaborators in the class.
The number of other classes used by one 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 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, the containing class should send a message to the included object. That is: including relationships always means using relationships.
Most methods defined in the (27) Most of the methods defined in the class should use most data members most of the time.
(28) The number of objects contained in the 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, the logically related data members can be divided into a group, and then a new containing class can be used to include this group of members.
(29) Let the system functions be distributed vertically in a narrow and deep inheritance system.
(30) When implementing semantic constraints, it is best to implement them according to the class definition. This often leads to class flooding, in which case constraints should be implemented in the behavior of the class, usually in the constructor, but not necessarily.
(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 on which the constraint depends is changed frequently, it is best to put it in a centralized third-party object.
(33) If the semantic information on which the constraint depends is seldom changed, it is best to be distributed in the various classes involved in the constraint.
(34) The class must know what it contains, but cannot know who contains it.
(35) Objects that share literal scope (that is, they are included in the same class) should not have a usage relationship with each other.
(36) Inheritance should only be used to model specialized hierarchies.
(37) Derived classes must know the base class, and the base class should not know any information about their derived classes.
(38) All data in the base class should be private, and no protection data is used.
Class designers should never put things that class users do not need in public interfaces.
(39) Theoretically, the inheritance hierarchy system should be deeper, and the deeper the better.
(40) In practice, the depth of the inheritance hierarchy should not exceed the short-term memory ability of an ordinary 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 the commonalities of data, behaviors and/or interfaces as much as possible at the high end of the inheritance hierarchy system.
(44) If two or more classes share public data (but no public behavior), then the public data should be placed in a class, and each class that shares this data contains this class.
(45) If two or more classes share data and behavior (that is, methods), then each of these classes should inherit from a common base class representing these data and methods.
(46) If two or more classes share a common interface (referring to messages, not methods), they should inherit from a public base class only if they need to be used polymorphically.
(47) The analysis of the segmentation of the display of object types is generally wrong. In most such cases, designers should use polymorphism.
(48) The analysis of the sub-situation of the display of attribute values ​​is often wrong. Classes should be decoupled into an inheritance hierarchy, and each property value is transformed into a derived class.
(49) Do not model the dynamic semantics of classes through inheritance relationships. Attempting to model dynamic semantics with static semantic relationships results in switching types at runtime.
(50) Do not turn the object of the class into a derived class. Be careful with any derived class that has only one instance.
(51) If you feel you need to create a new class at run time, then take a step back to realize that what you are trying to create is the object. Now, summarize these objects into a class.
(52) It should be illegal to overwrite methods in the base class using empty methods (that is, methods that do nothing) in the derived class.
(53) Do not confuse optional inclusion with the need for inheritance. Modeling optional inclusions into categories that inheritance will lead to flooding.
(54) When creating an inheritance hierarchy, try to create a reusable framework instead of reusable components.
(55) If you use multiple inheritance in your design, first assume that you made a mistake. If you don'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 relationships and association relationships, please select inclusion relationships.
(59) Do not use global data or global functions for the bookkeeping work of class objects. Class variables or class methods should be used.
(60) Object-oriented designers should not let physical design guidelines undermine their logical design. However, we often use physical design criteria in making decisions on logical design.
(61) Do not bypass public interfaces to modify the state of the object.