是面向业务设计接口还是面向资源设计接口
比如一个订单表包含有地址信息,修改地址这么一个需求,设计接口一般是 /updateAddress
还是 /updateOrder
呢,如果用 /updateOrder
的话后续更新订单其他信息也可以复用这个接口,但是更新订单信息可能当前业务只开放修改部分信息,所以接口里面做校验的逻辑就复杂了很多,如果用 /updateAddress 的话接口会越来越多,也增加测试的工作量
大佬们有何见解
1
mokeyjay 2022-05-23 11:00:18 +08:00
简单的项目面向资源,复杂的项目面向业务。也可以主面向资源,部分逻辑复杂的接口面向业务
可以看看 restful 规范,但不要死板遵循。复杂项目没法完全 restful |
2
dzdh 2022-05-23 11:05:21 +08:00
个人喜欢 post /order/update {address_id:id}
|
3
kaiki 2022-05-23 11:06:57 +08:00
要不折中一下,用 /update/address
|
4
luckyrayyy 2022-05-23 11:08:07 +08:00
同意楼上,不过 PATCH 请求应该更好?
|
5
luckyrayyy 2022-05-23 11:08:25 +08:00
完了被插楼了,我是说 2 楼
|
6
MakHoCheung OP @mokeyjay 有道理
|
7
MakHoCheung OP @dzdh address 没跟 order 分开,所以没有 addressId ,不过你这种想法应该就是面向业务了
|
8
potatowish 2022-05-23 12:32:22 +08:00 via iPhone
可以用一个接口,比如 /updateOrder
通过类型来判断具体要修改的信息 {type:"address"} |
9
dzdh 2022-05-23 12:37:55 +08:00
@MakHoCheung 看咋说。设计个接口没有业务调用你设计他干啥 (doge
|
10
8520ccc 2022-05-23 12:44:48 +08:00 via iPhone 1
order/update
order/delete order/fetch order/create |
11
MakHoCheung OP @dzdh 主要纠结的是多个业务操作的是同一个资源,是分开多个接口对应多个业务,还是一个接口给多个业务共用。前者简单清楚,但是要维护多个接口,后者接口少但是内部逻辑就复杂,维护起来也难受
|
12
boolstone 2022-05-23 14:01:52 +08:00
看下 restful 吧
|
13
vikaptain 2022-05-23 15:19:10 +08:00
@MakHoCheung 我倾向于分多个接口,一个接口就干一个接口的事情。一个接口到后面会越来越恶心,自己都不想去动。
|
14
MakHoCheung OP @boolstone 了解 restful ,我说的面向资源说的就是类 restful ,当然我们不允许用 restful ,post 一把梭
|
15
MakHoCheung OP @vikaptain 同感恶心,按一楼说的在复杂场景分接口出来了
|
16
fivesmallq 2022-05-23 16:19:22 +08:00 1
对资源设计不清晰,order 和 address 属于不同的资源,如果是修改用户的配送地址 put /users/:userId/address/:addressId 如果是修改某个订单的地址 put /orders/:orderId/address ,address 一般有单独的维护页面,用户可以管理自己的多个配送地址,这个地方是有 address id 的,而下单后,address 信息会固化一部分到订单中,用户有临时修改这个订单地址的时候,一般来说就不太用 adress id 了,一般来说是收货地址,如果是多个地址,那么也可以在 path 上再区分
|
17
jatsz 2022-05-23 16:32:19 +08:00
楼上说的有道理,其实不管面向啥,重要的区分是修改的单个订单地址,还是修改个人常用地址。从 API 使用者的角度让两个操作变得明确。
|
18
dcsuibian 2022-05-23 16:44:41 +08:00
个人喜爱的偏 restful 的方法:
http patch 方法(代表部分更新), /orders/{id} ,然后发送的 JSON 字符串大概是:{"address":"新的地址信息"} 后端收到 JSON 字符串后,反序列成 Order 对象,此对象除 address 属性外都为 null ,只有不为 null 的字段认为要修改,这样就可以了。 缺陷就是没有办法直接把一个字段设置为 null 。 |
19
dcsuibian 2022-05-23 16:47:30 +08:00
如果要显式设置为 null 的话
① PUT 方法 /orders/{id},代表全量修改。(个人不太喜欢,要发送完整信息,还有不一致问题) ② PUT 方法 /orders/{id}/address ,传入一个 null ③ DELETE 方法 /orders/{id}/address ,什么也不传 |
20
Chad0000 2022-05-23 16:53:06 +08:00
偏 Restful 但无需完全照搬,比如下单前检测是否可以下单是查询请求,与创建订单接口要提交的数据很接近,如果非用 Get 那么接收查询参数将是个挑战以及比较恶心。这时候"无脑"Post 就带来好处了。
|
21
MakHoCheung OP @fivesmallq 我这边举的例子就是“用户有临时修改这个订单地址的时候”,不过我也倾向你这种“put /orders/:orderId/address” 而不是“ put /orders/:orderId/”
|
22
fivesmallq 2022-05-23 23:14:27 +08:00
推荐 2 个 api 设计的指南,我会经常参考 google 的 https://cloud.google.com/apis/design?hl=zh-cn
微软 azure 的 https://docs.microsoft.com/zh-cn/azure/architecture/best-practices/api-design 另外有些场景想不太明白也会参考 https://docs.github.com/en/rest/repos/repos 和 https://docs.digitalocean.com/reference/api/api-reference/#operation/list_deployments 总是看到有人说 RESTful 不好用,复杂场景搞不定,自己思考过,参考过好的设计吗? |
23
lldld 2022-05-24 08:47:04 +08:00
这个我是分两层的.
数据表相关的用资源的方式暴露内部接口; 业务相关的用前端需要的逻辑组合内部接口, 添加逻辑, 一般都是 POST, 比如问题中这个, 接口名字可能是 /order/address/update, /updateOrderAddress |
24
MakHoCheung OP @fivesmallq 多谢
|