V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
MakHoCheung
V2EX  ›  问与答

请教一下大佬们怎么设计接口

  •  
  •   MakHoCheung · 2022-05-23 10:50:50 +08:00 · 2253 次点击
    这是一个创建于 914 天前的主题,其中的信息可能已经有所发展或是发生改变。

    是面向业务设计接口还是面向资源设计接口

    比如一个订单表包含有地址信息,修改地址这么一个需求,设计接口一般是 /updateAddress 还是 /updateOrder 呢,如果用 /updateOrder 的话后续更新订单其他信息也可以复用这个接口,但是更新订单信息可能当前业务只开放修改部分信息,所以接口里面做校验的逻辑就复杂了很多,如果用 /updateAddress 的话接口会越来越多,也增加测试的工作量

    大佬们有何见解

    24 条回复    2022-05-24 09:18:39 +08:00
    mokeyjay
        1
    mokeyjay  
       2022-05-23 11:00:18 +08:00
    简单的项目面向资源,复杂的项目面向业务。也可以主面向资源,部分逻辑复杂的接口面向业务
    可以看看 restful 规范,但不要死板遵循。复杂项目没法完全 restful
    dzdh
        2
    dzdh  
       2022-05-23 11:05:21 +08:00
    个人喜欢 post /order/update {address_id:id}
    kaiki
        3
    kaiki  
       2022-05-23 11:06:57 +08:00
    要不折中一下,用 /update/address
    luckyrayyy
        4
    luckyrayyy  
       2022-05-23 11:08:07 +08:00
    同意楼上,不过 PATCH 请求应该更好?
    luckyrayyy
        5
    luckyrayyy  
       2022-05-23 11:08:25 +08:00
    完了被插楼了,我是说 2 楼
    MakHoCheung
        6
    MakHoCheung  
    OP
       2022-05-23 11:18:19 +08:00
    @mokeyjay 有道理
    MakHoCheung
        7
    MakHoCheung  
    OP
       2022-05-23 11:19:11 +08:00
    @dzdh address 没跟 order 分开,所以没有 addressId ,不过你这种想法应该就是面向业务了
    potatowish
        8
    potatowish  
       2022-05-23 12:32:22 +08:00 via iPhone
    可以用一个接口,比如 /updateOrder
    通过类型来判断具体要修改的信息
    {type:"address"}
    dzdh
        9
    dzdh  
       2022-05-23 12:37:55 +08:00
    @MakHoCheung 看咋说。设计个接口没有业务调用你设计他干啥 (doge
    8520ccc
        10
    8520ccc  
       2022-05-23 12:44:48 +08:00 via iPhone   ❤️ 1
    order/update
    order/delete
    order/fetch
    order/create
    MakHoCheung
        11
    MakHoCheung  
    OP
       2022-05-23 13:15:57 +08:00
    @dzdh 主要纠结的是多个业务操作的是同一个资源,是分开多个接口对应多个业务,还是一个接口给多个业务共用。前者简单清楚,但是要维护多个接口,后者接口少但是内部逻辑就复杂,维护起来也难受
    boolstone
        12
    boolstone  
       2022-05-23 14:01:52 +08:00
    看下 restful 吧
    vikaptain
        13
    vikaptain  
       2022-05-23 15:19:10 +08:00
    @MakHoCheung 我倾向于分多个接口,一个接口就干一个接口的事情。一个接口到后面会越来越恶心,自己都不想去动。
    MakHoCheung
        14
    MakHoCheung  
    OP
       2022-05-23 16:00:57 +08:00
    @boolstone 了解 restful ,我说的面向资源说的就是类 restful ,当然我们不允许用 restful ,post 一把梭
    MakHoCheung
        15
    MakHoCheung  
    OP
       2022-05-23 16:02:02 +08:00
    @vikaptain 同感恶心,按一楼说的在复杂场景分接口出来了
    fivesmallq
        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 上再区分
    jatsz
        17
    jatsz  
       2022-05-23 16:32:19 +08:00
    楼上说的有道理,其实不管面向啥,重要的区分是修改的单个订单地址,还是修改个人常用地址。从 API 使用者的角度让两个操作变得明确。
    dcsuibian
        18
    dcsuibian  
       2022-05-23 16:44:41 +08:00
    个人喜爱的偏 restful 的方法:

    http patch 方法(代表部分更新), /orders/{id} ,然后发送的 JSON 字符串大概是:{"address":"新的地址信息"}

    后端收到 JSON 字符串后,反序列成 Order 对象,此对象除 address 属性外都为 null ,只有不为 null 的字段认为要修改,这样就可以了。

    缺陷就是没有办法直接把一个字段设置为 null 。
    dcsuibian
        19
    dcsuibian  
       2022-05-23 16:47:30 +08:00
    如果要显式设置为 null 的话
    ① PUT 方法 /orders/{id},代表全量修改。(个人不太喜欢,要发送完整信息,还有不一致问题)
    ② PUT 方法 /orders/{id}/address ,传入一个 null
    ③ DELETE 方法 /orders/{id}/address ,什么也不传
    Chad0000
        20
    Chad0000  
       2022-05-23 16:53:06 +08:00
    偏 Restful 但无需完全照搬,比如下单前检测是否可以下单是查询请求,与创建订单接口要提交的数据很接近,如果非用 Get 那么接收查询参数将是个挑战以及比较恶心。这时候"无脑"Post 就带来好处了。
    MakHoCheung
        21
    MakHoCheung  
    OP
       2022-05-23 21:58:06 +08:00
    @fivesmallq 我这边举的例子就是“用户有临时修改这个订单地址的时候”,不过我也倾向你这种“put /orders/:orderId/address” 而不是“ put /orders/:orderId/”
    fivesmallq
        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/reposhttps://docs.digitalocean.com/reference/api/api-reference/#operation/list_deployments

    总是看到有人说 RESTful 不好用,复杂场景搞不定,自己思考过,参考过好的设计吗?
    lldld
        23
    lldld  
       2022-05-24 08:47:04 +08:00
    这个我是分两层的.
    数据表相关的用资源的方式暴露内部接口;
    业务相关的用前端需要的逻辑组合内部接口, 添加逻辑, 一般都是 POST, 比如问题中这个, 接口名字可能是 /order/address/update, /updateOrderAddress
    MakHoCheung
        24
    MakHoCheung  
    OP
       2022-05-24 09:18:39 +08:00
    @fivesmallq 多谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5152 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 09:31 · PVG 17:31 · LAX 01:31 · JFK 04:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.