【效率專精系列】善用API統一描述語言提高RestAPI開發效率

團隊內部RestAPI開發採用設計驅動開發的模式,即便用API設計文檔解耦前端和後端的開發過程,雙方只在聯調與測試時耦合。在實際開發和與前端合做的過程當中,受限於衆多因素的影響,開發效率還有進一步提升的空間。本文的目的是優化工具鏈支持,減小一部分重複和枯燥的勞動。php

現狀梳理

先後端工做流

  1. 需求理解:先後端先理解產品思路、需求的詳細內容
  2. 敲定接口:後端出API設計文檔初稿,與前端面對面或者在線討論修正,接着後端(有時是前端)把API描述記錄到公司內部的API文檔庫(在線markdown編輯器,提供分級目錄的存儲功能,對如何描述API沒有必定的標準,所以描述格式不統一,因人而異1)。接着根據雙方工做的安排,約定聯調時間
  3. 獨立開發:雙方獨立開發(也有可能非徹底獨立開發,如須要對方的環境配合等;或者存在返工,如API設計發生變動等)
  4. 系統聯調:測試API基本功能和雙方系統的連通性
  5. 測試迴歸:開發或者QA編寫測試用例並測試業務流程

可優化方向

1. 減小文檔編寫時間

根據我的的開發經驗,後端編寫API設計文檔時常見的狀況有:若是是簡單的需求,API數量較少,後端直接經過內部即時通訊軟件和前端溝通;若是是複雜的需求,API數量較多,後端會先把API描述寫到本地臨時文檔(純文本、markdown、evernote等)或者內網(內部我的Wiki、git倉庫)中,而後把連接發給前端review或者直接面對面溝通。這樣的方式靈活,但存在一些問題,好比:html

  • 描述格式沒有標準。對於簡單的描述,文檔格式比較隨意,雙方基於約定和經驗理解和開發1;完備的描述,編寫文檔所需時間較長,而且細節複雜(須要考慮不一樣的HTTP請求類型、HTTP頭部信息、HTTP請求內容等),高質量地建立這份文檔自己就是件很是吃力的事,下游的抱怨聲不絕於耳。固然在合做開發中,文檔越完備,雙方的理解誤差就越少、開發產生的bug就越少,後期也更容易維護代碼、適應人員變動,可是編寫完備的文檔所須要的額外時間也不容忽視,沒有代碼產出的設計文檔可能不得已讓位於現實中總體開發時間的緊張。前端

    以開發「得到管理員帳戶下可用商戶」爲例。若是是簡單的描述,後端告知前端url爲 {host}/ajax/shop,返回的結構是 [{"shopId":int,"shopName":string}],有經驗的前端會自動判斷出 MethodGetContent-typeapplication/json,request不須要附帶參數,不須要對錯誤值作特殊處理;而若是是複雜的描述,後端通常會列出 API名稱、功能描述、調用方式、請求參數、請求示例、返回值、成功的返回結果示例、失敗的返回結果示例中的幾項,填充到已有的API模板中 2
  • 輸入效率不高。因爲開發的API模板缺少固定的標準,所以只能在例如Wiki、純文本編輯器、markdown編輯器中編寫,沒法獲得現代IDE中語法高亮、自動補全、錯誤提示等特性的支持,總體感受就像是在記事本中寫Java。java

    • 設計文檔中會規定API輸出的數據結構(通常爲json數組或者json對象),若是數據結構較爲複雜(好比包含有幾十個字段的POJO),要在設計文檔中書寫可讀性良好的數據結構須要更多的時間;若是數據結構中字段缺失或者可讀性差,則會影響前端的文檔理解和代碼開發。
    • 若是後端能提供樣例數據天然是最好的,由於後端最熟悉業務邏輯,產生的樣例數據比前端本身Mock的數據更好。可是複雜數據結構的樣例數據的編寫一樣很花時間。
