首先我大量查阅了 V2EX 、知乎的讨论,发现前后端主流做的合作方法都是:
但是,在实践中,我发现了一些问题:
起草文档阶段往往是非常短暂的。在这个过程中,开发者无法了解系统全貌,自然无法确定完接口列表。随着前端和后端的开发工作的推进,这些忘记的接口、需要修改的接口才逐渐暴露,这会增加前后端合作、沟通的时间成本。
那么,在起草文档阶段,是否有一个系统的方法,来确保最小化这种需要增加、修改的接口数量?
1
pmyile 2020-06-16 11:16:06 +08:00
交互评审的时候 走一遍 接口交互
|
2
gz911122 2020-06-16 11:17:00 +08:00
在起草文档阶段,是否有一个系统的方法,来确保最小化这种需要增加、修改的接口数量 :
后端先定好技术方案, 再商议接口文档,变更会小很多. |
3
pushback 2020-06-16 11:23:31 +08:00
不改需求不就没修改了么。
|
4
hantsy 2020-06-16 11:24:30 +08:00 1
对于开发阶段变化太快了,又臭又长的文档根本不可能用来做约束。
CDC 模式( Consumer Driven Contract )是一种很好的用于 API 协议开发 Pattern,API Producer 和 Consumer 之间先定好协议 Contract,生成 Stub 之类的,再分开开发实现,最终两边都是要通过相关的 Contract 测试。 自己查看 Pact 使用,支持各种语言。 另外 Spring 下的 Spring Cloud Contract 也一样,对 Spring 生态支持一流,还可以定义 Message Broker 之间的协议,只是对前端语言框架支持不如 Pact 好。 |
5
yidinghe 2020-06-16 11:27:14 +08:00 via Android
前端只关注布局、风格、交互效果和响应性,内容通过后端发来的元数据渲染出实际的界面元素,比如表单有哪些字段等等。
|
6
Kilerd 2020-06-16 11:38:00 +08:00
果然会出现 spring cloud contract,那玩意写起来简直是灾难,然后团队无一例外的转向了 moco
|
7
rapiz 2020-06-16 11:52:34 +08:00
突然想,有没有这样的工具,在开发初期可以用图形界面之类快速设定接口格式,可以生成 openapi 文档,然后向前端提供后端的 mock 代码,向后端提供对应框架自动生成的接口代码。
|
8
carbrokers 2020-06-16 12:00:46 +08:00
歪个楼,做过一个项目,后端把数据库所有能取到的字段全部给前端了,后期完全不需要接口变更,所以后续的开发任务后端完全没有参加过。。。
|
9
skypyb 2020-06-16 12:03:41 +08:00 via Android
产品:新加一个小需求 /小改动
|
10
xiangyuecn 2020-06-16 12:07:15 +08:00 2
前后端靠背坐:
前端要数据转身拍拍后面那家伙:兄 di 给数据🎉 后端改了接口转身揉揉后面那妹纸:接口字段又改了哈🤣 有争论?互殴解决 |
11
faceRollingKB 2020-06-16 12:12:38 +08:00
个人经验:这种问题几乎无法避免,所以技术上我选择用 typescript 开发,方便日后改接口定义,另外如果接口定义问题比较大(概率小),通常涉及到组件、模块的重构,所以我选择用 ng 框架,重构代价小
|
12
Jackeriss 2020-06-16 12:14:10 +08:00 via iPhone
graphql
|
14
lenqu 2020-06-16 12:26:00 +08:00
可以参考我之前未做完的一个的东西,API 接口的一个中间件,在后端接口之上进行统一规范化,后端只完成最小单元接口实现,中间件进行整合提供服务
有需要的联系我哦!!!一起做 |
16
Foxkeh 2020-06-16 12:32:17 +08:00
@carbrokers 你说的"所有", 包括用户的密码字段吗😄
|
19
Justin13 2020-06-16 12:41:26 +08:00 via Android
上 GpaphQL
|
20
hantsy 2020-06-16 12:51:39 +08:00
@chendy 这两个东西只要你的团队一直坚持写测试,一般不会有什么太大的问题。restdocs 我之前一个项目下来一直在用,用于 API 开发文档生成。
Spring Cloud Contract 有一定局限性,对于全部后端 Microservice 中 service 2 service 互操作的测试,优势很明显。但前后端调用,虽然官方也一直在加强其它实语言支持,也提供了 Nodejs 与 Java 项目结合的例子,但是与前端结合的时候远不如 Pact 舒服。 |
21
slyang5 2020-06-16 12:52:58 +08:00
用 protobuf ?
|
23
ChanKc 2020-06-16 13:05:01 +08:00 via Android
理论上,restful 和 hateoas 就是为了解决这个问题的。
当然实际上,restful 已经变成了“有比较好看的 URL 的 API”的意思了 |
24
ty89 2020-06-16 13:17:09 +08:00
@carbrokers 这样别人爬你数据就太方便了,简直就是直接复制你的数据库
|
25
hantsy 2020-06-16 13:18:07 +08:00
@chendy 以前我觉得比较难受是用 Json Schema 定义( jsonschema.org ,这个也是标准 draft)把交互格式都是定好。
有在线工具 https://jsonschema.net/home 然后前后全部写测试验证符合就行了,这个比较直接。 后端 Java 可以用 RestAssured (包括 Jsonschema vilidator)验证. 前端按 JsonSchema 定义生成 json data 文件测试中 mock 就可以了。 |
26
ty89 2020-06-16 13:19:24 +08:00
从根本上的解决方案应该是 TDD, 测试驱动开发。 尤其是后端。
|
27
hantsy 2020-06-16 13:33:57 +08:00
|
28
zzzmh 2020-06-16 13:45:08 +08:00
1. 生成文档,我们用 swagger,另外还有一个 apidoc 生成放到静态服
2. 我要是能帮前端写掉一部分的代码尤其是逻辑类的,我会实现一版 demo 3. 再有分歧就互掐 |
29
houfeibin 2020-06-16 13:46:08 +08:00
@carbrokers 感觉你这样数据会很不安全
|
30
hantsy 2020-06-16 14:04:28 +08:00
@zzzmh Swagger 结合其它的一些工具,也可以生成不错的静态文档,https://github.com/hantsy/building-restful-apis-with-springmvc-gitbook/blob/master/swagger.md#documents-rest-apis
|
31
noobsheldon 2020-06-16 14:07:01 +08:00
|
32
noobsheldon 2020-06-16 14:07:45 +08:00
|
33
ISSSSSSS 2020-06-16 15:03:20 +08:00
所以必然要有联调试过程。
|
34
index90 2020-06-16 15:15:08 +08:00
如果一个软甲只加代码不修改,是几乎不会出错的。接口也一样,不存在修改接口,只有加接口,用 /v1/xxx /v2/xxx 去区分。
|
35
la2la 2020-06-16 15:33:27 +08:00
后端开发搬着笔记本做到前端小姐姐旁边调
|
36
Seneca 2020-06-16 15:35:23 +08:00
我们是后端写接口,前端等着接口来了,直接调用就行。给你啥你用啥
|
37
xff1874 2020-06-16 15:45:40 +08:00
我们目前正在做这个事情,原理就是读取定义的接口和真实的请求,然后做比对
|
38
stevenkang 2020-06-16 16:38:14 +08:00
需求来了,基本上过一遍就能把接口定下来。
要改接口一般都是由于需求不明确(或自己没理解到位)、需求变更等原因。 这种情况下改一下接口就行了,毕竟改需求前端后端不都得过一遍嘛。 |
39
lplk 2020-06-16 16:59:43 +08:00
@carbrokers #8 我就这样搞过,虽然很省事,但是如果后期表格字段不断增加,这样会增加网络传输数据的时间,甚至有的字段会很大,最好还是严格规范
|
40
msg7086 2020-06-16 17:02:41 +08:00
改接口 = 改文档,然后前段照着文档来不就行了。
BDD/TDD 很多框架都可以根据测试数据来生成文档的。 |
41
jinwyp 2020-06-16 17:04:38 +08:00
很简单啊 找个资深前端定接口, 前端把界面开发完成 50%后 定的接口基本差不多了。
|
42
Aprilming 2020-06-16 17:05:22 +08:00
前端就给我画样式,接口啥的都是自己来写,自己对接,前端逻辑也是自己写。我的前端伙伴就是一个无情的 UI 机器人
|
43
Airon 2020-06-16 17:08:35 +08:00
交互能明确确认,确认完交互后端就能先出 mock,这样前后端开发就没啥影响。但是问题在于,需求是否真的明确这么细,产品是否完全不变动交互流程 (ps:很多傻逼产品明明自己确认的交互,开发出来还逼逼赖赖 技术们开发不考虑用户体验。。。然后又是改流程改接口)
|
44
xuanbg 2020-06-16 17:09:49 +08:00
起草文档阶段往往是非常短暂的,这个是有问题的。设计的必要时间还是要留的,好的设计能够有效减少写代码和测试的时间。所谓磨刀不误砍柴工。
|
46
Sapp 2020-06-16 20:02:51 +08:00
你想要一次性拿全接口,如果是小项目开发有可能,只需要找个经验丰富的后端,他基本能 cover 你所有的需求,提供的接口一点不会少,妥妥的够你用,你想到的问题他都提前想到了,但是大项目基本不可能,一是你没办法招到那么多好后端,二是大项目本身就面临着需求变更,如果一开始就商量好所有的变更,我不说现实不现实,你们坐着开会都要开多久?开会的时间都可能比开发的时间长, 更何况真的能坐在会议桌就考虑到所有的问题? 所以这方面就不要指望能完全搞定了。但是有另一个方法,可以减少接口变更带来的前后端成本,就是 typescript + 动态生成接口,前端不需要手写 ajax 请求,直接调用 node 根据后端文档生成好的请求方法,
例如: const [getUsername, loading] = useRequest(getUsernameRequest) useeffect(() => { getUsername({userID: xxx}) }, []) getUsernameRequest 直接生成的,同时生成了 interface 文件。 同时因为 typescript 的类型要求,前端也根本不需要看文档就能知道需要输入那些参数,并且你提到的后端改了接口,把 userID 改为了 userId,那么前端会直接收到 typescript 的报错提示,然后顺手改一下就行了。如果是改了接口名字,那么前端看一下 git 记录就知道你改了哪些名字,也不需要在口头沟通,或者等测试报错才知道你改了接口。 这样对于后端而言省了每天提醒前端我又改了什么什么的时间,对于前端省了每天要找后端对你又改了什么什么,怎么我测试的时候还没问题,测试一测就又出问题的时间,还少写了 interface 文件。 |
47
6IbA2bj5ip3tK49j 2020-06-16 20:14:58 +08:00
spring cloud contract 真的是垃圾,道理我都懂,用起来就是难用。
一个简单的 json array 为空列表 -> 合法 json array 不为空 -> 判断里面 item 字段 都做不到(只能通过很恶心的办法实现 |
48
zqx 2020-06-17 06:52:33 +08:00 via Android
需求评审-设计交互评审-前端和后端分别技术评审,然后再出接口文档,再开发,基本不会改了,除非产品需求变更了
|
50
hejingyuan199 2020-06-17 11:20:54 +08:00
我没有认真读前面的留言。不好意思。
我们的做法是,后端先把基础弄起来后。 前端给我们一个接口清单,我们去做。 毕竟前端跟客户最贴近。 不过如果遇到前端太胡闹的时候 就得吵吵架。 让前端提要求以后, 他们就不太 BB 地改需求了, 毕竟理亏在他们。 |
51
sunxiansong 2020-06-17 14:09:27 +08:00
与其避免接口变化不如拥抱变化,让变化可控、可测试、可追踪
- 首先会有一份 api 风格说明,说明一般的通用的数据结构风格、错误处理、token 机制 - 后端通过 cli 工具导出后端模型到前端的 ts 结构,前端可以拷贝或直接使用数据模型。导出的代码也包含了可能的错误码、常量枚举 - 后端直接写 ts http 调用的代码,并附上最小可测试代码( jest 测试代码),在代码中标注文档(状态码、错误码等),这步其实主要是 route 标注,前端甚至可以直接复用 http 调用的代码 - 生成的 ts 数据结构和 http 调用代码放在 git 上,提交时填写恰当的注释标注 api 变更,这步主要是确保前端可以详细的跟踪 api 变动,前端可以 watch 文档工程追踪 api - 时间充足的话,最好还是写足够的 api 集成测试 我以前还做过其他的尝试,在测试环境用 AOP 拦截请求,用 json schema 记录请求的 route/request body/response body,然后写到数据库里,再人工标注 api 注释,缺点就是首次请求之前不会有记录。 |