The maintainability and reusability of software
Robert C.martin, a well-known software guru, believes that a low-maintainability (maintainability) software design is typically caused by the following 4 reasons:
- Too stiff (rigidity)
- Too fragile (fragility)
- Low reuse rate (immobility)
- High viscosity (Viscosity)
The software engineering and modeling guru Peter Coad believes that a good system design should have the following three properties:
- Scalability (Extensibility)
- Flexibility (flexibility)
- Pluggable (pluggability)
software reuse (reuse) or reuse has many advantages, such as improving software development efficiency, improving software quality, saving development costs, and proper reuse can also improve the maintainability of the system .
The goal of object-oriented design multiplexing is to enable multiplexing that supports maintainability.
In object-oriented design, maintainability reuse is based on the principle of object-oriented design, which is the principle of reuse, which can effectively improve the reusability of the system and improve the maintainability of the system.
The object-oriented design principle and design pattern are also the compass to reconstruct the system rationally, and the reconstruction (refactoring) is to improve the quality and performance of the software by adjusting the program code without changing the existing functions of the software, and making the design pattern and structure of the program more reasonable. Improve the scalability and maintainability of the software .
Commonly used object-oriented design principles include 7, these principles are not isolated, they depend on each other and complement each other.
Design Principle Name |
Introduction to design principles |
Importance |
Single principle of responsibility |
Classes have a single responsibility and cannot put too much responsibility in one class |
★★★★☆ |
Opening and closing principle |
The software entity is open to the extension, but it is closed for modification, that is, to extend its functionality without modifying a software entity |
★★★★★ |
Principle of substitution on the Richter scale |
In a software system, a subclass object can be accepted where a base class object is acceptable. |
★★★★☆ |
Dependency reversal principle |
Programming for the abstraction layer, rather than programming for specific classes |
★★★★★ |
Interface Isolation principle |
Use multiple specialized interfaces instead of one unified interface |
★★☆☆☆ |
The principle of synthetic multiplexing |
Use composition and aggregation associations as much as possible in your system, use less and not even use inheritance relationships |
★★★★☆ |
Dimitri Law |
The fewer references a software entity has to other entities, the better, or if two classes do not have to communicate directly with each other, then these two classes should not have a direct interaction, but by introducing a third party to the indirect interaction |
★★★☆☆ |
Single Duty principle (Responsibility Principle, SRP)principle Definition
Defined as follows:
An object should contain only a single responsibility , and the responsibility is fully encapsulated in a class.
The English definition is:
Every object should has a single responsibility, and that responsibility should is entirely encapsulated by the Class.
Another way to define this is as follows:
As far as a class is concerned, there should be only one cause for it to change .
The English definition is:
There should never is more than one reason for a class-to-change.
analysis of single duty principle
The more responsibilities a class (or large to a module, small to a method) assumes, the less likely it is to be reused , and if a class takes on too much responsibility, it is tantamount to coupling those responsibilities together, and when one of the responsibilities changes, it may affect the operation of other responsibilities.
The responsibilities of the class include two aspects: data Responsibility and behavior responsibility , data responsibility is embodied by its attribute , and behavior responsibility is embodied by its method .
The principle of single responsibility is to achieve high cohesion , low-coupling guidelines, in many code refactoring techniques can find its existence, it is the simplest but most difficult to apply the principle of the need for designers to discover the different responsibilities of the class and separate it, The multiple responsibilities of the discovery class require designers to have strong analytical and design skills and related refactoring experience.
example of a single responsibility principle
Example description
A Java-based C/s system "login function" is implemented by the following login class (login):
A single responsibility principle is now used to reconstruct it.
Definition of opening and closing principles (open-closed Principle, OCP)principle Definition
Defined as follows:
A software entity should be open to extensions and closed for modifications . In other words, when designing a module, it should be allowed to be extended without modification, that is, to change the behavior of the module without modifying the source code.
The English definition is:
Software entities should is open for extensionand closed for modification.
analysis of opening and closing principle
The opening and closing principle was proposed by Bertrand Meyer in 1988, which is one of the most important principles in object-oriented design.
In the definition of open and closed principle, a software entity can refer to a software module, a local structure consisting of multiple classes, or a separate class.
abstraction is the key to the open and closed principle.
The open/Closed principle can also be described by a more specific " Principle of variability encapsulation ", on the principle of variability encapsulation (Principle of encapsulation of Variation, EVP) Requirements to find the system's variables and encapsulate them.
Example of opening and closing principle
Example description
A graphical interface system provides a variety of different shapes of buttons, the client code can be programmed for these buttons, the user may change the requirements of the use of different buttons, the original design:
The system is now reconstructed to meet the requirements of the closed-closed principle.
The principle of substitution on the Richter scale (Liskov Substitution Principle, LSP)principle Definition
The principle of substitution of the Richter scale (Liskov Substitution Principle, LSP) is defined in two ways,
The first is defined in a relatively strict manner, and is defined as follows:
If each object of type S is O1, there is an object O2 of type T, so that all program P defined in T is replaced with O2 for all objects O1, and the behavior of the program P does not change, then the type S is a subtype of type T.
The English definition is:
If for each object O1 of type S There are an object O2 of type T such so for all programs P defined in terms of T, the being Havior of P was unchanged when O1 was substituted for O2 and S is a subtype of T.
The second easier to understand definition is as follows:
all references to the base class (the parent class) must be able to use the object of its subclass transparently .
The English definition is:
Functions that use pointers or references to base classes must is able to use objects of derived classes without knowing I T.
analysis on the principle of substitution of Richter
The principle of substitution of the Richter scale can be expressed as follows: if the base class object can be used in software, its subclass object must be used . Replace the base class with its subclasses, the program will not produce any errors and exceptions, and conversely, if a software entity uses a subclass, then it is not necessarily able to use the base class.
The principle of substitution of the Richter scale is one of the important ways to realize the open and closed principle, because the subclass object can be used wherever the base class object is used, so as far as possible the base class type is used in the program to define the object, while at run time the subclass type is determined, and the child class object is substituted for the parent class object.
Like animals → like cats Because cats are animals. |
example of substitution principle on the Richter scale
Example description
A system needs to implement the encryption of important data (such as user password), in the data Operation Class (Dataoperator) need to call the encryption algorithm defined in the cryptographic class, the system provides two different encryption classes, Ciphera and Cipherb, they implement different encryption methods, You can choose one of these to implement cryptographic operations in Dataoperator.
:
If you need to replace a cryptographic algorithm class or add and use a new cryptographic algorithm class, such as change Ciphera to Cipherb, you need to modify the client class client and data operation class Dataoperator source code, violating the open and closed principle.
It is reconstructed by the principle of the substitution of the Richter scale, and the system can be expanded flexibly to meet the principle of opening and shutting.
Dependency reversal principle (dependence inversion Principle, DIP)principle Definition
Defined as follows:
High-level modules should not rely on low-layer modules , they should all rely on abstraction. Abstractions should not be dependent on detail, and detail should be dependent on abstraction .
The English definition is:
The modules should not depend upon low level modules, both should depend upon abstractions. abstractions should not depend upon details, details shoulddepend upon abstractions.
Another expression is:
To program for the interface, do not program for implementation .
The English definition is:
Program to a interface, not an implementation.
analysis of dependency reversal principle
Simply put, the dependency reversal principle means that the code relies on abstract classes rather than on specific classes, programming to interfaces or abstract classes, rather than specific classes .
The key to realize the open and close principle is abstraction, and from abstract to materialize realization, if the opening and closing principle is object-oriented design, then the dependence reversal principle is the main means of object-oriented design .
One of the common implementations of the dependency reversal principle is to use abstract classes in your code and place specific classes in the configuration file .
"Put abstractions into code, put details into metadata"
Put abstractions in Code, Details in Metadata
Coupling between classes
- 0 coupling relationship
- Specific coupling relationship
- Abstract coupling relationship
The dependency reversal principle requires the client to rely on abstract coupling, and abstract coupling is the key to the dependency reversal principle .
Dependency Injection
- Construct injection (Constructor injection): Injects an instance variable through a constructor .
- Set value injection (setter injection): Injects instance variables through setter methods .
- Interface Injection (Interface injection): Injects an instance variable through an interface method .
example of dependency reversal principle
Example description
A system provides a data conversion module that can convert data from different data sources into multiple formats, such as the ability to convert data from a database (Databasesource), or convert data from a text file (TextSource), and the converted format can be an XML file ( Xmltransformer), or it can be an xls file (Xlstransformer), and so on.
Due to changes in demand, the system may need to add new data sources or new file formats, each adding a new type of data source or a new type of file format, the customer class MainClass need to modify the source code in order to use the new class, but contrary to the open and closed principle. It is now reconstructed using the dependency reversal principle.
Interface Isolation principle (Interface segregation Principle, ISP)principle Definition
Defined as follows:
The client should not rely on interfaces that it does not need .
The English definition is:
Clients should not being forced to depend upon interfaces, that they does not use.
Note that the interface in the definition refers to the method that is defined.
Another way to define this is as follows:
Once an interface is too large , it needs to be split into smaller interfaces , and clients using that interface need only know the methods associated with them.
The English definition is:
Once an interface have gotten too ' fat ' it needs to being split into smaller and more specific interfaces so this any Clients of the interface would only know on the methods that pertain to them.
analysis of the principle of interface isolation
The principle of interface isolation refers to the use of multiple specialized interfaces rather than a single total interface . Each interface should assume a relatively independent role, not a lot, do not do the things that should be done to do.
- An interface represents only one role , and each role has its own specific interface, which can be called the "role isolation principle".
- The interface simply provides the behavior required by the client, that is, the required method, the behavior that the client does not need to hide, and should provide the client with as little as possible a separate interface rather than a large total interface.
When you split an interface using the interface isolation principle, you must first meet a single principle of responsibility , define a set of related operations in an interface, and, with high cohesion, the fewer methods in the interface are as good as possible.
Can be used in the design of the system in a customized way, that is, for different clients to provide a wide range of interfaces , only the user needs to provide the behavior, and hide the user does not need the behavior.
example of an interface isolation principle
Example description
Demonstrates a system with multiple customer classes that defines a huge interface (FAT interface) Abstractservice in the system to serve all customer classes. It can be refactored using the interface isolation principle.
Instance parsing
Synthetic multiplexing principles (Composite reuse Principle, CRP)principle Definition
The synthetic multiplexing principle (Composite reuse Principle, CRP) is also known as the combinatorial/aggregation multiplexing principle (composition/aggregate reuse Principle, CARP)
Defined as follows:
Try to use object combinations instead of inheritance to achieve reuse.
The English definition is:
Favor composition of objects over inheritance as a reuse mechanism.
analysis of the principle of synthetic multiplexing
The principle of synthetic reuse is to use some existing objects in a new object through association relationships (including combinatorial relationships and aggregation relationships) to make them part of new objects; The new object is used to re-use its existing functions by delegating methods that call existing objects . In short: Use the combination/aggregation relationship as much as possible, with less inheritance .
In object-oriented design, there are two basic methods for reusing existing designs and implementations in different environments, that is, by combining/aggregating relationships or through inheritance .
- Inheritance reuse: Simple to implement and easy to scale. The encapsulation of the system is compromised; the implementations inherited from the base class are static, impossible to change at run time, not flexible enough, and can only be used in a limited environment. (" White box " multiplexing)
- Combination/Aggregation multiplexing: a relatively low degree of coupling, optionally invoking the operation of a member object, which can be performed dynamically at run time. (" black box " multiplexing)
The combination/aggregation can make the system more flexible , the coupling between classes and classes is reduced , the change of one class has a relatively small impact on other classes, so it is generally preferred to use combination/aggregation to achieve reuse , and then to consider inheritance, when using inheritance, Need to strictly follow the principle of the Richter substitution, effective use of inheritance will help to understand the problem, reduce complexity, and abuse of inheritance will increase the difficulty of system construction and maintenance and the complexity of the system, so the need for careful use of inheritance reuse .
Examples of Principles
Example description
Some database access class design of some teaching management system:
If you need to replace the database connection mode, such as the original JDBC connection to the database, now with the database connection pool connection, you need to modify the Dbutil class source code. If the Studentdao uses a JDBC connection, but the Teacherdao uses a connection pooling connection, you need to add a new Dbutil class and modify the source code of Studentdao or Teacherdao to inherit the new database connection class, which will violate the open/closed principle. Poor system scalability.
It is now reconstructed using the synthetic multiplexing principle.
Dimitri (Law of Demeter, LoD)principle Definition
The Dimitri rule (law of Demeter, LoD), also known as the least-knowledge principle (Least knowledge Principle, LKP), has several defining methods, several of which are typically defined as follows:
(1) do not talk to "strangers" .
The English definition is:
Don ' t talk to strangers.
(2) communicate only with your direct friends .
The English definition is: talk only to your immediate friends.
(3) each software unit has only the least knowledge of the other units, and is limited to the software units closely related to the unit.
The English definition is as follows: Each unit should has only limited knowledge on other units:only units "closely" related to the current unit.
analysis on principle of Dimitri Law
The Dimitri Law came from a research project called "Demeter" at Northeastern University (Northeastern University) in the fall of 1987.
To put it simply, the Dimitri rule means that a software entity should interact with as few entities as possible . Thus, when a module is modified, it will minimize the impact of the other modules, the extension will be relatively easy, this is the software entity communication between the restrictions, it requires limiting the width and depth of communication between software entities.
In the Dimitri law, for an object, its friends include the following categories:
- Current object itself (this)
- An object that is passed in as a parameter to the current object method
- The member object of the current object
- If the member object of the current object is a collection, then the elements in the collection are also friends;
- The object created by the current object.
Any object, if one of the above conditions is met, is the "friend" of the current object, or "stranger".
Dimitri Law can be divided into narrow law and generalized law.
in the narrow Dimitri law, if two classes do not have to communicate with each other directly, then these two classes should not have direct interaction , if one of the classes needs to invoke a method of another class, you can forward the call through a third party.
The Dimitri rule of the narrow sense:
Can reduce the coupling between classes , but will add a large number of small methods in the system and scattered around the system, it can make a system of local design simplification, because each part will not be directly related to long-distance objects, but also The communication efficiency between different modules of the system is reduced, which makes the system not easy to coordinate with each other.
The generalized Dimitri rule:
It refers to the control of information flow, flow direction and the influence of information, mainly on the control of information hiding. The concealment of information can decouple the subsystems, allowing them to be developed, optimized, used and modified independently, while facilitating the reuse of the software, since each module does not depend on other modules, so each module can be used independently of other places. The larger the size of a system, the more important it is to conceal information, and the greater the importance of information hiding.
The main purpose of the Dimitri Law is to control the overload of information :
- In the division of classes, we should try to create loosely coupled classes , the lower the coupling between classes, the more beneficial to reuse, a loosely coupled class once modified, will not cause too much impact on the associated class
- In the structure design of a class, each class should minimize the access rights of its member variables and member functions
- In the design of a class, whenever possible, a type should be designed as an immutable class
- On references to other classes, one object's references to other objects should be minimized
Examples of Principles
Example description
The call relationship between a system interface class (such as Form1, FORM2, etc.) and data access classes (such as DAO1, DAO2, and so on) is more complex:
Instance parsing
Summary of Design principles
- For the design of object-oriented software system, it is necessary to improve the reusability of the system while supporting maintainability.
- The reuse of software can improve the efficiency of software development, improve the quality of software, save the development cost, and the proper reuse can improve the maintainability of the system.
- The principle of single responsibility requires that in a software system, a class is responsible only for a functional area of responsibility.
- The open and closed principle requires that a software entity should be opened to the extension and shut down for modification, that is, to extend the behavior of a system without modifying the source code.
- The principle of substitution of the Richter scale can be expressed in the software if the base class object can be used, its subclass object must be able to be used.
- The dependency reversal principle requires that abstractions should not be dependent on detail, that details should be dependent on abstraction, and programming for interfaces, not for implementation.
- The principle of interface isolation requires that clients should not rely on interfaces that it does not need, and that some large interfaces will be thinned out into small interfaces for use by clients.
- The principle of synthetic multiplexing requires that the combination of objects be used whenever possible, without inheritance.
- The Dimitri law requires that a software entity should interact with as few interactions as possible with other entities.
Object-Oriented design principles