> 舉例:需求要求開發一個新增優惠券API,其樣例數據只能由開發手動生成。若是是修改已有的API,要補充新的樣例數據,開發通常會登陸商戶平臺,打開優惠券頁面,在Chrome中實際操做一遍,抓包獲得request的body(json格式),在json格式化網站(如[json.cn](json.cn))美化後複製到API設計文檔中。![clipboard.png](/img/bVTWta)
  • 重複錄入。由於文檔庫功能羸弱,使用不便,因此開發通常先按本身的格式寫一份文檔,可是若是不直接把API錄入到公司文檔庫,則開發須要對一份API出兩份設計文檔。開發通常會開兩個窗口,左邊是API設計文檔的完成件,右邊是公司API文檔庫編輯頁面,而後把左邊格式各異的API描述文本轉換到右邊統一的markdown格式。git

    例如:想象一下從Wiki文檔的表格中一個個複製粘貼,再編輯成markdown格式文本是典型的成本大於收益的工做。
  • 文檔維護成本大。因爲文檔和代碼分開存放,因爲須要手動操做,所以文檔與代碼同步成本較高。隨着時間推移,不斷修改接口實現的時候都必須同步修改接口文檔,而文檔與代碼又處於兩個不一樣的媒介,除非有嚴格的管理機制,否則很容易致使不一致現象,並在業務總體交接、開發成員替換時使後來人付出較大的時間成本。github

    不一樣的存放形式的優缺點見仁見智,相似於Spring也有XML和JavaConfig兩種配置方式。

2. 減小聯調時間

缺乏樣例數據。因爲團隊內部前端通常不會全面的瞭解業務,後端提供的樣例數據每每比前端本身生成的Mock數據對業務需求的把握更準確。若是後端能在API設計文檔中提供樣例數據,一是若是前端沒有自動Mock工具的話,能節約前端生成Mock數據的時間;二是能在聯調前爲前端提早發現一些低級錯誤(好比具備業務特徵的一些默認值處理、空值處理、字段缺失等場景)。ajax

3. 減小部署時間

beta環境綁定了惟一的beta域名,所以在多分支並行開發時是稀缺資源,較大的項目在beta環境編譯和部署每每消耗不少等待和解決衝突的時間。若是在聯調中發現的問題較多,就須要屢次部署beta環境,時間成本十分可觀。spring

如何減小部署時間另外行文

尋找技術候選

總結起來,上面列出的問題大部分是因爲API描述標準不統一引發的,所以要用標準化的工廠代替散亂的手工生產。雖然平時開發的API具備Rest風格、對外網開放,只被企業本身的應用調用,不過廣泛的WebAPI開發流程仍是適用的。我在網上搜索一些功能較爲符合的RestAPI設計工具,將其大體分爲3類討論。
clipboard.pngjson

第一類:Swagger、Apiary、RAML

人和機器可讀的API描述標準,圍繞該語言有完善的工具鏈:通常有設計、編譯(即Codegen)、測試(有MockServer、自動Mock、本地直連等形式)、文檔(包括靜態文檔,如html和pdf;還有可交互文檔html+js)、合做(多人+多角色合做開發)這幾個模塊,各個標準都差很少。segmentfault

較爲學術性的表述:雖然Web API的實現正變得愈來愈普及,但在工具方面還缺少一些被普遍接受的標準,用以描述、發現,而且理解大量基於API的服務的意義。Web API之「元語言」有三個關鍵領域:API描述、API發現以及API檔案。所謂的API描述,指的是以一種讓人類與機器均可讀的形式對API進行描述,包括API的實現細節,例如資源與URL、表述格式(HTML、XML、JSON等等)、狀態碼以及輸入參數。
Swagger、Apiary、RAML的格式各自採起了一種略有不一樣的設計方式,但在本質上都提供了相同的基本特性:以多種不一樣級別的細節對Web API進行描述。

