Airbnb senior program Yuan: API talk

Lei Feng network: According to the author Zhu Xi, Airbnb senior program Yuan. Authorized by Lei Feng Network (search "Lei Feng Network" public number concerned) release.

Having experienced a small company growing into a big company, you may have encountered such a situation: When you see a line of code, I think it is not worth considering. So you use git blame to find its owner, and found that the original author is actually a CTO or VP or Director that has not written code.

Then by chance, you chat with him about this, and he will be proud to tell you a story: "Oh, then, we must make this product feature one day. Then I was a programmer. Maybe Tom is also. One day, this is the best plan that can be made at the time." After that, he fell into a whirlwind of good times...

You may have heard stories like this: One day, your CTO had a whim and felt that he could actually write some code. So gorgeous submitted a piece of code. Everyone saw it and was very excited, so many people began to give comments on the PR. Your CTO: Look, dozens of comments... Now this code is going to be written like this? So troublesome? So he said to an engineer, "You put down the comments address, and then merge." And then happily do it yourself.

Oh, it's a bit off topic.

In fact, these two stories, to say is: a company's early code for various historical reasons, may not be so perfect, but at a specific time, that is the best solution. As time passes, features continue to stack up and the code architecture continues to be optimized. The system may experience some iterative processes that become complicated and simplified. Then one day, the code would be completely different, and the original owner did not know his original work.

This is especially true of the design and implementation of the API. A mature set of APIs are constantly evolving and iterating. There are very few APIs that are designed and implemented flawlessly from the very beginning. Let's talk about some of the APIs.

Let's start with the API's signiture. That is, which formats and parameters are supported by the API request and response.

First of all, anyone who has done API knows that an API used on the line wants to change its signiture. Usually, due to compatibility reasons, it is very painful to want to change later. Therefore, at the beginning of the design of the API signiture, it is necessary to repeatedly scrutinize and scrutinize it, trying to avoid changes after going online.

In addition to some basic RESTful principles, the definition of Signiture is often an abstraction of the business logic . The business logic of a system may be intricate, so API design should be done in the most compact and intuitive format to support all requirements. This is often the opposite of the API design. Sometimes we seem to have to add an interface that violates the design in order to support a certain function; sometimes we seem to have to give up direct support for certain functions in order to guarantee the API absolute specification, so the function can only be called by iteration. Or client-side preprocessing to achieve.

This design trade-off, usually only list all possible solutions, from simple design to complex design, and then by analyzing the frequency of various use cases and the complexity of using a certain design, from the actual system requirements Start with the simplest and most direct support possible for commonly used features and, to some extent, “sacrifice” some features that are rarely used. Repeatedly scrutinize the system scene to obtain a reasonable compromise as much as possible.

In this eclectic process, always ensure that the following basic principles are met , for example:

Guaranteed API 100% RESTful. The core of RESTful is everything for a "resource". All actions and interfaces should be CRUD operations on the corresponding resource. If this model is departed from this model, is it necessary to think twice? There are no other programs to avoid.

