Coupling of C ++ program design

Disclaimer: This article is part of adoption and reference "code view of the world - the road leading architect of the" content, it can be said that the book is a chapter book review coupling, thanks to the selfless sharing of the remainder of the book leaves the teacher.

1. What is the coupling?

Coupled fact, the correlation between the programs.

Absolutely no correlation between the program is not possible, otherwise it is impossible to start a program, the following chart:

 

 

This is a Linux socket TCP programming in program flow, TCP server-side in the figure, socket (), bind () interfaces, listen () interfaces, accept there is certainly between () associated with the interface (that is, to call the next an interface program is necessary before the first call to an interface), which is coupled to, or the whole TCP server will not be established, as well as changes in the incoming data bind () in, such as port number, then the next listen () listen port, Accept () will change the reception connection port, so there is a strong correlation between them, are tightly coupled. Therefore, the coupling of the code is relevant, if not understand, it does not matter, read on, I believe you will understand, ha ha.

 

2. Coupling form

Coupling between (1) Data

    In the same structure or class, such as:

typedef struct Person

{

int age;

char* name;

}Person;

class Person

{

    private:

        int age_m;

        bool namePresent_m;

        std::string name_m;

};

In the above structures and classes, the names and ages of two basic data units combined into one data unit, there is a coupling between the two data, because they know each other, in some operations may require operating with each other of course these two data coupling it is relatively low, but the data name_m namePresnet_m determines whether there is, so coupling between the two data on much higher.

 

Coupling between (2) Function

    If there will function in a class of mutual coupling, such as the following example:

    Class Person

{

    Public:

        Int getAge(){return age_m;};

        Void setAge_v(int age){age_m = age;};

        Std::string getName(){return name;};

        Void setName(std::string name){name_m = name;};

   

    Private:

        Int age_m;

        Std::string name_m;

};

Wherein getAge () and setAge_v () interface operation is the same data, can influence each other, it is clear that there is a coupling, but getName () and getAge () associated with the interface of the two is not significant, but also present coupling, because getName () class data can be accessed, getAge () can access, if the programmer inadvertently writing code also calls the same data to two interfaces, each had an impact.

In addition to coupling between the package functions in a class, will also have a function of the external coupling according to business needs, such as the example network programming in said beginning, socket (), listen (), bind (), accept ( between) to generate a strong coupling.

And in the two classes, such as:

Class Fruit

{};

Class Apple:Fruit

{};

Class FruitFactory

{

    Public:

        O'ercame getFruit () {fruit_p Fruit * = new Apple (); fruit_p return; }

};

Class Person

{

    Public:

        Void eatFruit (Fruit furious *);

};

FruitFactory fruitFactory;

Fruit* fruit = fruitFactory.getFruit();

Person person;

If (fruit != NULL)

{

person.eatFruit(fruit);

}

    Generating a data coupling between the above two FruitFactory and Person class, getFruit () and eatFruit () also produced between the two coupling interfaces.

 

Coupling between (3) and function data

    From (2) The program can also be seen, eatFruit () This interface and the data generated Fruit coupling, if you do not create Fruit first, then the next eatFruit () operation also does not make sense, if forced to call, and may even cause program crashes, resulting coredump.

    Examples of the above coupling is quite obvious, there are some obvious coupling, as follows:

    Speaker speaker;

speaker.PowerOn() ;
speaker.PlayMusic() ;

The surface is PlayMusic () of PowerOn is () dependent, and is a function of the coupling between, but the reason behind the PowerOn is () function allows the player in an energized state:

PowerOn(){
this.isPowerOn = true;

}
// Only access to electricity, the player can play normal music
PlayMusic () {
IF (this.isPowerOn)

Play();

}

These two functions are .isPowerOn this data to communicate through this. Essentially the coupling between the data and functions is this.

 

3. Q coupling

    Often hear the "decoupling" of the word, it is not coupled are bad?

    The coupling according to the characteristics of the code to analyze, first of all look at the following few questions, after reading, I believe we have the answer.

(1) coupling can eliminate it?

After so many examples above, it also means the couple everywhere, so that can not be eliminated.

(2) Since that can not be eliminated, then what is the meaning of decoupling?

Decoupling is to reduce the coupling between program modules.

What is the purpose (3) that decoupling is?

