The Beauty of Design Patterns 52-Facade Pattern: How to design a reasonable interface granularity to take into account the ease of use and versatility of the interface?

52 | Facade mode: How to design a reasonable interface granularity to take into account the ease of use and versatility of the interface?

We have learned the proxy mode, bridge mode, decorator mode, adapter mode, these four structural design modes. Today, let's learn a new structural model: the facade model. The principle and implementation of the facade mode are very simple, and the application scenarios are relatively clear. It is mainly used in interface design.

If your usual work involves interface development, have you encountered any problems with interface granularity?

In order to ensure the reusability (or versatility) of the interface, we need to design the interface as fine-grained as possible, with a single responsibility. However, if the granularity of the interface is too small, when the user of the interface develops a business function, it will result in the need to call n more fine-grained interfaces to complete. The caller will definitely complain that the interface is not easy to use.

On the contrary, if the granularity of the interface is designed too large, an interface returns n more data and needs to do more than n things, the interface will not be universal enough and the reusability will not be good. The interface cannot be reused, so we need to develop different interfaces to meet the business needs of different callers, which will lead to infinite expansion of the interface of the system.

So how to solve the contradiction between interface reusability (universality) and ease of use? Through today's study of the facade model, I think you will have the answer in your heart. Without further ado, let's officially start today's study!

The principle and realization of facade pattern

Facade mode, also called appearance mode, the full English name is Facade Design Pattern. In the book "Design Patterns" by GoF, the facade pattern is defined as follows:

Provide a unified interface to a set of interfaces in a subsystem. Facade Pattern defines a higher-level interface that makes the subsystem easier to use.

Translated into Chinese is: the facade mode provides a set of unified interfaces for the subsystem, and defines a set of high-level interfaces to make the subsystem easier to use.

This definition is very concise, I will explain further.

Suppose there is a system A that provides four interfaces a, b, c, and d. System B needs to call interfaces a, b, and d of system A to complete a certain business function. Using the facade mode, we provide a facade interface x that wraps the calls of a, b, and d interfaces for direct use by system B.

I don’t know if you will have such a question. Let system B directly call a, b, and d. It doesn’t feel like a big problem. Why do you need to provide an interface x that wraps a, b, and d? Regarding this issue, I will explain it through a specific example.

Suppose the system A we just mentioned is a backend server, and system B is the App client. The App client obtains data through the interface provided by the backend server. We know that the communication between the App and the server is through the mobile network, and the network communication takes a lot of time. In order to improve the response speed of the App, we should minimize the number of network communications between the App and the server.

Suppose, to complete a certain business function (such as displaying information on a certain page), it is necessary to call the three interfaces a, b, and d "in sequence". Due to the characteristics of its own business, it does not support calling these three interfaces concurrently.

If we now find that the response speed of the App client is relatively slow, after investigation, we find that it is because too many interfaces call too much network communication. In response to this situation, we can use the facade mode to let the back-end server provide an interface x that wraps the three interface calls of a, b, and d. The App client calls the interface x once to obtain all the desired data, reducing the number of network communications from 3 times to 1 time, and improving the response speed of the App.

The example given here is just one of the intentions of applying the facade pattern, which is to solve performance problems. In fact, in different application scenarios, the intention of using the facade pattern is also different. Next, let's take a look at the various application scenarios of the facade mode.

Examples of application scenarios of the facade mode

In the definition given by GoF, it is mentioned that "the facade pattern makes the subsystem easier to use". In fact, in addition to solving the problem of usability, it can also solve many other problems. Regarding this point, I have summarized and listed 3 commonly used application scenarios. You can refer to them and learn from them in your own projects.

In addition, I would like to emphasize that the "subsystem (subsystem)" in the definition of the facade pattern can also be understood in many ways. It can be either a complete system or more fine-grained classes or modules. This point will also be reflected in the explanation below.

1. Solve the usability problem

