How to design an interface well? | JD Cloud technical team

How to design an interface? It is a topic that is often asked during our daily development or interviews.

Many people think that this is not CRUD, and it is fine if it can be realized. It is not difficult to implement simply, but it is not a simple matter to be easy to use, easy to expand, and easy to maintain. Here we do not emphasize the principles or design methods of some interface design, but simply discuss how to design a good interface.

1. Naming convention

We write code not only to achieve current functions, but also to facilitate subsequent maintenance. The so-called maintenance means that the code is not only written for yourself, but also for others. Therefore, the interface definition should be clear and easy to understand, and the naming convention should be standardized.

In addition to naming conventions for interfaces, methods, and access parameters, attention should also be paid to code specification issues. Most of the friends who come into contact with various bad code smells at the beginning will think that these specifications are redundant and annoying, but in fact, these good coding habits are the basis for everyone to develop according to the basic specifications, easy to read and easy to maintain.

When defining the interface, please also pay attention to the singleness of the interface function. In fact, this is also some ideas of microservices, the single responsibility of the interface function, clear and simple. For example, the login interface, what it does is to verify the account name and password; the interfaces related to order service, point service, and product information are all divided.

2. Parameter verification

Input and output parameter verification is a basic quality that every programmer must have. The interface you design must first verify the parameters. For example, whether the input parameter is allowed to be empty, the length requirement of the input parameter, whether the input parameter is within the enumeration value range, etc. In daily development, many low-level bugs are caused by not checking parameters.

When referring to parameters, you must mention the interface status and error code. Whether it is failure or success, a complete interface should tell the caller to return information. If the interface fails, what is the specific reason for the failure, which requires a clear definition of the error code and the corresponding description. At the same time, try to encapsulate the error information as much as possible, and do not directly throw out the server-side exception information.

3. Monitoring/performance

How to judge the performance of an interface requires monitoring, which is very important for the server to monitor interface performance and abnormal alarms. The number of calls, availability rate, TP99, TP999 and other monitoring indicators, and the extremely important core interface also need to be subdivided into second-level monitoring for identification.

The performance of an interface does not only depend on its own business logic, but external remote calls are also an important part of consuming performance. If you call third-party interfaces or remote services, you need to consider exceptions and timeouts. If there is an exception, how to deal with it, whether to retry or treat it as a failure or an alarm. If retrying, how many times? This requires thinking about this issue from a business perspective. These measures also directly affect the current interface performance.

A powerful tool to improve performance can also consider caching. If the cache is used well, it can carry more requests, improve query efficiency, and reduce the pressure on the database. However, the use of cache needs to consider cache and database consistency guarantees, cache breakdown and other issues.

4. Log

The key code of the interface must be escorted by logs. First of all, the log level needs to be used reasonably: error > warn > info > debug.

Secondly, what does the log information include, such as the input parameter printing before the core code block call, the exception capture log after the interface call, etc. It should be noted that if the log involves relatively large JSON rich text, please use log.isInfoEnable(). In the case of high concurrency and complex log information splicing, using this standard method to output the log can save a lot of time. System overhead. In addition, if the process of constructing log information requires a lot of string operations, it is recommended to use StringBuilder to complete string splicing.

5. Abnormal/Timeout

Implementing a good interface is inseparable from elegant exception handling. For example, in the order of exception matching, specific exceptions are captured first; when using streams, remember to use finally to close stream resources;

For runtime errors, such as data boundary crossing and null pointers also appear in daily development, there is still one item that should be judged and verified.

Timeout issues also often render interfaces unavailable. Setting a reasonable timeout is also protecting your interface. Timeout is generally used in conjunction with retry, but please note that when setting the timeout period, you need to fully consider the timeout period set by your upstream and downstream. For example, a request is the first to access your upstream, and the timeout period set by your upstream is 500ms, and the upstream calls your interface, but the timeout period you set is 2000ms, which is actually an invalid timeout period.

There are also some methods for interface time-consuming optimization, such as changing remote serial calls to parallel calls, changing single calls to batch calls, and so on. But please be careful not to call remotely in loops or transactions.

6. Asynchronous

In some scenarios of the interface, it is more reasonable to use asynchrony. To give a simple example, for some operation operation interfaces, it is often necessary to record the operation log of the corresponding operation, recording who operated what object at what time, so as to track the "incident scene". However, recording the operation log is not in the main process of the interface, and recording the success or failure of the operation log should not affect the execution of the normal main process. At this time, asynchronous decoupling with message queues and other methods should be considered.

7. Notes

Arguably, comments are also an important part of good code. Some people have always believed in show me the code, but they don't want to write a line of comments, thinking it is unnecessary. But you can't guarantee that the code logic is always clear and efficient. If it is more complicated, it is recommended to write the comments clearly, which is very important for subsequent maintenance and clear code logic.

8. Downgrade/current limit

Today's request calls are basically distributed call links. When a basic service in a distributed system is unavailable, the entire system will eventually be unavailable. Therefore, when there is a problem with the downstream system or its own service, you must consider downgrading. If it is more complete, you can also consider fusing.

At the same time, for high-concurrency traffic peak interfaces, current limiting must be considered to deal with challenges beyond the system's carrying capacity. Throttle measures can also limit crawlers, protect the system, and discard redundant requests.

9. Security

The security mentioned here is too broad. For example, linear security, many people turn to HashMap, because it is non-linear security, you can consider ConcurrentHashMap under high concurrency.

If the front end repeats the request, how does your logic handle it? Whether to consider interface deduplication processing (sometimes anti-brush processing). To be simple, you can use redis anti-heavy processing to filter the same request within a certain time interval. Of course, for some interfaces with low concurrency, such as transfer interfaces, it is recommended to use database primary keys or unique indexes.

If there is repeated consumption in the message queue, how do you control your business logic? Whether to consider idempotence check.

Anti-duplication is mainly to avoid duplicate data, just intercept duplicate requests. In addition to intercepting the processed requests, the idempotent design also requires the same result to be returned every time the same request. However, in many cases, their processing procedures and methods are similar.

There are also some other security considerations, such as read-write separation, granular control of code locks, data encryption, and so on.

10. Communication

Why should there be communication? And why put communication last? When encountering some technical difficulties, align the solution with the technical leader. In the process of realizing the requirements, if there is any problem, it is necessary to communicate with the product in time. It is necessary to align the interface with the client, and you must not come up and immerse yourself in defining the interface. In various scenarios, it is very important to learn to communicate. Effective and efficient communication will not only bring joy and smooth development, but also improve interpersonal relationships.

Well, the above is a small answer to the question "How to design an interface?" based on my own experience. If there are any deficiencies, please advise.

Author: JD Retail Li Zeyang

Source: Reprinted by JD Cloud developer community, please indicate the source

Microsoft's official announcement: Visual Studio for Mac retired The programming language created by the Chinese developer team: MoonBit (Moon Rabbit) Bjarne Stroustrup, the father of C++, shared life advice Linus also dislikes messy abbreviations, what TM is called "GenPD" Rust 1.72.0 released , the minimum supported version in the future is Windows 10 Wenxin Yiyan opens WordPress to the whole society and launches the "100-year plan" . : Crumb green language V1.0 officially released
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/u/4090830/blog/10104827