preface

With the rapid development of the Internet, the company’s project development cycle is constantly shortened. Faced with various demands, it is difficult for each end to quickly respond to various demands and improve efficiency by using the original docking method. As a result, we had to rework the docking specifications and develop the logic to get the project online quickly.

Our goal

  • Minimize communication costs, have the fewest meetings, and do the most things.

  • Spend a minimum of time writing documentation and make sure 90% of the developers understand everything.

  • You can understand the interface logic without looking at the documentation.

  • Don’t write code repeatedly

  • Write as readable code as possible

What we did

  • The front and rear ends are separated

  • Android, ios, and Web share a set of interfaces

  • Unified interface specification (POST, PUT, GET, Patch, delete)

  • Unified debugging tools

  • Interface documentation is unified

Before us

The interface looks like this:



The client request looks like this:

  • … /A project/module 1/getProducts? Id = 1 & 2 & b = a = c = 3 & 4 & d = 5…………………

  • A ===== B (carrying N variables) ==== C (carrying M variables, including I variables of A) ——- N >4 frequently

  • Most requests are POST, I don’t give a shit what put, patch, and DELETE are.

  • Regarding the use of JSON for interface input parameters, it all depends on the development mood.

The output parameter looks like this:

{“message”:”success”,”code”:0,”data”: details}

In the data array may be [{” a “:” 1 “, “b” : “1”}, {” a “:” 1 “, “b” : “1”}, {” a “:” 1 “, “b” : “1”}, {” a “:” 1 “, “b” : “1”}] even used the next page will not use the id, but spread in all fields. Interface A, return product for product; If good is used in interface B, multiple interfaces may be inconsistent.

Client docking looks like this:

  • Android, ios one set; Part of the interface with a set; Html5 end a set.

  • The client and the background are in constant communication

The interface documentation looks like this

  • swagger

  • Ali’s rap

  • Word document

  • other

Of course, I think swagger and RAP magic tools are very powerful and can realize various functional logic, but considering the lack of mastery and high complexity of developers, it is difficult to improve efficiency, I decided not to use these two magic tools in the early stage.

The back end looks like this

… /A project/module 1/getProducts —- interface… /A project/module 1/ products.html —- page… /A Project/module 1/ products.js —- Static resources

Interface and static resources entangled in a piece, after all, many pages may be a developer at the same time to develop the front end, back end, the drawback here is, only need to know their logic, a lot of temporary coping, the scheme is not elegant, others are also difficult to understand. Once the colleague is gone, much unexplained logic is left to posterity.

And so on…………………

refactoring

Let’s get down to business and talk about how I reformulated the process in the face of all these problems

Database conventions

All tables in the convention database must contain a primary key field named ID. You might say, well, wouldn’t every table normally have an ID primary key in it? However, due to the lack of rigorous development in our project, some tables have no id primary key, or no primary key for ID. Here we use distributed globally unique codes as ids.

API outgoing parameter convention

If all outgoing arguments contain a list and this list is used by other requests, all objects in the list must contain unique ids.

The participation agreement

The token authentication protocol adopts uniform input parameter mode, and the backend uses AOP aspect programming to identify user identity. All other parameters are JSON.

Resultfull Indicates the interface convention

  • GET: corresponding Retrieve operation (query operation)
  • POST: corresponds to the Create operation
  • DELETE: indicates the DELETE operation
  • PUT: indicates the Update operation
  • PATCH: indicates the Update operation

First we choose a plural noun, such as product

Post method

Add a “XXX” for example… /products adds a new product parameter json as follows:

