Reduce coupling (by Martin Fowler)

zhaozj2021-02-11  199

One of the oldest design quality signs is coupled. It appears together in the earliest structured design and never disappears. I still think of it when considering software design. There are several ways to describe the coupling, but it can be reduced to this: if the change in one module in a program requires changes in another module, then coupling exists. This may be a similar thing in two modules, so code in one module is the code in another module.

There is an impact on repeat. This is the most important and obvious essential example of code repetition. Repeat always means coupling, as a change in a duplication means changes in another code. It is also difficult to find a duplication code, because there is no obvious relationship between the two codes.

The coupling also appears in the code used in one module to use the other module's code, possibly by calling a function or access some data. At this point, it becomes very clear, unlike duplicate code, you can't always avoid coupling. You can divide a program into many modules, and these modules need to communicate in some way - otherwise, you only have many programs. Coupling is required because if you disable coupling between modules, you only put all things in a large module. Then

There will be a lot of coupling - only under the carpet.

Therefore, coupling is the Dongdong we need to control, but how to control it? Do we need anywhere, is it worried, or is it important than some places than some places? Which factor makes coupling bad, what is it allowed?

figure 1:

Look

I am most concerned about the coupling of the highest layer module. If we divide a system into one

(Or fewer) large modules, how do these modules couple it? I am concerned with coarse particle size

Block, because it is worried that the coupling of any place is puzzled without knowing it. Biggest question

The problem comes from the uncontrolled coupling of the upper layer. I don't worry about the number of modules coupled together.

But I pay attention to the style of dependencies between modules. I also found pictures (Diagram)

We are very helpful.

When I use this term, I use it as the UML as defined.

So if any code in the UI (user interface) module is called a function

Use some data or use the type of type in the domain module to reference the field

Any code in the model, then the UI module depends on the domain module. If anyone change

The domain model, the UI model will have the possibility of changing. Dependent is one-way: UI

Modules are usually dependent on the domain module, not other situations. We will have a second

Dependency If the domain module also rely on the UI module.

UML dependence can also be transferred. If the UI module depends on the domain module, and the domain module depends on the data module, we cannot assume that the UI module relies on the database module. If it is indeed, we must use an additional direct dependence on the UI and database modules. This non-passed is very important because it makes us figure out how I use the UML symbol. UML is designed for the OO system, but the symbol of the basic module and dependent on the style of most software. This high-level

Module's UML name is package (Package), so I will use this term from now.

The UML police will not arrest me!: P) Because these are bags, my name is this chart (however in UML

Strictly called class maps).

What I described here is a hierarchical structure, which is very familiar with any person engaged in information systems.

The layer in an information system provides us to describe the things that must be considered.

material. The most common recommendations for dependent structures are to avoid cycling. The loop is to bring problems,

Because they point out that you will get a change in each change, these changes are returned.

Initial packet. Such a system is more difficult to understand because you only have repeated loops many times. I do not

The loop between the avoidance is avoided as a strict law. If they are localized, I will

Will tolerate them. The problem between the two packets of the same layer of an application smaller.

figure 2:

A mapper package

In Figure 1A, all dependencies are in one direction. This is a symbol of a collection of well-controlled depends, but is not a need. Figure 1b shows the usual feature of another information system, which separates the domain model from the database. (A mapper is a bidirectional insulation package.) The mapper package provides two-way insulation, and the domain model and database are independently changed. As a result, you can often find this style in a more complex OO model. Of course, if you think what happens when you have data, you will find that this picture is not very correct. How do you get some data from a module in the domain model needs to get some data from the database? It cannot request a map because if it can, it will cause a dependence from the domain model to the mapper, resulting in a loop. In order to solve this problem, I need different kinds of dependence.

So far, I have discussed a piece of code using other code. However, there is another dependency ---- interface and its implementation. Implementation is dependent on the interface, and it is not true. In particular, the caller of any interface is only dependent on the interface, even a separate module implements it.

Figure 2 depicts this idea. The domain model relies on the interface instead of implementation. The domain model left some mapped to achieve uncomfortable, but only changes in the interface can lead to changes in the domain model.

In this case, there are some separated packages, but it is not required. Figure 3 illustrates a storage package in the domain model, implemented by a storage implementation in the mapper. In this case, the domain model defines the map. In short, the domain package can be worked with any mapper that is selected to implement the storage interface.

Defines an interface in another module of one module for implementing a basic breaking dependence and reduced coupling. This practice has a lot of forms, the most basic is the callback (Callback) in this situation, one caller is requested to provide a reference to a function with a specific mark, which will be called for a while. One of the usual examples in the Java world is Listener. Because Listener is a class, they are more white and easy to understand, making the situation clearer.

Another example is a module that defines them to pass, and others can react. You can consider the interface that usually follows the event as a listening module. The caller of the callback function, the definition of the monitoring module, and the manufacturer of the event don't know which module is actually called, so there is no dependence here.

image 3:

I think it is missing an end because I am talking about the word like "good dependence". I am hard to provide a good guide to try to define a collection of well-controlled relying. Of course, it is about reducing the amount of coupling, but this is not all things. It is also important to rely on the direction and the way they point to avoid cycles. And, I treat all dependencies, regardless of the width of the interface. It is more important than fearing that you are more important.

The basic law I have contrasted is to discover my high-level dependence and understand them, separation interfaces and achievements to break the dependence of I don't want. Like research on many designs, this looks very imperfect. However, I have already felt very helpful - the end, I have to say.

转载请注明原文地址:https://www.9cbs.com/read-5203.html

New Post(0)