The facade pattern can be used to encapsulate the underlying implementation of the system, hide the complexity of the system, and provide a set of simpler, easier-to-use, higher-level interfaces. For example, the Linux system call function can be regarded as a "facade". It is a set of "special" programming interfaces exposed to developers by the Linux operating system, which encapsulates the underlying more basic Linux kernel calls. For another example, the Linux Shell command can actually be regarded as a facade mode application. It continues to encapsulate system calls, providing more friendly and simple commands, allowing us to interact with the operating system directly by executing commands.

As we have said many times before, many design principles, ideas, and models are interlinked, and they are expressions of the same principle from different angles. In fact, from the perspective of hiding the complexity of implementation and providing an easier-to-use interface, the facade pattern is somewhat similar to Dimit's law (the principle of least knowledge) and the principle of interface isolation: two interactive systems only expose limited the necessary interface. In addition, the facade mode is somewhat similar to the design idea of ​​encapsulation and abstraction mentioned earlier, providing a more abstract interface and encapsulating the underlying implementation details.

2. Solve performance problems

Regarding the use of facade mode to solve performance problems, we have just talked about it. By replacing multiple interface calls with a facade interface call, we reduce network communication costs and improve the response speed of App clients. So, on this point, I will not give any examples. Let's discuss such a question: From the perspective of code implementation, how to organize facade interfaces and non-facade interfaces?

If there are not many facade interfaces, we can put them together with non-facade interfaces without special marking, just use them as ordinary interfaces. If there are many facade interfaces, we can re-abstract another layer on top of the existing interfaces, and place the facade interfaces specifically to distinguish them from the original interface layer in terms of class and package naming. If there are too many facade interfaces, and many of them span multiple subsystems, we can put the facade interfaces into a new subsystem.

3. Solve distributed transaction problems

Regarding the use of facade mode to solve distributed transaction problems, let's explain it through an example.

In a financial system, there are two business domain models, user and wallet. These two business domain models both expose a series of interfaces, such as interfaces for adding, deleting, modifying and checking users, and interfaces for adding, deleting, modifying and checking wallets. Suppose there is such a business scenario: when a user registers, we will not only create a user (in the User table of the database), but also create a wallet for the user (in the Wallet table of the database).

For such a simple business requirement, we can complete it by sequentially calling the user creation interface and wallet creation interface. However, user registration needs to support transactions, that is, the two operations of creating a user and a wallet either succeed or both fail, and one cannot succeed and the other fail.

It is difficult to support two interface calls to be executed in one transaction, which involves distributed transaction issues. Although we can solve it by introducing a distributed transaction framework or an after-event compensation mechanism, the code implementation is more complicated. The simplest solution is to use the database transaction or the transaction provided by the Spring framework (if it is Java language), and execute the two SQL operations of creating a user and creating a wallet in one transaction. This requires two SQL operations to be completed in one interface. Therefore, we can learn from the idea of ​​the facade pattern and design a new interface that wraps these two operations, and let the new interface execute two SQL operations in one transaction.

key review

Well, that's all for today's content. Let's summarize and review the content you need to master.

We know that the "communication" between classes, modules, and systems is generally done through interface calls. The quality of the interface design directly affects whether the classes, modules, and systems are easy to use. Therefore, we have to spend more time on interface design. I often say that completing the interface design is equivalent to completing half of the development task. As long as the interface is well designed, the code is not much worse.

If the interface granularity is designed too large, it is not good if it is too small. If it is too large, the interface will not be reusable, and if it is too small, the interface will not be easy to use. In actual development, the reusability and ease of use of the interface require a "delicate" trade-off. In response to this problem, one of my basic principles is to keep the reusability of the interface as much as possible, but for special cases, it is allowed to provide redundant facade interfaces to provide easier-to-use interfaces .

In addition to solving the problem of interface ease of use, the facade mode also talked about two other application scenarios today, using it to solve performance problems and distributed transaction problems.

class disscussion

  1. The common point of the adapter mode and the facade mode is to adapt the unusable interface to the easy-to-use interface. Can you try to summarize the difference between them?
  2. In your past project development, have you encountered unreasonable interface requirements? Or, have you ever encountered a very difficult interface? You can leave a message to "tucao".

Welcome to leave a message and share with me. If you gain something, you are welcome to share this article with your friends.

Guess you like

Origin blog.csdn.net/fegus/article/details/130498787