How to Control layers in system design
One of the core tasks of design: hierarchical control
For software, layers are what people love and hate. Many problems are solved by adding layers, but other problems are also imported due to layers. Let's look at several examples respectively.
Example 1: in many cases, we do not want the final application to be bound to a specific platform, such as Windows. To achieve this cross-platform goal, you need to add an intermediate layer between the OS and the application, which is responsible for shielding the differences between different OS. In fact, Java virtual machines and so on follow this route.
Example 2: When saving configuration information using an XML file, we do not want the XML structure to be everywhere in the entire program. For example, we now save the default directory under the configuration/outputfolder node, but in the future it is likely that the node will change to configuration/outputfolder/save. To split the association with the XML structure, we need to add a new abstraction layer to characterize the XML file, and then obtain the default storage directory through the getsavefolder () method.
When a problem is solved by adding layers, new problems also occur. Hiding a layer of gauze in front of you can prevent the eyes from being damaged by sand, but if you mask 10 layers, more serious consequences will occur-you cannot see the road.
From an understandable perspective, the specific code can be understood only after all the layers involved in a function and the various possibilities of the variables associated with it are clarified. This is especially true in troubleshooting. Let's look at an example:
When using C ++ to create a collection class, we may want to customize the memory usage of the Collection class. Sometimes we may want to reserve a piece of memory in advance, and then perform secondary allocation on this piece of memory to store various small objects. Sometimes we may want to directly allocate space on the disk to store the objects in the Collection class. In order to achieve the above purpose, we can establish classes such as allocator to create an abstraction layer. When creating a collection class, you can specify different Allocator methods to control memory usage.
This should be a good design method, which is done in the C ++ standard template library.
Next, let's take a look at the case where an error occurs. We may want to keep swallow copy of the objects in the Collection class. Therefore, the copy constructor and value assignment function of the class are overloaded. However, when the object is put into the collection class, I don't know why it always fails.
At this time, the program has no problems in logic, so it cannot be solved simply by thinking about it. For troubleshooting, we can only start the debugger. During the debugging process, we usually cannot check whether the problem is related to allocator. Therefore, to locate the problem, we also need to analyze allocator. The overhead of this analysis is actually the cost of adding allocator.
Through the above example, we can roughly understand the power of the double-edged sword.
Through layers, we can make the software more flexible and abstract. However, layers also split the information necessary to achieve a certain function, increasing complexity. Therefore, the number of levels is often not a right or wrong problem, but a level problem. What level is appropriate? It is determined by the person on the scene.
Someone once said this sentence for our reference. He said: If you know what you are doing, three layers are sufficient. If you do not know what you are doing, then Layer 7 is useless. I personally agree with this point of view. Unless in special circumstances, we should try to control the layers on the left or right, otherwise we would rather sacrifice a little abstraction.
There are two main issues related to hierarchies: the number of hierarchies and the consistency of hierarchies. If the number of layers is an appropriate issue, level consistency is a non-problem. What is embodied in a certain level should be hierarchical consistency.
This is similar to the hierarchy problem discussed above.
For example, if there is a cat class, then the interface of this class can have the returned cat color and cat type. These attributes are at an abstract level. However, if an interface returns the number of cats, most of the time it is strange.
We feel that the strange essence is that the abstraction layer is inconsistent. The color and type attributes belong to a specific cat, and the number belongs to the set of cats. This inconsistency of abstract layers is actually a major culprit in increasing coupling.
Unfortunately, this is another place that depends on individual skills. Currently, there is no way to automatically determine whether the abstract level is appropriate.
How to Control layers in system design