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

后端接口一定要保持单一职责吗

  •  
  •   chenxiaolani · 85 天前 · 6216 次点击
    这是一个创建于 85 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前干前端的时候遇到一个需求就是需要用表格展示一些订单或者商品信息,但是跟我对接的后端哥们让我从两个接口拿。但是我想让他再单独出一个接口直接返回我所有的信息,这样我就不用请求两次接口再拼装展示到表格中; 我的想法就是: 单独一次的请求肯定比两次性能好,万一有一个请求嘎了或者慢了, 表格数据就加载慢或者不出来了。

    后端那哥们的想法是:接口需要保持单一职责,再单独出一个接口就重复了。

    当时刚到那家公司,也没劲跟这哥们扯犊子,不过他给的理由我也无办法反驳,但是我感觉我的想法也是对的。

    大佬们遇到这种情况,最佳的做法应该是咋样的啊。

    55 条回复    2024-09-10 10:32:59 +08:00
    esee
        1
    esee  
       85 天前 via Android   ❤️ 5
    前后端都写的人表示,还是分成两个接口吧,你写代码都要解耦,请求接口不也一样嘛,如果拼接成一个接口然后这个接口只能这个功能专用也不合适吧?你请求的时候可以并发请求,又不是非得一个一个进行
    goodSleep
        2
    goodSleep  
       85 天前 via Android
    接口是要保持单一职责,但是也可以抽一层 api 出来 聚合后端接口;毕竟后端之间走内网,前后端走公网
    nikenidage1
        3
    nikenidage1  
       85 天前
    所以,才有了 BFF
    https://bff-patterns.com/
    Mithril
        4
    Mithril  
       85 天前
    要么你前端老大撕逼能力强,让后端根据你前端 ViewModel 写一堆聚合接口

    要么你推后端去用 GraphQL ,虽说如果真的按照它去设计,很多时候这玩意很难用,但你用它包一下,一次请求调俩接口还是很容易的。

    但对于后端来说,不去维护多个功能过于类似的接口是基本素养。
    IvanLi127
        5
    IvanLi127  
       85 天前
    需要,除非你现在开发的项目是后端的唯一前端。
    ShuWei
        6
    ShuWei  
       85 天前
    标题的结论应该是“尽可能”,不过你的场景中,你没有说清楚具体的内容,其实很难判断到底后端所谓的单一职责,划分是否合理,不少后端其实爱把一些本来应该更紧密耦合的东西,强行分开,就为了自己有时候更简单而已
    GeekGao
        7
    GeekGao  
       85 天前   ❤️ 1
    架构的魅力:平衡的艺术,在不同需求之间找到平衡点非常重要。
    billzhuang
        8
    billzhuang  
       85 天前 via iPhone   ❤️ 1
    如上所述,BFF 就是干这个的,GraphQL 也可以解决。

    “ 单独一次的请求肯定比两次性能好,万一有一个请求嘎了或者慢了, 表格数据就加载慢或者不出来了。” 这个想法经不住盘问。
    tairan2006
        9
    tairan2006  
       85 天前 via Android
    写个聚合接口就完了
    way2create
        10
    way2create  
       85 天前
    之前有前端要求我每个 api 接口对应页面让他不用动脑,我是按功能模块划分的,还说这样网络请求少性能好,但这个小项目不要求性能,使用的人很少,字段很少也有文档,同样的 api 接口不同页面都有调用。
    不过我这个情况本质是他在摸鱼搞外包。。。
    fffq
        11
    fffq  
       85 天前
    虽然耦合了很多业务,但是职责很单一,以后就只有这个用途,符合单一职责[狗头]。
    lizy0329
        12
    lizy0329  
       85 天前
    这就是 curd boy 的作用了,拼好后给前端
    xiangyuecn
        13
    xiangyuecn  
       85 天前
    盲猜,java ,不让用 map ,傻逼设计:要多加个不同字段,就得去改定义所在的 java 文件,或得增加一个 java 文件
    sagaxu
        14
    sagaxu  
       85 天前
    “单独一次的请求肯定比两次性能好,万一有一个请求嘎了或者慢了, 表格数据就加载慢或者不出来了。”

    单元素接口重复请求 n 次,跟批量请求一次,这种场景你的理由才站得住脚。设计上,接口之间要有正交性,也就是单一职责。

    以前有些互联网公司,会招一些人,干聚合 API 的事情,通常是 PHP 岗,调内部(那时还不叫中台)服务接口,稍加处理返回给前端,甚至直接 PHP 输出 html 。
    zoharSoul
        15
    zoharSoul  
       85 天前
    bff 就干这个的
    hefish
        16
    hefish  
       85 天前
    看业务有多大。 如果是个高达 100 个账号用的系统,还是可以的。
    Kenyore
        17
    Kenyore  
       85 天前
    后端接口确实时单一职责,不过可以有个聚合服务做拼凑。具体还是看公司习惯
    Orlion
        18
    Orlion  
       85 天前
    以“前端按照业务逻辑状态渲染按钮”这个场景来说,以前可能喜欢返回一个 status 字段让前端根据 status 的不同值渲染不同样式的按钮。后来发现这种玩法前端经常来问字段含义,我还要结合需求给前端讲解,跟对端扯皮的功夫可能自己都做完了。
    现在学聪明了,直接把渲染按钮需要的按钮文案、颜色之类的东西都给前端返回,就很少跟前端扯皮了,节省了大量的时间哈😄
    Foxkeh
        19
    Foxkeh  
       85 天前
    这个分歧结果就是要么尽可能快的展示部分数据并逐步展示完整, 要么一次性展示所有数据.
    如果接口性能好的话对用户来说感知不大, 如果部分性能不佳的话,性能最差的那部分就是瓶颈.

    建议找技术主管拍板,谁拍板谁担责(虽然最后擦屁股的还得是一线开发)

    我参与过的项目:两种实现都有. 有的是考虑解耦和复用就单独写,有的是考虑几种数据只会在一种统计页面展示就聚合到一起, 业务上没有绝对的界限说必须用哪种.
    其他人的:多年前听说过雅虎的设计是尽可能一次返回减少 IO,这会儿没找到原文不知道说的啥场景.
    sophos
        20
    sophos  
       85 天前 via iPhone
    https://github.com/sysulq/graphql-grpc-gateway

    所以我试着做了一个 graphql 转 grpc 的网关,各个模块提供 grpc 接口即可,在网管层合并为 graphql ,端上可以根据需求自行选择接口聚合
    chenxiaolani
        21
    chenxiaolani  
    OP
       85 天前
    @nikenidage1 @billzhuang @zoharSoul 好像想起来我之前呆过一家公司后端 php,但是前后端之间加了一层 node,前端只请求 node 服务,node 再调 php,这里 node 就是 BFF 层吧。
    Irisxx
        22
    Irisxx  
       85 天前
    我就是因为和你碰到一样的问题,自己学 Node 写了聚合 ,挺方便的,求人不如靠自己。
    zoharSoul
        23
    zoharSoul  
       85 天前
    @chenxiaolani #21 嗯 或者说业务网关层. 一般都有这种玩意. 同语言的, 不同语言的. 有团队是前端负责, 有团队是后端写...
    反正都少不了这个东西把各个服务的接口聚合后丢出去...
    flmn
        24
    flmn  
       85 天前
    如果你的前端是 web ,那么尽量保持单一职责;如果你的前端是 app ,那么尽量合并接口( bff )。
    说来说去,还是看前后端谁能说服谁。
    chenduke
        25
    chenduke  
       85 天前
    所以一个项目需要一个技术负责人去平衡技术实现的一些细节。 不然前后端分离导致的前后端经常撕逼的问题基本无解。 毕竟但凡有点老资格或者工作久点的程序员都想装逼。
    lux182
        26
    lux182  
       85 天前
    这里还是初级程序员多啊
    zbowen66
        27
    zbowen66  
       85 天前
    这无所谓吧,不是你拼就是他拼,我更倾向于 API 解耦。在前端封装一个函数调用多个 API 不就行了。
    laminux29
        28
    laminux29  
       85 天前   ❤️ 1
    因为要处理性能问题,计算机里有大量违反原则的事情,比如 CDN 、Cache/Buff 、各种冗余比如表字段冗余等等。

    楼主要多思考。
    jonsmith
        29
    jonsmith  
       85 天前
    当有话语权时,坚持接口单一职责;当只是个 curd boy 时,大佬们需要什么数据我返什么数据,复制粘贴多大点事。

    技术从来不是单纯的技术,要保持灵活性,因人而异。
    huangzhiyia
        30
    huangzhiyia  
       85 天前 via iPhone
    后端一个 API 对应只有一个项目一个功能的场景随意

    可是真实场景哪有这么简单,一般都是对应几个服务或者几个前端依赖这个 API

    某个前端偷懒说这不合理要求改动 API 这不是疯了

    除非有重大性能问题或者业务破坏性变更,前端能自己处理就自己处理

    处理不了的再和后端商量专门写一个新接口

    下线一个 API 都要看过去七天甚至一个月半年有没有请求记录才敢下线。

    已经部署到生产环境的 API 轻易不要妄动
    kyznever
        31
    kyznever  
       85 天前
    作为前后端都写的研发,从我个人思考和实践出发而言

    先说做法:

    - 后端 Controller 层:原先两个 Controller 保留,此外我会新增一个聚合的 Controller ,然后新的 Controller 基于原先两个 Controller 的具体实现。

    原因:
    1. 如果我们的前端是多端多服务的,我写一次,各个前端( Web 、APP )其实不用做多次重复的工作
    2. 假设一个 http 网络请求在联通中只有 99% 的成功率,这个聚合 API 是 3 个 API 组合而成的。那么成功率一个是 99%,一个是 0.99 * 0.99 * 0.99 = 97%
    nino
        32
    nino  
       85 天前   ❤️ 3
    他没理解什么叫单一职责,这说的都不是一个“接口”,你们碰到的接口是 API endpoint ,实际上这个原则说的是 Interface ,Interface 当然要单一职责
    Bingchunmoli
        33
    Bingchunmoli  
       84 天前 via Android
    @GeekGao 我觉得不一定对,因为有的单个接口是一个接口实现了多个接口的功能,那么业务代码可能是耦合的导致维护难度和复杂度更高的可能
    Bingchunmoli
        34
    Bingchunmoli  
       84 天前 via Android
    @xiangyuecn 建议全用 any
    xomix
        35
    xomix  
       84 天前
    人一定要吃的健康吗?我就喜欢吃烧烤。但是聚餐考虑就是大家协商解决。
    dif
        36
    dif  
       84 天前
    这是理想情况,我自己会坚持单一原则,但实际上 6 成以上的接口都不是单一的。业务决定的,没办法。真要坚持单一原则,那接口数量大约要膨胀 5 倍。前端不乐意了。
    yrj
        37
    yrj  
       84 天前
    @kyznever 作为全栈,也比较赞同你的说法,还有一种情况上,前后端分离下,一个页面要做 ssr ,多次请求会增加 http 连接,性能上也会有些影响。
    dcdlove
        38
    dcdlove  
       84 天前
    简直就是荒谬,一天天堆屎还堆出优越感了,接口不能满足前端就是垃圾,你就是吃这碗饭的,写不出来满足不了就是自己能力不行,别给自己找借口,拿什么规范原则做挡箭牌,真是丢死人,不行就转行挑大粪去
    GeekGao
        39
    GeekGao  
       84 天前
    @Bingchunmoli 没有对错之分,如果实在纠结,那可以从当前人力配备和项目时间管理的角度来看问题。
    justdoit123
        40
    justdoit123  
       84 天前   ❤️ 4
    这种不能简单通过谁方便、请求多少来考量。举个例子。

    复杂详情页面。比如,商品的详情页面。

    详情页面大概会有如下内容:
    a. 商品自身的信息;
    b. 优惠 & 活动;
    c. 评论(列表);
    d. 相关推荐(列表)。

    这时候后端是只给你一个接口好,还是分多个接口去请求好?

    从用户的体验来讲,最好先快速加载并渲染出商品信息、优惠信息。其次才是热评、最后是相关推荐。

    我个人认为,这种场景真的只用一个接口的话。体验大概率会比较差。分成多个接口,各自加载、渲染可能会更好。那些评论、相关推荐的数据大概率没有商品自己的信息加载来得快。
    Peachl
        41
    Peachl  
       84 天前
    @dcdlove 那我就要说凭什么满足你前端了 数据是我从数据库拿的 你前端这么牛逼 你也去从数据库捞去吧 反正接口我给了 你爱用不用
    zu1y
        42
    zu1y  
       84 天前   ❤️ 1
    领域层提供原子服务接口,应用层提供业务编排接口。

    如果他是一个项目里直接从 HTTP API 干到数据库,我的建议是直接跑路
    samnya
        43
    samnya  
       84 天前
    如果后端不是响应式的话,后端聚合会不会还慢一点?
    因为服务端做并发查询还需要额外写代码,但前端并发请求过来的话一般都分配到不同线程上处理了
    dayeye2006199
        44
    dayeye2006199  
       84 天前
    问就是 graphQL
    sunchuo
        45
    sunchuo  
       84 天前
    如果是一个数据的各种枚举的中文映射的场景。是后端不讲理,建议后端按照约定的 schema 一次返回。

    如果是两组数据。

    如果有多个前端(不是程序员,是客户端),应该更倾向于听后端的。因为不是专门伺候你。
    如果仅一个前端,可以以前端开发为主(后端开发是生产者,前端开发是消费者),谁离业务更近,谁说了算,谁责任大。别说帮忙合并数据面向页面提供接口,前端要求后端直接返回渲染好的 html 都行。
    但具体实践中大部分要看习惯和交情。


    具体情况具体分析吧。




    从 op 描述来看。
    op 更想省事,后端理由正当合理。



    我们要判断争论点是把复杂度和锅(我可以听你的这么做,但是出问题你负责)从谁转移到谁。
    争夺复杂度和锅的争论,推脱复杂度但是不甩锅的争论,大部分都是好同志。
    推脱复杂度同时也不背锅的争论,我们可以直接理解为队伍里出现了不合适的人。


    另外多说一句:
    技术团队的技术争论,
    如果有人不「站在 “整体”的位置上,看“现在”和“将来”,」
    还争个热火朝天,
    如果不是公司薪资水平不行。那要么是菜,要么是坏。
    KING754
        46
    KING754  
       84 天前
    也不一定,非要怎么样吧.

    具体不知道是一个什么样表格.

    不过,就订单或者商品信息.
    如果订单信息,一开始只展示粗略信息.(就是一开始,并不会显示所有商品,而是用户点一个详情,然后再显示)
    这种情况,我肯定是拒绝一下子,全部返给前端.

    其它情况,要商量着看吧.
    8355
        47
    8355  
       83 天前
    app 或者大模块首页接口之类的必要性大模块结构可以提供聚合,其他的接口最多提供多批量查询。
    接口性能和可靠性是后端负责的话就不可能给你这么提供,不然前后端分离意义在哪不如直接 display ?
    pxllong
        48
    pxllong  
       83 天前
    看团队 leader 的话语权了。
    MoYi123
        49
    MoYi123  
       83 天前
    感觉很多前端都会莫名其妙地追求性能, 前端代码跑在用户的设备上, 成本也不用公司出, 接口慢了也不用前端背锅, 为什么老是要用性能为理由来要求后端改接口呢?
    LitterGopher
        50
    LitterGopher  
       83 天前
    作为后端,如果你要是问我是不是一定要保持单一原则,那我会毫不犹豫的说:是。

    但我会依据情况不同改变对单一原则的认定标准(底线灵活)。
    SolaWing
        51
    SolaWing  
       83 天前
    单一职责是给内部代码维护用的,不是给外部直接调用的。单一职责的优势是可组合性非常强,代码好维护。但是如果这个接口被外部用了,以后想变就没那么容易了。给外部使用的接口应该首先保证可控,其次才考虑扩展性和灵活性。如果针对外部使用场景专门封装了场景特化接口,这个接口可以随时根据场景调整,内部的单一接口也可以随时按需重构,内部代码的可控性和外部边界都会清晰很多。
    gerefoxing
        52
    gerefoxing  
       83 天前
    视具体业务情况而定
    siweipancc
        53
    siweipancc  
       83 天前 via iPhone
    我只会给你开一个聚合接口,不保证后续兼容
    kw8023cn
        54
    kw8023cn  
       83 天前
    看数据的关联性,如果是相对隔离的数据,就分开,不然其他页面正好需要其中一个接口的数据呢,接口单一职责原则的好处不是仅仅对于这一个页面来说的,而已整个系统,职责单一的接口可以灵活的支持其他业务的需求,大接口,基本上只能满足你这一个需求。其他需求要用的话,返回的无用字段太多了。单独一次请求的性能并不一定比两次性能好或者说有感知的提升啊,都是异步并发调用,而且大多时候,观感上来说,分多个接口的效果反而更好(数据逐步渲染,但人眼看到有部分数据出来,就会觉得已经响应了)
    MYlyc
        55
    MYlyc  
       82 天前
    组里领导,前端出生,写喂饭式接口
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2609 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 10:58 · PVG 18:58 · LAX 02:58 · JFK 05:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.