Object-Oriented Software Design Principles (V)-Application Examples

Source: Internet
Author: User
Tags scp command

Now let's take a look at a practical example to observe its design from the perspective of different design principles. This example is the message processing module of the data transmission control component of the information processing center. First, let's take a look at its structure and class implementation pseudoCodeAnd subjectProgramPseudocode:

 

Figure 3-1 Structure of the Message Processing Module

 

Program 3-1Class implementation pseudocode

 //////////////////////////////////////// /////////////////////////////////////////  //  
Command class
//////////////////////////////////////// ///////////////////////////////////////// //

/* The difficulty of multithreading lies in thread management and thread synchronization.

The following pseudo code completes these two aspects well:
1. Use Windows Thread Pool for thread management
2: Use a ccommand object to implement Thread Synchronization
*/

Class Ccommand
{
Public :
Ccommand ()
{
: Interlockedincrement (& sm_executingcommandcount );
}

Virtual ~ Ccommand ()
{
: Interlockeddecrement (& sm_executingcommandcount );
}

Virtual Int Execute () = 0 ;

Void Setcontent (const string & content)
{
M_scontent = content;
}

// Number of commands being processed
Volatile Static Int Sm_executingcommandcount = 0 ;
// The cswmrg class implements the "multiple threads read at the same time, but cannot read or write at the same time" function.
Static Cswmrg sm_swmrg;

Protected :
// Only the ccommand subclass that processes messages needs to reload this method.
Virtual Int Process () =0 ;

Private :
String m_scontent;
};

/*
Subclass only needs to overload process () to process various requests (PARSE m_scontent and process m_scontent !!!
It can be operated as a single-threaded program.
Do not worry about cache synchronization and object release
*/

// SCP command inherits this class
Class Creadcommand: Public Ccommand
{
Virtual Int Execute ()
{
Sm_swmrg.waittoread ();
Int Retval = process ();
Sm_swmrg.done ();
Return Retval;
}
};

// Update commands inherit this class
Class Cwritecommand: Public Ccommand
{
Virtual Int Execute ()
{
Sm_swmrg.waittowrite ();
Int Retval = process ();
Sm_swmrg.done ();
Return Retval;
}
};

 

Program 3-1Main Program Implementation pseudocode

 //////////////////////////////////////// /////////////////////////////////////////  //  
Main Program
//////////////////////////////////////// ///////////////////////////////////////// //

Void Processmsg ( Const String & header, Const String & content)
{
// Ccommandfactory generates the corresponding ccommand object based on the Message Header
Ccommand * pcmd = ccommandfactory: getcommand (header );
// Set ccommand object content
Pcmd-> setcontent (content );

: Queueuserworkitem (threadfunction, pcmd );
}

Void Threadfunction (pvoid PV)
{
Ccommand * pcmd = reinterpret_cast <ccommand *> (PV)
Int Ret = pcmd-> execute ();
Delete pcmd;
}

 

The program contains four packages: Main, command, SCP, notice, and consumer factory. The main package contains the High-level Policy of the application, and the main code of the execution program. The command package is an abstract package that contains three abstract classes: ccommand, creadcommand, and cwritecommand; the SCP package contains all command objects that process the SCP protocol. The Notice package contains all command objects that process cache update notifications. The factory package contains the c‑factory class, this class generates the corresponding subclass object of the ccommand Class Based on the message header.

The program code in the main package uses the ccommand class and the ccommandfactory class, so it inherits the creadcommand class according to the internal command package and internal factory; the class in the SCP package inherits from the creadcommand class, so it relies on the command package; the classes in the notice package inherit from the cwritecommand class, so it depends on the command package. The c‑factory class in the factory package uses the ccommand abstract class and all its implementation subclasses, therefore, it depends on the command, SCP, and notice packages.

 

The following describes its design from the perspective of various object-oriented design principles:

1.Single Responsibility Principle (SRP))

The ccommand class and its sub-classes are responsible for executing commands (execute method), while the ccommandfactory class is responsible for selecting commands. Imagine what will happen if you put the job of selecting a command in ccommand: every time a ccommand subclass is added, the selection function of the ccommand will be modified, due to the modification of the ccommand class, all code dependent on it (all ccommand subclasses and client code using ccommand) need to be re-compiled, even if they have not been modified.

2.Open-closed principle (OCP)

When a new command is to be processed, we can add a subclass of the ccommand class to process the command, and then modify the ccommandfactory accordingly. The main code of the program does not need to be modified.

3.LiskovReplacement principle (LSP)

Replacing the ccommand base class with any subclass of the ccommand class will not change the function of the main program written for the ccommand.

4.Dependency inversion principle (dip)

The main program code (high-level module) does not depend on the Implementation subclass of each command (lower-level module), and both depend on ccommand (abstraction ).

