接口设计合理性讨论 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
请不要在回答技术问题时复制粘贴 AI 生成的内容
sseven

接口设计合理性讨论

  •  
  •   sseven Sep 12, 2023 3808 views
    This topic created in 961 days ago, the information mentioned may be changed or developed.

    编辑保存的接口入参如下

    { id: 1, name: '', age: 1, childTable: [{ id: 1, cardNo: '', type: 1, del: 0 }], } 

    关于 childTable 中的数据如何传?

    方式一

    • 无 id ,表示新增
    • 有 id ,表示编辑
    • 不传的表示删除了
      • 即,获取详情 childTable 返回了三条,如果删了一条,删的那条不用传了

    方式二

    • 无 id ,表示新增
    • 有 id ,表示编辑
    • 传 del=1,表示删除
      • 即,获取详情 childTable 返的数据中,如有有被删的,删除那条打 del 标记

    不同点在于删除的处理

    • 方式一需要后台查库比较哪些数据被删了
    • 方式二需要前台做逻辑,标记哪些数据被删了

    需要传 del 吗?哪种设计更合理?

    25 replies    2023-09-13 10:34:51 +08:00
    geelaw
        1
    geelaw  
       Sep 12, 2023 via iPhone
    当然是删除传入 del=1 合理,否则只要有两个客户端并发保存数据就很容易发生踩踏事件。

    两个客户端可能只是开了另一个窗口,或者离开窗口很久之后忘记,重新打开,并在一年之后回到原来的窗口。
    luomao
        2
    luomao  
       Sep 12, 2023
    我觉得都不咋合理,如果非要选一个,建议选方式二。
    方案一有个非常严重的问题,用户 A 新增 id 1 2 3 ,用户 B 新增了 4 ,A 先提交,B 在提交,那么你这代码不就变成了仅保留 4 ,删除 1 2 3 。
    sseven
        3
    sseven  
    OP
       Sep 12, 2023
    @geelaw 懂,不传 del,可能删别人新增的数据,传 del,精准到此次编辑的数据
    opengps
        4
    opengps  
       Sep 12, 2023
    方式一“不传的表示删除了”有重大缺陷
    justfindu
        5
    justfindu  
       Sep 12, 2023
    我们选的方式二 给标记, 你要选一, 那就是 del 单条操作
    yazinnnn
        6
    yazinnnn/strong>  
       Sep 12, 2023
    除非你的数据以客户端为准, 服务端的接口只是同步数据的目的, 否则哪个都不合理
    NessajCN
        7
    NessajCN  
       Sep 12, 2023   4
    拆成三个接口,/edit /new /delete
    wyx119911
        8
    wyx119911  
       Sep 12, 2023
    直接传三个 childTable 数组多清晰
    Pythoner666666
        9
    Pythoner666666  
       Sep 12, 2023
    如果 childTable 不超过 10 条直接方式一 ,因为 childTable 我会直接存成一个 string ,每次直接覆盖。如果条数很多那么久方式二
    IvanLi127
        10
    IvanLi127  
       Sep 12, 2023 via Android
    如果不做多人同时编辑的话,我选一。直接批量删除再批量添加,比都不用比。这种要么拆接口,要么直接方案一,方案二的话为啥不拆接口,或者做成 put 数组和 delete 数组?
    leetcode2020
        11
    leetcode2020  
       Sep 12, 2023
    综合方式一、二和其它老哥回复,可得:
    1. 新增条目:条目没有`id`字段(或`id`为 null 或特殊标记)。
    2. 编辑条目:条目有`id`字段,并且`del`字段未标记或为 0 。
    3. 删除条目:不从列表中移除,而是保留`id`字段,并将`del`字段标记为 1 。

    优点:
    1. 数据一致性:通过保持所有条目(包括已删除的)在列表中,并明确标记它们的状态,我们可以减少因数据丢失或时间差产生的数据一致性问题。
    2. 简化后端逻辑:后端可以直接根据`id`和`del`字段来确定应该执行哪种操作(新增、编辑或删除),而无需与数据库中的现有数据进行比较。
    3. 前端逻辑清晰:前端只需要在用户执行删除操作时更新`del`字段,而不是从列表中移除条目,使得前端逻辑更为简单和清晰。

    缺点:
    1. 数据传输量:由于已删除的条目仍然保留在列表中,会稍微增加数据传输量。

    示例:
    {
    "id": 1,
    "name": "",
    "age": 1,
    "childTable": [
    { "id": null, "cardNo": "", "type": 1, "del": 0 }, // 新增
    { "id": 1, "cardNo": "", "type": 1, "del": 0 }, // 编辑
    { "id": 2, "cardNo": "", "type": 1, "del": 1 } // 删除
    ]
    }
    eatgrass
        12
    eatgrass  
       Sep 12, 2023
    从前到后一套接口,又想优雅,说实话很难

    一个接口直接做整个聚合根( Aggregate Root )资源的更新,REST 的做法一般会继续往下拆解,即内嵌资源的增删改查 继续暴露接口

    两套接口的做法增加 BFF 层,这套接口直接为前端服务,不考虑后端领域模型,中间层组装请求调用后端的 Rest 接口
    kujio
       
    kujio  
       Sep 12, 2023
    /**
    * 比较两个列表的差异
    *
    * @param newList 新的列表
    * @param oldList 旧的列表
    * @param keyGetter 主键获取器
    * @return 返回新列表对比旧列表变化的元素(新增的、修改的、删除的)
    */
    public static <T> SeparateRst<T> separate(List<T> newList, List<T> oldList, SeparateKeyGetter<T> keyGetter) {}
    ychost
        14
    ychost  
       Sep 12, 2023
    建议删除添加一个接口
    leonshaw
        15
    leonshaw  
       Sep 12, 2023
    不一定,看业务逻辑。举个简单的情况:如果 childTable 是有序的,怎么解决冲突呢?
    imokkkk
        16
    imokkkk  
       Sep 12, 2023
    按我们的习惯 根据有无 id 区分是新增 还是 修改还可以接受,删除最好是单独出来一个接口
    dreamKing
        17
    dreamKing  
       Sep 12, 2023
    如果是我的话,应该回这样吧
    {
    id: 1,
    name: '',
    age: 1,
    childTable: [{ id: 1, cardNo: '', type: 1}],

    }
    dreamKing
        18
    dreamKing  
       Sep 12, 2023
    @dreamKing 不小心发出去了 完整的是
    {
    id: 1,
    name: '',
    age: 1,
    childTable: [{ id: 1, cardNo: '', type: 1}],
    delChildId[{id:1},{id:2} ]
    }
    Edward4074
        19
    Edward4074  
       Sep 12, 2023
    我现在的方案,原来的编辑接口用的方案 1 ,单独开个 patch 接口用于增量更新,可以同时处理增删改

    {
    id: 1,
    action: "ADD/EDIT/DEL"
    data: {
    name: '',
    age: 1,
    childTable: [{
    id: 1,
    action: EDIT,
    data: {
    cardNo: '',
    type: 1
    }
    }, {
    action: ADD,
    data: {
    cardNo: '',
    type: 1
    }
    }, {
    id: 1,
    action: DEL
    }
    ]
    }
    }
    Edward4074
        20
    Edward4074  
       Sep 12, 2023
    @Edward4074 这 json 格式没法看……自己格式化下吧 /doge
    debuggerx
        21
    debuggerx  
       Sep 12, 2023
    我的话宁愿用 POST/PUT/DELETE 方法来区分……
    wpzz
        22
    wpzz  
       Sep 12, 2023
    拆成三个接口,能监控到用户不同的行为。

    而且后端一个 controller 三个不同 service 不合理。
    yinmin
        23
    yinmin  
       Sep 12, 2023 via iPhone
    写 3 个接口,通过 url 区分,都用 post method ,别 restful 过不了等保
    luermao
        24
    luermao  
       Sep 13, 2023
    方式二
    wei2629
        25
    wei2629  
       Sep 13, 2023
    有的情况是无法拆分。不是一个操作就保存,而是多个操作后一次性保存。 可能考虑读取数据然后比对。
    About     Help     Advertise     Blog     API     FAQ     Solana     4966 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 91ms UC 03:46 PVG 11:46 LAX 20:46 JFK 23:46
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86