Both the request and the response should be structured as much as possible. If it is a hash, pass a hash (don't pass hash.to_string). The serialization / deserialization of the API will automatically serialize it to a string. Calls between multiple language APIs, such as Ruby, Java, and C, are usually done in serialization / deserialization.

Authentication and Security considerations should always be the top priority. Ensure that only specific interfaces and permissions are exposed for specific users. Authentication may use certificates and whitelists, or it may be handled through authentication tokens generated by the user's login credential, or session/cookies. In addition, all logging of the API layer should be guaranteed not to log any sensitive information.

The API itself should be client-independent. In other words, an API handles the request as much as possible to avoid consideration of whether the client is mobile or web. Client related response formats should not be implemented in the API. All client-independent calculations and processing should be handled as uniformly as possible on the server side. To improve performance and consistency.

Make the API as Idempotent (Idempotent) as much as possible. There are several different levels of meaning. To cite a few examples: Is it possible to guarantee the same result by sending the same request and sending it twice? Is it possible to guarantee the same result if the retransmission after the Request fails and the first transmission? Of course, the specific approach still depends on the application scenario.

In addition, each language already provides a good API framework. Learn more about these frameworks before designing.

Why do you know more about it? If you are a small team, you may want to choose a suitable framework to start with, and make appropriate adjustments. This is better than building a wheel from scratch. But in reality, many companies will eventually have their own customized solutions due to the special needs of their own business logic.

Assessing a framework can be considered from the following aspects:

Uniform control of access rights

Automatic test support

Support for formatting of requests and responses, and support for serialization and deseialization

Support for logging and logging filtering

Support for automatic document generation

The actual implementation of the architecture and performance considerations

Finally, how to deal with some of the opposites in the design.

In addition to the occasional opposition between interface simplicity and functionality, as mentioned above, there are many other opposing and trade-offs in API design and implementation.

1, freedom is always relative.

It is as if in a group, if there were no rules and freedom of complete behavior, problems would arise. Small groups are okay, but for a large group, someone will be free to be injured by others.

The same is true for writing software. In a small startup, how the API is designed and how the code is written, a few people negotiate and reach consensus, and do not need so many rules and regulations. A company with a large number of people collaborating on code, everyone's freedom will lead to the ultimate conflict and even problems. Therefore, many large companies will develop best practices for some APIs, and must force the design and implementation to follow certain patterns. Although some rules are justified, it is not saying that it cannot do so. Many times, because of this reason, there are many limitations in our API design. On the surface, it seems to bring unnecessary difficulties to the design, but careful consideration, from the perspective of normative code consistency, there are still great benefits .

2. What is the current design? Or design for the future?

One of the common situations in API design is that there is a system function that is not used by anyone at the moment, but someone has said: "This situation we should support in the future." As I said before, it is very difficult to change the API after going online. In the early stages of design, we must consider the future development as much as possible. However, these “possible” application scenarios are unclear because of the details of the requirements and the frequency of use, and are most likely to cause over-design of the system.

I remember hearing an argument. To recap: think about future, design with flexibility, but only implement for production. The Chinese probably means that: To consider future scenarios, there is room for design, but only for the functions that production really does.

3, Maintainability vs Efficiency

There are often some packaging and abstractions in the design and implementation. In some special cases, the process of encapsulation and re-disassembly may affect the speed of the API to a certain extent, or there may be conflicts between optimization of code quality and optimization of performance. This is difficult to generalize, but it depends on whether the specific code is in Critical Path or is it a code that requires a lot of people to collaborate. The final choice depends on the situation.

4, AOP vs non-AOP

AOP programming itself is a very controversial topic. In summary, AOP's philosophy is to separate cross-cutting concerns from the main focus and is the core concept of side-oriented programming. Separation of concerns makes it possible to isolate the code of a particular domain from the business logic. The code of the business logic no longer contains calls for specific domain issues. The relationship between the business logic and problems in a specific domain is encapsulated and maintained on the side. Distributed in the entire application changes can be well managed.

Because there are many common concerns in the design and implementation of APIs, such as Logging, Authentication, Parsing, Monitoring, etc., APIs have become a very natural application area of ​​AOP. Using AOP's API design inherits the advantages of AOP, such as: code reuse, regularity, and programmers can focus on the system's core business logic. However, it naturally inherits the problems inherent in AOP, such as profiling and debugging of the code; the requirements of the programmer experience and the requirements for mutual cooperation (such as changing a certain function may affect other functions).

This consideration is not the same for different systems and languages, so it does not involve too much detail. Only write some of the sentiments learned in the API and write it out. What do you have to say?

Topic: from Pinterest

Lei Feng Net Note: Reprint please contact the author's authorization, and be sure to retain the source and the author, not to delete the content.

Posted on