Ccommand (abstraction) does not depend on the Implementation sub-classes (details) of each command, and the Implementation sub-classes (details) of each command depend on ccommand (abstraction ).

5.Interface isolation principle (ISP)

(This example is not shown)

6.Reuse publish Equivalence Principle (rep)

All classes in the Command package can be reused, and all classes in other packages cannot be reused.

7.Common Reuse Principle (CRP)

The command package is reusable, but some people may say that the command package is slightly in violation of the Reuse Principle, because some code may only use the creadcommand class (such as the SCP package) in the Command package ), some other code may only use the cwritecommand class (such as the notice package) in the Command package ). Should I split the command package into the readcommand package and writecommand package?

This is a question of design trade-offs. Yes, of course. Is it necessary to split the question? What are the benefits? In the command package, the creadcommand class and cwritecommand class should be generated in the ccommand class because it has another purpose besides executing commands-synchronous read/write operations. Therefore, it makes the assumption that the program using the command package must have the need to synchronize read and write operations, and the creadcommand and cwritecommand classes will be used at the same time.

The SCP package only uses the creadcommand class, while the notice package only uses the cwritecommand. How can this problem be solved? In fact, this is just a coincidence. If we add an SCP protocol package for some update operations, it will use cwritecommand. Likewise, if we add a read-only notification processing command to the notice package, it will also use creadcommand. In fact, we can combine the SCP package and the notice package into a large package. In this way, we can see that this large package uses both the creadcommand and cwritecommand classes. By the way, why not separate SCP and notice packages?

This is another design issue! When an SCP packet is used to process the SCP Protocol, each processing command may have a common abstraction (such as the SCP packet data structure) in other aspects ); the same is true for notice (such as the notification data format ). Therefore, the separation of SCP and notice is based on other reasons and has nothing to do with this topic.

8.Common blocking principle (CCP)

What are the advantages of separating the SCP package from the notice package instead of combining them? Suppose that when the SCP protocol format is modified, it only affects all command classes that process the SCP protocol, the command class for processing notification messages does not need to be re-released because of a change unrelated to it. Similarly, when the notification message format is modified, it should not affect the command class that processes the SCP protocol.

9.No-ring dependency principle (ADP)

From the structure diagram, we can see that there is no ring in the dependency.

10.Stable dependency principle (SDP)

The command selection rule is very unstable. Every time a new command or business rule is added, it must be modified accordingly. Therefore, the dependency factory package should be located at the high layer of dependency; the command package is very stable. No matter the business rule changes or other changes do not affect it, it should be located at the lower layer of the dependency relationship. That is to say, the dependency is in a stable direction.

11.Stable abstraction principle (SAP))

The command package is a very stable package, and it is also an abstract package (including abstract classes); the main, SCP, notice, and consumer factory packages are very unstable, and they are also specific.

 

Is it perfect?

Through the above explanation, does it show that this design is almost perfect? Either.

 

Have you noticed that because the main package uses the ccommandfactory class, a dependency is connected from the main package to the export factory package? The plufactory package depends on SCP and notice packages. In this way, the main package contains the subject code passing of the High-Level Policy, depending on SCP and notice; when the SCP or notice package is changed, the ccommandfactory class of the export factory package will be modified. Because of the ccommandfactory class modification, the main program body code part of the main package must be re-compiled.

It is difficult to find the dependency of the main package on the SCP package and the notice package from the code of the main package. Only the code of the main package depends on the command package and the factory package, you cannot see that it uses any SCP package or classes in the notice package. However, in the correlation graph, this dependency is totally lost. Hmm ...... Sometimes the graphic expression is indeed better than the code ~ ^_^ ~.

 

To put it bluntly, how can we eliminate the above dependency? Simple! -- Dip. The modified structure is 3-2:

 

Figure 3-2 Structure of the modified Message Processing Module

 

In this way, the compile factory package no longer depends on the SCP and notice packages. No matter what changes are made to the SCP or notice packages, the compile factory package and the main package do not need to be re-compiled.

 

The problem is, is this modification unnecessary? If the SCP and notice packages are frequently modified, or the main program body code of the main package requires a long Compilation Time, or the SCP and notice packages are provided in the form of a shared library or DLL, the preceding modifications are necessary. Otherwise, if the program size is small and the compilation time required by the main code of the program can be ignored, the modifications are not required. After all, the modified program structure adds an abstract layer, which increases complexity.

 

Design principles and patterns

For more information about the design patterns, see the 23 design patterns described in [gof95. The design pattern is indeed a good thing. How should we combine the object-oriented design principles with the design patterns?

 

My usual practice is to ignore the design model first, so everything is simple and supreme. After all, the complexity of the software is more or less increased when the design model is used (does it smell the smell of Complexity ?). With the expansion of the program scale, we need to apply the object-oriented design principle to abstract and decouple the modules in the software, and then return it to the pattern.

Codeproject

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.