{
    "name":"I am a new product"."price": 100,"kind":"My category"."pic":[a set of images], // and so on and so on}Copy the code

Java code Control layer

    @ResponseBody
    @RequestMapping(value = "/A project /B module /products", method = {RequestMethod.POST})
    public ResultObject getProducts() {// concrete logic. }Copy the code

Put method

Update a XXX record such as… /products/ 111111111111 add parameter json as follows:

{
    "name":"I am a new product"."price": 100,"kind":"My category"."pic":[a set of images], // and so on and so on}Copy the code

Update a record with id 111111111111

Java code Control layer

    @ResponseBody
    @RequestMapping(value = "/A project /B module /{id}", method = {RequestMethod.PUT})
    public ResultObject putProducts(@PathVariable(value = "id") String id) {// Specific logic. }Copy the code

The get method

Get all XXX… /products means get all the products because there is pagination, so we add? page=1&pageSize=50

We’ve agreed that all plural nouns will return a list, and that each list object will have a unique ID with a field id.

Such as

{
    "data": {"list": [{"id":"The only id"."Many other fields":""}, {"id":"The only id"."Many other fields":""}]."page":1, other fields},"code": 0."message":"Success"
}
Copy the code

… /products/{id} get a specific product (must be more detailed than the list)

For example, a specific product contains a list, such as the recommended list of the product, then:…… /products/{id}/recommendations

Assuming that instead of a list, it contains objects such as product commission information, then:… /products/{id}/Commission

Here we determine whether an object or a list is a plural noun.

Java code Control layer

    @ResponseBody
    @RequestMapping(value = "/A project /B module /{id}", method = {RequestMethod.GET})
    public ResultObject putProducts(@PathVariable(value = "id") String id) {// Specific logic. }Copy the code

Patch method

Updated the YYY information about XXX products

Input parameters are a subset of the input parameters of the POST method, as all parameters support update will show, not all variables are supported

… /products/{id}

{
    "name":"I am a new product"."price":100, // Some variables}Copy the code

Java code Control layer

    @ResponseBody
    @RequestMapping(value = "/A project /B module /{id}", method = {RequestMethod.PATCH})
    public ResultObject putProducts(@PathVariable(value = "id") String id) {// Specific logic. }Copy the code

The delete method

Delete XXX records…… /products/11111

Delete product 11111.

Java code Control layer

    @ResponseBody
    @RequestMapping(value = "/A project /B module /{id}", method = {RequestMethod.DELETE})
    public ResultObject putProducts(@PathVariable(value = "id") String id) {// Specific logic. }Copy the code

Other instructions

We use verbs as little as possible, but there are some actions that require verbs, like logging in. As for the version number, we are going to add /v1/ after the module.

Access agreement

The server determines whether the user role has the permission to execute certain logic.

Front and rear end separation conventions

The back end mainly develops the interface, no longer participates in the page development, or the hybrid JSP page development, uniformly returns in the form of the interface, and the front end renders the data and processing logic through JS.

A common interface

Web, Android, and ios use a unified interface, and do not open additional interfaces because of special requirements of any party.

Use the unified DAO layer generation tool

Based on Mybatis – Generator, it is transformed into DAO layer and part of Service layer suitable for our project for internal maintenance and common use.

Use Postman as interface documentation and debugging tool

Although rap and Swagger introduced above are especially awesome interface artifacts, we still choose Postman. Developers will store the interface name, description, input parameter, output parameter, and various output parameter examples, so that developers can directly see the interface meaning.

We recommend the use of browser plug-in, here to 360 speed browser as an example. Plug-in download address:

https://download.csdn.net/download/qq273681448/10033456

Open the 360 browser extension center, check the Developer mode, and then click load the decompressed extension, select the directory after the decompressed package, and finally click Run.

The output parameter comments and interface description are written in tests:

/* Here is the interface description and the meaning of each input and output parameter. * /Copy the code

Interfaces are divided into folders by module:

The arguments:

Examples of output parameters:

Normal request:

Developers can directly see the interface example to develop, while developers can call it once and save it as a Postman file. In order to speed up the launch, we allow the code (including comments) of entity class variable definition in Java to be copied and pasted directly.

Static resource caching, such as js

In the short term, my request is to reduce changes to the JS file, and if there are changes, be sure to change the version number. So how to reduce the modification, our approach is to write part of JS in HTML, anyway, before and after the end of the separation, the biggest refresh CDN node cache, after all, most browsers will not take the initiative to cache HTML files (most browsers will cache JS files).

Unified JS request framework

Here we use the Angular JS request framework because we are familiar with AngularJS internally. Wrapped requests can automatically pop up error requests and override error callbacks.

The effect of

At the moment, we clients see interfaces and can probably guess what they mean, as well as a string of interfaces, for example

… /classes

You can see that it is the interface to get the class list,

Guess what… /classes/id get Get class details with id = id…… /classes/id patch Modify class information…… /classes/id delete Delete class information

Patch is a subset of POST. Put =patch and DELETE have no input parameters.

And enter the meaning, directly open postman can directly view the meaning of each field, and can real-time access to the development environment data (non-developer computer), here we use multiple environments, details can be understood:

The use of unified packaging of the front-end JS request framework also speeds up the development schedule, without building wheels.

Developers, general code development written, using Postman self-test, test completed, interface documentation is also written. Testers who want to see interface documentation can also use Postman to import it.

At this point, our communication costs have been reduced by more than half, and the rest of the meeting is either breaking down requirements by UI or building by UI.

conclusion

After some twists and turns, the development progress is finally a little faster, but also to a certain extent to reach the effect of fast online project. Everyone has their own opinions about restful apis, and as long as the internal conventions are clear and as little communication as possible, I think that’s a good understanding. As for the interface tool, many people may say why not before, I think it will be used in the future, it is best to achieve plug-in automatic generation API, but the Java development annotation requirements are more strict, take your time, after all, we still have a lot of road to go.