以Swagger23爲例,分爲5個部分(示例圖來自於RAML,不過功能都差很少)。
clipboard.png

  • Design:其標準爲OpenAPI(前身是Swagger API Spec),提供強大的在線編輯功能,包括語法高亮、錯誤提示、自動完成、實時預覽4,而且支持用戶以Json、Yaml格式撰寫5、導入、導出、轉換文檔。
  • Build:設計文檔能夠編譯成客戶端和服務端,支持的語言包括Java、NodeJS、C++等主流語言。其中Java服務器端使用流行的Spring Boot構建,生成的代碼包括定義的API接口、空實現方法的樣板代碼、業務POJO、配套的Swagger註解。值得注意的是,由自動生成的Swagger註解,能夠反向生成最初的API設計文檔
  • Test:可在本地服務器運行時使用本地測試功能;用戶也可使用SwaggerHub中提供收費的在線測試功能,主要有MockServer(Auto Mocking)、問題跟蹤(Issue Tracking
  • Document:能夠在線或離線(包括代碼編譯時和運行時)地生成靜態html、pdf等文檔;SwaggerHub能夠配合API版本,自動同步相應文檔的版本
  • ShareSwaggerHub提供團隊管理、聯調開發、文檔標註等多人合做開發的支持

再提一下Apiary和RAML。Apiary6使用API Blueprint標準,Apiary網站提供了在線編輯、實時預覽、Mock、可交互文檔、團隊合做、Github同步、流量追蹤等包含整個API生命週期的全部服務,固然這是收費產品,並且價格不菲;另外,用戶也能夠經過開源的命令行工具進行離線的API設計、文檔生成、發佈過程,並將其集成到本身的工做流中,這也是它的一大特色。RAML使用RAML1.0標準,沒有本身的可視化在線開發平臺,而是用官方或第三方的離線工具(如API Workbench系列)來代替,所以它也存在一些缺點,好比:工具更新不及時,某些Tool不支持最新的RAML1.0

第二類:Apidocjs

相似於Intellij Idea的生成JavaDoc功能,是一種註釋解析器,從C++、Java、Python代碼註釋中基於特定的關鍵字(如@param@return)生成API靜態文檔。因爲更像是先代碼實現後生成API文檔,因此不能算做是設計驅動的開發;另外apidocjs也缺少IDE支持。

第三類:Rap、eolinker

沒有公開的API設計語言,提供在線或離線、閉源或開源的可視化、一體化API開發平臺。這裏選擇中文的Rap、eolinker做爲表明。Rap是阿里的開源做品,也提供線上服務,核心功能是文檔編輯和自動Mock服務。eolinker是綜合的接口管理平臺,除了常見的功能,還提供接口商店、數據字典等適合創業團隊快速開發API的特性。在此不作進一步介紹。

如何選型?

選型邏輯

  1. 社區活躍、功能完善,應用成熟。
  2. 學習成本低、上手時間短。做爲業務開發,缺乏時間熟悉學習曲線陡峭的知識和工具。
  3. 功能較多地契合上述優化方向。
  4. 能補充現有工做流的不足,不作大範圍的代替。
  5. 要考慮測試環境處於內網形成的障礙。

初步分析

  1. rap、eolinker、swaggerHub、apiary提供了一整套API開發環境,取代了現有工做流。放棄。
  2. apidocjs缺少現代IDE特性支持,輸入效率較低。放棄。

進一步分析

Swagger2 API Blueprint RAML
Design 在線編輯、IntelliJ Idea插件 在線編輯、命令行、Sublime/Atom/Vim插件 API Workbench、Sublime/VS插件
Design文檔格式 yaml、json markdown yaml
Build支持 在線Build、IntelliJ Idea插件 / Maven插件
Codegen服務端框架 Spring Boot / JAX—RS
Test 運行時手動Mock、第三方工具 官方和第三方工具生成MockServer/Client 第三方工具和在線服務
Document Maven插件生成靜態文檔、在線或運行時生成可交互文檔,支持SpringMVC+註解形式 第三方工具 第三方工具
Share 在線、收費 在線、收費 離線、第三方工具

綜合考慮,最後選擇Swagger2。由於Swagger對現有的工做流侵入較少;工具較爲完整;與團隊使用的Spring MVC技術棧無縫集成,能夠減輕文檔工做量。Swagger2也有一些缺點,如:使用註解方式對代碼有侵入性。

用Swagger2優化現有工做流

  1. 減小文檔的編寫時間

    1. 若是後端先編寫獨立的API設計文檔,可利用Swagger在線編輯器或IDE插件的自動完成等特性;yaml格式統1、簡單易懂、表達能力強,較markdown冗餘字符更少。經過模仿官方Example很容易學習OpenAPI規定的關鍵字。
    2. 另外後端也能夠把API設計文檔直接經過註解的形式,標註在Controller類和相關方法上(以Spring MVCSpring Boot爲例),便可以經過Java反射在Maven Complie或運行時生成API設計文檔。Swagger有Intellij Idea的插件支持,Swagger註解則能利用現代Java IDE的特性,提升輸入效率;另外完善的註解也方便其餘開發人員進行後期維護,不須要在設計文檔和代碼實現中來回切換查看。此種方式至關於面向規約的開發模式,即先規定接口,再填充實現。
  2. 減小文檔的轉換時間:利用第三方工具實現從Swagger、API Blueprint、RAML格式的互相轉換,或者直接輸出爲html靜態文檔,方便整合到如今的工做流中。好比:API Blueprint的markdown格式能夠存儲到公司的API文檔庫,html靜態文檔能夠存儲到內部Wiki。
  3. 減小(可能的)開發時間:若是已有獨立的API設計文檔,在Swagger Editor中生成基於Maven + Spring Boot的服務端代碼,不過生成的POJO和Controller類的命名可能不太理想,須要本身調整。
  4. 減小聯調時間:後端能夠在設計文檔或註解中指定API或者POJO的Example數據,節約前端手動編寫Mock數據的時間。

附錄1:流程實例演示(腳手架爲Spring MVC

1. 標註相應的Swagger註解做爲API設計文檔

先創建RestController類、相應的API空方法、POJO做爲骨架。對應的API設計文檔見文末的Reference節。

@Api("Users")
@RestController
@RequestMapping(value = "/users")
public class UserController {
    @ApiOperation(value = "建立用戶", notes = "根據User對象建立用戶")
    @PostMapping
    public String postUser(@RequestBody User user) {
        return null;
    }
    @ApiOperation(value = "獲取用戶詳細信息", notes = "根據url的id來獲取用戶詳細信息")
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return null;
    }    
}
class User{
    private Long id;
    private String name;
    private String age;
    //getter,setter
}

2. 生成API設計文檔

生成的具體方式按照耗時長短排列爲:Maven Complie、Test Case、Server Runtime。可在Swagger Editor中預覽相應的可交互文檔。根據前端的反饋,修改Swagger註解,並把新的文檔存儲到內部Wiki或者API文檔庫(若是改動量大的話,利用Diff工具提升效率)。
clipboard.png

3. 在Swagger-UI提供的可視化頁面中完成自測

開發完成後啓動Server,Swagger-UI的訪問地址爲http://localhost:8080/swagger-ui.html

clipboard.png

4. 與前端聯調

爲了減小beta環境的衝突、加快部署速度,最好在本地開發環境聯調。

附錄2:Swagger配置與使用

【5分鐘指南】Swagger2環境配置與使用

附錄3:YAML格式的API描述文檔示例

swagger: '2.0'
info:
  description: Click Link Below for Help
  version: v1
  title: demo13
  termsOfService: 'http://www.github.com/kongchen/swagger-maven-plugin'
host: HOST
basePath: /s
tags:
  - name: Users
schemes:
  - http
paths:
  /users:
    post:
      tags:
        - Users
      summary: 建立用戶
      description: 根據User對象建立用戶
      operationId: postUser
      parameters:
        - in: body
          name: body
          required: false
          schema:
            $ref: '#/definitions/User'
      responses:
        '200':
          description: successful operation
          schema:
            type: string
  '/users/{id}':
    get:
      tags:
        - Users
      summary: 獲取用戶詳細信息
      description: 根據url的id來獲取用戶詳細信息
      operationId: getUser
      parameters:
        - name: 'id'
          in: path
          required: true
          type: integer
          format: int64
      responses:
        '200':
          description: successful operation
          schema:
            $ref: '#/definitions/User'
definitions:
  User:
    type: object
    properties:
      id:
        type: integer
        format: int64
      name:
        type: string
      age:
        type: string

Reference

  1. Swagger:Rest API的描述語言
  2. RAML vs. Swagger vs. API Blueprint
  3. Springfox Reference Documentation
  4. Swagger使用
  5. swagger-maven-plugin
  6. 經過Swagger進行API設計,與Tony Tam的一次對話
  7. API 設計: RAML、Swagger、Blueprint三者的比較
  8. API描述、發現與檔案入門
  9. Spring Boot中使用Swagger2構建強大的RESTful API文檔
  10. API Design And Documentation
  11. Swagger與其餘API文檔編寫工具對比

  1. 以「雲打印機設置」中的一個API爲例,簡單描述的典型。 clipboard.png
  2. 自定義API模板。 clipboard.png
  3. swagger的Design-Build-Document流程 clipboard.pngclipboard.png
  4. 實時預覽。 clipboard.png
  5. Swagger支持YAML格式。clipboard.png
  6. Apiary的Design-Use-Implement流程。 clipboard.png
相關文章
相關標籤/搜索