接口设计合理性讨论

2023-09-12 10:54:53 +08:00
 sseven

编辑保存的接口入参如下

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

关于 childTable 中的数据如何传?

方式一

方式二

不同点在于删除的处理

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

2932 次点击
所在节点    程序员
25 条回复
geelaw
2023-09-12 10:57:27 +08:00
当然是删除传入 del=1 合理,否则只要有两个客户端并发保存数据就很容易发生踩踏事件。

两个客户端可能只是开了另一个窗口,或者离开窗口很久之后忘记,重新打开,并在一年之后回到原来的窗口。
luomao
2023-09-12 11:03:31 +08:00
我觉得都不咋合理,如果非要选一个,建议选方式二。
方案一有个非常严重的问题,用户 A 新增 id 1 2 3 ,用户 B 新增了 4 ,A 先提交,B 在提交,那么你这代码不就变成了仅保留 4 ,删除 1 2 3 。
sseven
2023-09-12 11:04:03 +08:00
@geelaw 懂,不传 del,可能删别人新增的数据,传 del,精准到此次编辑的数据
opengps
2023-09-12 11:04:33 +08:00
方式一“不传的表示删除了”有重大缺陷
justfindu
2023-09-12 11:05:11 +08:00
我们选的方式二 给标记, 你要选一, 那就是 del 单条操作
yazinnnn
2023-09-12 11:07:24 +08:00
除非你的数据以客户端为准, 服务端的接口只是同步数据的目的, 否则哪个都不合理
NessajCN
2023-09-12 11:26:47 +08:00
拆成三个接口,/edit /new /delete
wyx119911
2023-09-12 11:37:19 +08:00
直接传三个 childTable 数组多清晰
Pythoner666666
2023-09-12 12:46:22 +08:00
如果 childTable 不超过 10 条直接方式一 ,因为 childTable 我会直接存成一个 string ,每次直接覆盖。如果条数很多那么久方式二
IvanLi127
2023-09-12 13:20:33 +08:00
如果不做多人同时编辑的话,我选一。直接批量删除再批量添加,比都不用比。这种要么拆接口,要么直接方案一,方案二的话为啥不拆接口,或者做成 put 数组和 delete 数组?
leetcode2020
2023-09-12 13:32:57 +08:00
综合方式一、二和其它老哥回复,可得:
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
2023-09-12 13:47:34 +08:00
从前到后一套接口,又想优雅,说实话很难

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

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

}
dreamKing
2023-09-12 16:36:40 +08:00
@dreamKing 不小心发出去了 完整的是
{
id: 1,
name: '',
age: 1,
childTable: [{ id: 1, cardNo: '', type: 1}],
delChildId[{id:1},{id:2} ]
}
Edward4074
2023-09-12 16:44:57 +08:00
我现在的方案,原来的编辑接口用的方案 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
2023-09-12 16:46:24 +08:00
@Edward4074 这 json 格式没法看……自己格式化下吧 /doge

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/972960

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX