【效率专精系列】善用API统一描述语言提升RestAPI开发效率

团队内部RestAPI开发采用设计驱动开发的模式,即使用API设计文档解耦前端和后端的开发过程,双方只在联调与测试时耦合。在实际开发和与前端合作的过程中,受限于众多因素的影响,开发效率还有进一步提高的空间。本文的目的是优化工具链支持,减少一部分重复和枯燥的劳动。

现状梳理

前后端工作流

  1. 需求理解:前后端先理解产品思路、需求的详细内容
  2. 敲定接口:后端出API设计文档初稿,与前端面对面或者在线讨论修正,接着后端(有时是前端)把API描述记录到公司内部的API文档库(在线markdown编辑器,提供分级目录的存储功能,对如何描述API没有一定的标准,因此描述格式不统一,因人而异1)。接着根据双方工作的安排,约定联调时间
  3. 独立开发:双方独立开发(也有可能非完全独立开发,如需要对方的环境配合等;或者存在返工,如API设计发生变更等)
  4. 系统联调:测试API基本功能和双方系统的连通性
  5. 测试回归:开发或者QA编写测试用例并测试业务流程

可优化方向

1. 减少文档编写时间

根据个人的开发经验,后端编写API设计文档时常见的情况有:如果是简单的需求,API数量较少,后端直接通过内部即时通信软件和前端沟通;如果是复杂的需求,API数量较多,后端会先把API描述写到本地临时文档(纯文本、markdown、evernote等)或者内网(内部个人Wiki、git仓库)中,然后把链接发给前端review或者直接面对面沟通。这样的方式灵活,但存在一些问题,比如:

  • 描述格式没有标准。对于简单的描述,文档格式比较随意,双方基于约定和经验理解和开发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。

    • 设计文档中会规定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格式。

    例如:想象一下从Wiki文档的表格中一个个复制粘贴,再编辑成markdown格式文本是典型的成本大于收益的工作。
  • 文档维护成本大。由于文档和代码分开存放,由于需要手动操作,因此文档与代码同步成本较高。随着时间推移,不断修改接口实现的时候都必须同步修改接口文档,而文档与代码又处于两个不同的媒介,除非有严格的管理机制,不然很容易导致不一致现象,并在业务整体交接、开发成员替换时使后来人付出较大的时间成本。

    不同的存放形式的优缺点见仁见智,类似于Spring也有XML和JavaConfig两种配置方式。

2. 减少联调时间

缺少样例数据。由于团队内部前端一般不会全面的了解业务,后端提供的样例数据往往比前端自己生成的Mock数据对业务需求的把握更准确。如果后端能在API设计文档中提供样例数据,一是如果前端没有自动Mock工具的话,能节约前端生成Mock数据的时间;二是能在联调前为前端提前发现一些低级错误(比如具有业务特征的一些默认值处理、空值处理、字段缺失等场景)。

3. 减少部署时间

beta环境绑定了唯一的beta域名,因此在多分支并行开发时是稀缺资源,较大的项目在beta环境编译和部署往往消耗很多等待和解决冲突的时间。如果在联调中发现的问题较多,就需要多次部署beta环境,时间成本十分可观。

如何减少部署时间另外行文

寻找技术候选

总结起来,上面列出的问题大部分是由于API描述标准不统一引起的,因此要用标准化的工厂代替散乱的手工生产。虽然平时开发的API具有Rest风格、对外网开放,只被企业自己的应用调用,不过普遍的WebAPI开发流程还是适用的。我在网上搜索一些功能较为符合的RestAPI设计工具,将其大致分为3类讨论。
clipboard.png

第一类:Swagger、Apiary、RAML

人和机器可读的API描述标准,围绕该语言有完善的工具链:一般有设计、编译(即Codegen)、测试(有MockServer、自动Mock、本地直连等形式)、文档(包括静态文档,如html和pdf;还有可交互文档html+js)、合作(多人+多角色合作开发)这几个模块,各个标准都差不多。

较为学术性的表述:虽然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特性支持,输入效率较低。放弃。

进一步分析