The purpose of decoupling is to enhance the portability of a module, reusability, just like the human kidneys can be transplanted, but the vascular graft is difficult to transplant it, why, because the blood vessels that "module" and the body of this "system" of "coupling" between too strong, too many local association, transplant large workload. And to reduce the associated module and an external module, modified internal module to external influence is relatively small, this is also a kidney transplant and vascular grafts employing similar, each has a vascular organ, once transplanted, all organs have to move, time-consuming labor-intensive.

That portable and reusable What are the benefits? For example, we use a computer program to write a Tetris game, then customers have to do this game in the mobile phone side, this time will be able to reuse logic and strategy game Tetris computer terminal, just replace the line put out the interface, business strategy and part of the basic need to modify the game interface and business logic of the program if the computer end of the "seamless", it almost needs refurbished again.

(4) that all programs need to decouple it?

No, sometimes, but we need to enhance the coupling of the program, which is usually said that the "high cohesion, low coupling", which is actually a couple of cohesion, or the relevance of the program. As in the following example:

Different locations on the screen to display a plurality of different pattern, such as a triangle, square, etc., where all the information is concentrated in the following two array.

A shape array is: { "triangle," "square," "rectangle", "diamond"}.

A position array is: {pointl, point2, poin mouth, point4}.

The number of elements of two arrays is just as much, they are one to one relationship. For example, the first positio mouth is the location information of the first shape. Then the code is as follows:

for(int i = O; i <count, i++){

Draw(shape[i] , position[i]);

}

But not so easy to do! It will be buried risks for future changes. Because the correspondence between the two array elements, has not been officially recognized. This time it is necessary to enhance their association, the association implicitly converted to explicit association. as follows:

Dictionary die = { "triangle": pointl,

"Square": Point2,
"rectangle": Point3,
"diamond": Point4};
// Draw () function no longer have to worry about painting the wrong
foreach (var Item in dic) {
Draw (item.key, Item.. value);
}

Usually used in programming structure and the type of packaging is the same, the number of data and associated methods in combination, an explicit association between them to enhance convenience of use and portability.

4. how decoupling?

    (1) for implementing the principles of the interface code

    Program can not be without changes, but try to change a module on the internal interfaces do not change, even if the need to change, it is best to use an additional adapter mode adaptation program. Because the interface is associated with a program with the outside at the interface remains unchanged, coupling constant is to keep the modules and external modules, so as to ensure its portability and reusability is not modified outside the module affected.

    (2) ensure that a module may test (Test Unit)

    If the module is a separate unit testing, means that it can be transferred to another program, low coupling.

    (3) can learn about the design ideas of design patterns.

    (4) the module to complete the internal logic

    The fundamental purpose of decoupling is to dismantle unnecessary contact between elements, a core principle is to let the logic of each module and complete independence. Which contains the two points, one complete internal logic, but relies on external resources as much as possible is invariant; the second is the external feature is also reflected in the "invariant" (or do not variable as possible), so that others may safely rely on me. Some honorable function, and it is limited to external data communication parameters and return value of the function, then this function gives the impression can be described with two words: fly. It is the data they need are clearly identified in the parameter list, we can provide the complete works of value in return. If a parameter is not in the data you need, you'll Lennon rely on others, because you will likely need a third party to identify by name special for; the same token, if you provide incomplete data and return value parameters , the others will depend on you. Some people feel mysterious function, regular hard to find: it needs all the data is not reflected in the parameter list, some hidden inside a function, variables such unreliable behavior is difficult to predict; it also outputs not focused on the return value, but may be modified in some obscure corner of hidden resources. Such people need to function in the course and it keeps running in order to grasp its characteristics. The former assured to use, and is portable, reusable, requiring careful when using the latter, and difficult to transplant.

Examples of coupling 5. Optimization

Example one

In one example described above:

PowerOn(){
this.isPowerOn = true;

}
// Only access to electricity, the player can play normal music
PlayMusic () {
IF (this.isPowerOn)

Play();

}

PowerOn here () interfaces and PlayMusic () interfaces in the same class, isPowerOn internal variables are private variables, such wording is no problem. If isPowerOn is a global variable, and PlayMusic () interface program is relatively complex, you might forget to call when the first call to isPowerOn PowerOn is set to true on the outside. To make PlayMusic () interface logic and complete independence, it is necessary to explicitly PlayMusic () passed isPowerOn parameters, such as PlayMusic (bool isPowerOn), even in a class, it is recommended in order to prevent the use of at PlayMusic external call ( ) was added before a judgment isPowerOn interfaces, such as:

Speaker speaker;

If (speaker.isPowerOn())

{

    speaker.PlayMusic ();

}

Later it was modified so that when the part of the program, knows first energized while playing music.

 

Example Two

A person want to study:

The Person Person = new new the Person ();
person.ReadBook (Book);
// ReadBook function in the logic is as follows:
void ReadBook (Book Book) {
// first person requires reading glasses before, the first step must be to wear glasses the action
WearGlasses (this.MyGlasses); // person class has a member called MyClasses of
the Read (Book);
. If the person does not glasses, this.myGlasses variable is null, a direct call person ReadBook (book); there will be abnormal, how to do it?

Optimization of a: by injecting member functions

So a patch logic of it, before ReadBook give him a pair of glasses:
person.setMyGlasses (new new Glasses ()); // first for the person with glasses
person.ReadBook (book);
above, plus the person.setMyGlasses (new Glasses ()); this line of code, this bug is solved. Resolve was not perfect, because it requires every programmer needs to keep in mind before calling person.ReadBook (book), give members an assignment:
person.setMyGlasses (new new Glasses ());
it is very easy to go wrong. Because ReadBook is a public function, it should not be implicitly defined use conditions.

Optimization II: by implanting constructor
we can add a parameter to the constructor glasses of Person:
public Person (Glasses glasses) {
this.MyGlasses = glasses;

}
So that whenever a programmer to create a Person, that they will be forced to create a Glasses objects. Programmers no longer have to remember some of the extra demand. Such logic would achieve the initial self-improvement.
When the Person class creates much more, you will find constructor injection will bring the following question: because many other functions in the conduct Person, such as eating, running, etc., in fact, does not need glasses, and likes reading are in the minority Therefore person.ReadBook (book); the number of calls of this code pitiful. For a remote ReadBook function, we should let each Person must be equipped with a pair of glasses (whether he read do not read), it's not fair. Also, we should let each individual needs to solve.
So, is there a better way? "Optimization of three" described further below solves this problem.

Optimization three: by implanting an ordinary member function
can be modified so the next step: revert to the original no-argument constructor, and added separately as a function of glasses ReadBook parameters:
void ReadBook (Book Book, Glasses glasses) (
WearGlasses (glasses);
Read (book);
calling this function is as follows:
person.ReadBook (Book, new new glasses ());
. so that only the required reading people, will be equipped with a pair of glasses to achieve the precise allocation of resources
, but it is now every need with a new pair of glasses when reading: new glasses (), or too wasted, in fact, only
need a pair of enough.

Optimization four: a package injection

Well, before each taking their own reality glasses that best meet the needs of:
person.ReadBook (Book, person.getMyGlasses ());
This goes back to the original question: person.getMyGlasses () parameter may be empty, how do?

Simply let person.getMyGlasses () function package get themselves to solve this logic it:
Glasses getMyGlasses () {
IF (this.myGlasses == null)
this.myGlasses = new new Glassess ();
return this.myGlasses;

}
// ReadBook then return to the original code. ReadBook default logic is taken in his glasses
void ReadBook (Book Book) {
WearGlasses (this.getMyGlasses ());
the Read (Book);

}
Calls to ReadBook function as follows:
person.ReadBook (Book);
so every time reading, it will reuse the same pair of glasses, it will not affect other functions of the person.
Ah, you're done. This final ReadBook code portability of most, be regarded as independent and complete.
It can be seen from optimization to optimize a four around the circle, each step of the modifications are very small, each step is resolved - a small problem, new problems may be encountered before every step and did not anticipate. Optimization to optimize a three-dependent injection are three kinds of methods: injection property, and a normal function constructor injection injection. They are not good or bad, only the application of the points, here we are with a case presented to string them together. At the same time we Through this small example can also appreciate: write better code is needed craftsman spirit. So that each module is independent and complete, its meaning is rich. It's full of things they need on the list, provided to the outside world, it does not possession. This means that the association is unidirectional and the outside world, so that each module becomes neatly, easy to use. If the module to be replaced, and will not be removed when lingering around the module.

6. There are eggs

There is no absolute good program, just to understand the coupling to write a better program, but writing the program is too obsessed with coupling, but not beautiful. However, the usual programming should also pay attention and think, and slowly will be able to get some "feel", will develop a good programming practice.

 

Way to write good code, one must have a certain accumulation of knowledge, read more books, standing on the shoulders of our predecessors, not just the amount of code accumulation, the second is the code audit, the audit does not own the code to find yourself some good coding habits, have the awareness to change.

Guess you like

Origin www.cnblogs.com/qiuquanguan/p/11933126.html