V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
crclz
V2EX  ›  Java

大家工作中的前后端是如何合作的?如何减少接口变更?

  •  1
     
  •   crclz · 2020-06-16 11:10:03 +08:00 · 6299 次点击
    这是一个创建于 1382 天前的主题,其中的信息可能已经有所发展或是发生改变。

    引言

    首先我大量查阅了 V2EX 、知乎的讨论,发现前后端主流做的合作方法都是:

    1. 前后端先商定一份接口文档(如果自动化一点,那么可以写一堆未实现的方法,然后用 swagger 生成文档)
    2. 接着,前后端并行地开发,后端实现接口,前端依据接口文档进行开发
    3. 前后端联调

    问题

    但是,在实践中,我发现了一些问题:

    起草文档阶段往往是非常短暂的。在这个过程中,开发者无法了解系统全貌,自然无法确定完接口列表。随着前端和后端的开发工作的推进,这些忘记的接口、需要修改的接口才逐渐暴露,这会增加前后端合作、沟通的时间成本。

    那么,在起草文档阶段,是否有一个系统的方法,来确保最小化这种需要增加、修改的接口数量?

    51 条回复    2020-06-17 14:09:27 +08:00
    pmyile
        1
    pmyile  
       2020-06-16 11:16:06 +08:00
    交互评审的时候 走一遍 接口交互
    gz911122
        2
    gz911122  
       2020-06-16 11:17:00 +08:00
    在起草文档阶段,是否有一个系统的方法,来确保最小化这种需要增加、修改的接口数量 :

    后端先定好技术方案, 再商议接口文档,变更会小很多.
    pushback
        3
    pushback  
       2020-06-16 11:23:31 +08:00
    不改需求不就没修改了么。
    hantsy
        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 好。
    yidinghe
        5
    yidinghe  
       2020-06-16 11:27:14 +08:00 via Android
    前端只关注布局、风格、交互效果和响应性,内容通过后端发来的元数据渲染出实际的界面元素,比如表单有哪些字段等等。
    Kilerd
        6
    Kilerd  
       2020-06-16 11:38:00 +08:00
    果然会出现 spring cloud contract,那玩意写起来简直是灾难,然后团队无一例外的转向了 moco
    rapiz
        7
    rapiz  
       2020-06-16 11:52:34 +08:00
    突然想,有没有这样的工具,在开发初期可以用图形界面之类快速设定接口格式,可以生成 openapi 文档,然后向前端提供后端的 mock 代码,向后端提供对应框架自动生成的接口代码。
    carbrokers
        8
    carbrokers  
       2020-06-16 12:00:46 +08:00
    歪个楼,做过一个项目,后端把数据库所有能取到的字段全部给前端了,后期完全不需要接口变更,所以后续的开发任务后端完全没有参加过。。。
    skypyb
        9
    skypyb  
       2020-06-16 12:03:41 +08:00 via Android
    产品:新加一个小需求 /小改动
    xiangyuecn
        10
    xiangyuecn  
       2020-06-16 12:07:15 +08:00   ❤️ 2
    前后端靠背坐:
    前端要数据转身拍拍后面那家伙:兄 di 给数据🎉
    后端改了接口转身揉揉后面那妹纸:接口字段又改了哈🤣

    有争论?互殴解决
    faceRollingKB
        11
    faceRollingKB  
       2020-06-16 12:12:38 +08:00
    个人经验:这种问题几乎无法避免,所以技术上我选择用 typescript 开发,方便日后改接口定义,另外如果接口定义问题比较大(概率小),通常涉及到组件、模块的重构,所以我选择用 ng 框架,重构代价小
    Jackeriss
        12
    Jackeriss  
       2020-06-16 12:14:10 +08:00 via iPhone
    graphql
    chendy
        13
    chendy  
       2020-06-16 12:17:08 +08:00
    @Kilerd #6 +1 spring 家两个东西 restdoc 和 contract 都是理想很丰满,用着贼难受的东西
    lenqu
        14
    lenqu  
       2020-06-16 12:26:00 +08:00
    可以参考我之前未做完的一个的东西,API 接口的一个中间件,在后端接口之上进行统一规范化,后端只完成最小单元接口实现,中间件进行整合提供服务

    有需要的联系我哦!!!一起做
    Kilerd
        15
    Kilerd  
       2020-06-16 12:31:27 +08:00
    @lenqu #14 graphql ? 先解决 N + 1 的问题再说吧。
    Foxkeh
        16
    Foxkeh  
       2020-06-16 12:32:17 +08:00
    @carbrokers 你说的"所有", 包括用户的密码字段吗😄
    malusama
        17
    malusama  
       2020-06-16 12:32:55 +08:00
    @Kilerd DataLoader
    lenqu
        18
    lenqu  
       2020-06-16 12:39:20 +08:00
    @Kilerd 如果已有的后端接口可以实现,那么直接扩展即可,如果没有,在已有的单元接口之上再进行扩展,保证后端开发代码量最小
    Justin13
        19
    Justin13  
       2020-06-16 12:41:26 +08:00 via Android
    上 GpaphQL
    hantsy
        20
    hantsy  
       2020-06-16 12:51:39 +08:00
    @chendy 这两个东西只要你的团队一直坚持写测试,一般不会有什么太大的问题。restdocs 我之前一个项目下来一直在用,用于 API 开发文档生成。

    Spring Cloud Contract 有一定局限性,对于全部后端 Microservice 中 service 2 service 互操作的测试,优势很明显。但前后端调用,虽然官方也一直在加强其它实语言支持,也提供了 Nodejs 与 Java 项目结合的例子,但是与前端结合的时候远不如 Pact 舒服。
    slyang5
        21
    slyang5  
       2020-06-16 12:52:58 +08:00
    用 protobuf ?
    hantsy
        22
    hantsy  
       2020-06-16 12:54:00 +08:00
    @Kilerd Moco 是什么鬼???
    ChanKc
        23
    ChanKc  
       2020-06-16 13:05:01 +08:00 via Android
    理论上,restful 和 hateoas 就是为了解决这个问题的。
    当然实际上,restful 已经变成了“有比较好看的 URL 的 API”的意思了
    ty89
        24
    ty89  
       2020-06-16 13:17:09 +08:00
    @carbrokers 这样别人爬你数据就太方便了,简直就是直接复制你的数据库
    hantsy
        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 就可以了。
    ty89
        26
    ty89  
       2020-06-16 13:19:24 +08:00
    从根本上的解决方案应该是 TDD, 测试驱动开发。 尤其是后端。
    hantsy
        27
    hantsy  
       2020-06-16 13:33:57 +08:00
    @ty89 这是必须的,对 API 开发很容易的事情。

    如果以前传统 Web 页面测试难写,说得过去,国内的项目页面变化太化,页面设计 Elment 不标准。现在纯 API 测试真的很简单。
    zzzmh
        28
    zzzmh  
       2020-06-16 13:45:08 +08:00
    1. 生成文档,我们用 swagger,另外还有一个 apidoc 生成放到静态服
    2. 我要是能帮前端写掉一部分的代码尤其是逻辑类的,我会实现一版 demo
    3. 再有分歧就互掐
    houfeibin
        29
    houfeibin  
       2020-06-16 13:46:08 +08:00
    @carbrokers 感觉你这样数据会很不安全
    hantsy
        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
    noobsheldon
        31
    noobsheldon  
       2020-06-16 14:07:01 +08:00
    一个接口,通过接口参数区分逻辑,完美。
    noobsheldon
        32
    noobsheldon  
       2020-06-16 14:07:45 +08:00
    ISSSSSSS
        33
    ISSSSSSS  
       2020-06-16 15:03:20 +08:00
    所以必然要有联调试过程。
    index90
        34
    index90  
       2020-06-16 15:15:08 +08:00
    如果一个软甲只加代码不修改,是几乎不会出错的。接口也一样,不存在修改接口,只有加接口,用 /v1/xxx /v2/xxx 去区分。
    la2la
        35
    la2la  
       2020-06-16 15:33:27 +08:00
    后端开发搬着笔记本做到前端小姐姐旁边调
    Seneca
        36
    Seneca  
       2020-06-16 15:35:23 +08:00
    我们是后端写接口,前端等着接口来了,直接调用就行。给你啥你用啥
    xff1874
        37
    xff1874  
       2020-06-16 15:45:40 +08:00
    我们目前正在做这个事情,原理就是读取定义的接口和真实的请求,然后做比对
    stevenkang
        38
    stevenkang  
       2020-06-16 16:38:14 +08:00
    需求来了,基本上过一遍就能把接口定下来。

    要改接口一般都是由于需求不明确(或自己没理解到位)、需求变更等原因。

    这种情况下改一下接口就行了,毕竟改需求前端后端不都得过一遍嘛。
    lplk
        39
    lplk  
       2020-06-16 16:59:43 +08:00
    @carbrokers #8 我就这样搞过,虽然很省事,但是如果后期表格字段不断增加,这样会增加网络传输数据的时间,甚至有的字段会很大,最好还是严格规范
    msg7086
        40
    msg7086  
       2020-06-16 17:02:41 +08:00
    改接口 = 改文档,然后前段照着文档来不就行了。
    BDD/TDD 很多框架都可以根据测试数据来生成文档的。
    jinwyp
        41
    jinwyp  
       2020-06-16 17:04:38 +08:00
    很简单啊 找个资深前端定接口, 前端把界面开发完成 50%后 定的接口基本差不多了。
    Aprilming
        42
    Aprilming  
       2020-06-16 17:05:22 +08:00
    前端就给我画样式,接口啥的都是自己来写,自己对接,前端逻辑也是自己写。我的前端伙伴就是一个无情的 UI 机器人
    Airon
        43
    Airon  
       2020-06-16 17:08:35 +08:00
    交互能明确确认,确认完交互后端就能先出 mock,这样前后端开发就没啥影响。但是问题在于,需求是否真的明确这么细,产品是否完全不变动交互流程 (ps:很多傻逼产品明明自己确认的交互,开发出来还逼逼赖赖 技术们开发不考虑用户体验。。。然后又是改流程改接口)
    xuanbg
        44
    xuanbg  
       2020-06-16 17:09:49 +08:00
    起草文档阶段往往是非常短暂的,这个是有问题的。设计的必要时间还是要留的,好的设计能够有效减少写代码和测试的时间。所谓磨刀不误砍柴工。
    lenqu
        45
    lenqu  
       2020-06-16 18:23:56 +08:00
    @ty89 干过 DBA 的都知道,数据库的一个普通权限读权限用户想拿到写权限需要找漏洞,反爬从来不在后端逻辑里写入不是么?
    Sapp
        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 文件。
    xgfan
        47
    xgfan  
       2020-06-16 20:14:58 +08:00
    spring cloud contract 真的是垃圾,道理我都懂,用起来就是难用。
    一个简单的
    json array 为空列表 -> 合法
    json array 不为空 -> 判断里面 item 字段
    都做不到(只能通过很恶心的办法实现
    zqx
        48
    zqx  
       2020-06-17 06:52:33 +08:00 via Android
    需求评审-设计交互评审-前端和后端分别技术评审,然后再出接口文档,再开发,基本不会改了,除非产品需求变更了
    ty89
        49
    ty89  
       2020-06-17 09:59:11 +08:00
    @lenqu 你把数据库里的全部字段直接通过接口返回,那不就相当于直接复制你数据库表了吗,跟读写权限有啥关系。
    hejingyuan199
        50
    hejingyuan199  
       2020-06-17 11:20:54 +08:00
    我没有认真读前面的留言。不好意思。

    我们的做法是,后端先把基础弄起来后。
    前端给我们一个接口清单,我们去做。
    毕竟前端跟客户最贴近。
    不过如果遇到前端太胡闹的时候
    就得吵吵架。

    让前端提要求以后,
    他们就不太 BB 地改需求了,
    毕竟理亏在他们。
    sunxiansong
        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 注释,缺点就是首次请求之前不会有记录。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2768 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 12:00 · PVG 20:00 · LAX 05:00 · JFK 08:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.