Swagger2API BlueprintRAML
Design在线编辑、IntelliJ Idea插件在线编辑、命令行、Sublime/Atom/Vim插件API Workbench、Sublime/VS插件
Design文档格式yaml、jsonmarkdownyaml
Build支持在线Build、IntelliJ Idea插件/Maven插件
Codegen服务端框架Spring Boot/JAX—RS
Test运行时手动Mock、第三方工具官方和第三方工具生成MockServer/Client第三方工具和在线服务
DocumentMaven插件生成静态文档、在线或运行时生成可交互文档,支持SpringMVC+注解形式第三方工具第三方工具
Share在线、收费在线、收费离线、第三方工具

综合考虑,最后选择Swagger2。因为Swagger对现有的工作流侵入较少;工具较为完整;与团队使用的Spring MVC技术栈无缝集成,可以减轻文档工作量。Swagger2也有一些缺点,如:使用注解方式对代码有侵入性。

用Swagger2优化现有工作流

  1. 减少文档的编写时间

    1. 如果后端先编写独立的API设计文档,可利用Swagger在线编辑器或IDE插件的自动完成等特性;yaml格式统一、简单易懂、表达能力强,较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对象创建用户")@PostMappingpublic 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 Helpversion: v1title: demo13termsOfService: 'http://www.github.com/kongchen/swagger-maven-plugin'
host: HOST
basePath: /s
tags:- name: Users
schemes:- http
paths:/users:post:tags:- Userssummary: 创建用户description: 根据User对象创建用户operationId: postUserparameters:- in: bodyname: bodyrequired: falseschema:$ref: '#/definitions/User'responses:'200':description: successful operationschema:type: string'/users/{id}':get:tags:- Userssummary: 获取用户详细信息description: 根据url的id来获取用户详细信息operationId: getUserparameters:- name: 'id'in: pathrequired: truetype: integerformat: int64responses:'200':description: successful operationschema:$ref: '#/definitions/User'
definitions:User:type: objectproperties:id:type: integerformat: int64name:type: stringage: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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/394340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据包提取文件_航测怎样高效提取无人机POS航点数据

无限创新工作室研发的POS数据记录仪是一款采集飞控POS 数据并管理的设备,它将飞控 POS 点数据进行记录,形成单独的POS 数据记录TXT 文本,并独立存储于内存卡,可通过USB、U 盘或内存卡形式对数据进行读取。通过对相机进行拍照控制和…

开始时间小于 结束时间 js_DNF分享红包开始及结束时间 红包有什么奖励相关介绍...

[闽南网]DNF分享红包分享快乐时间从2019年的1月3日开始到1月21日前结束,活动期间玩家每天登录游戏可以得到一个新年红包,使用后可以为同一个频道的玩家送去祝福,根据送出红包的数量得到不同的奖励。(dnf幸运饺子铺活动)(DNF95版新副本攻略)本…

SQL 邮件配置篇

在我们运维工作中,经常要对备份,ETL等作业进行监控,这时我们需要用到SQL SERVER自带的邮件服务器,其原理,我在这么里不多说,直接来实战,下面是我对服务器配置源码,分享给大家&#x…

汽车之家的安全框架,是如何从0到1搭建的?

“别人家的安全”是安全威胁情报(微信ID:Threatbook)近期推出的一档专栏。 合规、管理、构建、应急……安全问题千千万,层出不穷。我们没办法给出这些问题的标准答案,但我们可以用Case Study的形式,让你看看…

《网络空间欺骗:构筑欺骗防御的科学基石》一1.1 主动网络空间防御中网络空间抵赖与欺骗的视图...

1.1 主动网络空间防御中网络空间抵赖与欺骗的视图 本文讲的是网络空间欺骗:构筑欺骗防御的科学基石一1.1 主动网络空间防御中网络空间抵赖与欺骗的视图,将抵赖与欺骗纳入标准操作规程(SOP):随着攻击技术的不断演进,网…

揭开勒索软件的真面目

一、前言 2013年9月,戴尔公司的SecureWorks威胁应对部门(CTU)发现了一种名为“CryptoLocker”的勒索软件,它以邮件附件形式分发,感染计算机并加密近百种格式文件(包括电子表格、数据库、图片等)…

Java中的阻塞队列-LinkedBlockingQueue(二)

原文地址:http://benjaminwhx.com/2018/05/11/%E3%80%90%E7%BB%86%E8%B0%88Java%E5%B9%B6%E5%8F%91%E3%80%91%E8%B0%88%E8%B0%88LinkedBlockingQueue/ 在集合框架里,想必大家都用过ArrayList和LinkedList,也经常在面试中问到他们之间的区别。…

碳钢腐蚀速率计算公式_镁合金轮毂螺栓连接的电偶腐蚀行为

环境污染和能源短缺促使日益发达的汽车工业大力推进构件轻量化,镁合金是最轻的结构材料之一,构件采用镁合金制造可以在减重的同时不降低结构强度,受到汽车工业的青睐。轮毂作为汽车的主要组成部件,其轻量化是汽车节能减排的有效途…

避免人为灾难:盘点数据中心里十大愚蠢行为

对于企业运营,数据中心从设计、部署等各个环节都有极其严格的规范,保证简单的“题目”不出错也需要企业IT管理人员的智慧,在数据中心任何一个小错误往往会带来巨大灾难。数据中心从设计、部署、测试、运行、运维等各个环节都不能有任何的疏忽…

leetcode1039. 多边形三角剖分的最低得分(动态规划)

给定 N,想象一个凸 N 边多边形,其顶点按顺时针顺序依次标记为 A[0], A[i], …, A[N-1]。 假设您将多边形剖分为 N-2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 N-2 个三角形的…

thinkcmf 横向排列数据_利用python进行数据分析之数据清洗规整

1.处理缺失值数据使用dropna()时,注意里面参数axis、how、thresh的用法使用fillna()时,注意里面参数value、method、inplace、limit的用法2.数据转换去重data.drop_duplicates(keeplast)#注意keep的用法映射map()针对的是一维数组…

v$asm_diskgroup中state的说明

1.使用oracle账号连接数据库,查看v$asm_diskgroup 2.使用grid账号连接ASM实例,查看v$asm_diskgroup 3.官方v$asm_diskgroup关于state的解释 https://docs.oracle.com/en/database/oracle/oracle-database/19/refrn/V-ASM_DISKGROUP.html#GUID-5CF77719-7…

Python笔记 【无序】 【五】

描述符 将某种特殊类型的类【只要实现了以下或其中一个】的实例指派给另一个类的属性 1.__get__(self,instance,owner)//访问属性,返回属性的值 2.__set__(self,instance,value)//将在属性分配【即赋值】中调用,不返回任何内容 3.__delete__(…

化工图纸中LISP_化工设备厂参展模型设计制作

最近这个案子是受某化工设备企业委托做四套设备模型 用来参加展会在模型制作过程中,这类案例经常遇到。但是客户所提供的CAD图纸,往往是实物尺寸在进行缩放的过程中常会造成过薄和过于精细的情况出现眼下技术小哥就遇到这类情况让我们先看看客户提供的C…

社交大佬们的数据“大”在哪里?

文章讲的是社交大佬们的数据“大”在哪里,“别说忙,没工夫看书,你那刷FB/朋友圈的工夫腾出来,保证每周啃下一本”,小编身边总充斥着这样的“训话”。 额,奈何我每天的工作离不开从社交媒体中获取信息&#…

mysql 多数据源访问_通过Spring Boot配置动态数据源访问多个数据库的实现代码

之前写过一篇博客《SpringMybatisMysql搭建分布式数据库访问框架》描述如何通过SpringMybatis配置动态数据源访问多个数据库。但是之前的方案有一些限制(原博客中也描述了):只适用于数据库数量不多且固定的情况。针对数据库动态增加的情况无能为力。下面讲的方案能支…

菜鸟postman接口测试_postman 接口测试(转)

本文转载自testerhome;作者:xinxi1990 ;原文链接:https://testerhome.com/topics/18719;转载以分享知识为目的,著作权归原作者所有,如有侵权,请联系删除。postman使用创建用例集启动…

vb 数组属性_VB中菜单编辑器的使用讲解及实际应用

大家好,今天我们共同来学习VB中菜单方面的知识。VB中菜单的基本作用有两个:1、提供人机对话的界面,以便让使用者选择应用系统的各种功能;2、管理应用系统,控制各种功能模块的运行。在实际应用中,菜单可分为…

《JAVA程序设计》_第七周学习总结

一、学习内容 1.String类——8,1知识 Java专门提供了用来处理字符序列的String类。String类在java.lang包中,由于java.lang包中的类被默认引入,因此程序可以直接使用String类。需要注意的是Java把String类声明为final类,因此用户不能扩展Stri…

NeHe OpenGL教程 第三十七课:卡通映射

转自【翻译】NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改。对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢。 NeHe OpenGL第三十七…