记因 API 第一次挨同事骂 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
unbinilium
V2EX    程序员

记因 API 第一次挨同事骂

  •  
  •   unbinilium 2 小时 54 分钟前 1025 次点击

    背景:leader 最近接手了个嵌入式上的管理后台项目,架构比较古早 Static Web <-> Nginx <-> CGI (C, via Unix Socket) <-> Backend Application (C) <-> Modules 。同事抢了前端部分的工作,我分到了和储存系统相关的后端模块。评审完原型后就开工了,我写好自己模块前端部分 API 的草案后,请前端的同事先帮我 review 一下,结果被怒批了一顿。

    从对方比较尖锐的评价里我大概总结出以下几点:

    对方观点:

    1. 我不会做项目,完成任务优先级第一
    2. 我不是产品经理,不要替产品经理操心
    3. 我是学生思维,抓不到项目重点,写出来的东西不专业他看不懂(用不惯企微文档,加上有些术语想不到中文的名字, 草案就先用 md 写了英文的)
    4. 我协作不到位,我写这部分前端接口没提前通知他(事实上一起开会时我不仅说了,还把规划写在白板上了)

    对方理由:

    1. 他也写了这部分 API ,比我的简单很多;我的命名不符合他的规范(这点在 review 前就提醒了,我的出发点是先确定数据结构上有没有分歧,之后命名样式一定会按照他的要求改好)
    2. 他自称写过很多爬虫,也写过前端(他本职做 AI 算法的,211 硕)
    3. 不能反映到前端原型的字段上就别加,不要自作聪明以为其他人没想到
    4. 一年前上司曾批评过我过度设计,效率低

    事后也虚心看了下他写的 API ,这里仅以我的视角总结一下他的思路(因保密协议就不贴代码了):

    1. 前端页面下一个子组件对应到一个 endpoint ,不再分级,组件全部信息放在一个相同的 JSON schema 里就好
    2. 根据请求类型,后端自动去 request payload 里找需要的字段用或选择性更新 response body 里的部分字段
    3. 对于一个组件内部依赖其它组件信息或状态的情况,后端应该在这个组件的 API endpoint 里也提供
    4. 不假定某个地方需要扩展,不加冗余信息,产品有需求再改,总有办法能在现有接口上承载起新需求(顶多可能会让接口变得奇怪)

    下面说一下这部分我的观点(个人职场新人,非 CS 专业,目前也就做做 embedded infra ,这方面可能不专业):

    1. 前端原型里部分组件 anti-pattern 的迹象很明显,一个模块里揉合状态信息、配置信息和控制指令,我倾向做 decomposition 拆到该 endpoint 的子路径里做(我很难接受前端把这种模式通过 API 扩散给后端)
    2. 跨组件的状态信息,前端这边去调用对应的其它 API 处理,我的组件接口只维护生命周期在我模块内的信息
    3. 在后端仅读 payload 的数据结构上做扩展冗余,及 response 里加一些未来可能用上的信息,不会对前端解析处理增加太多负担(私有 C/S 场景也不必拮据带宽成本)
    4. 我的模块 leader 限制 C/C++/Rust 实现,一致性和 forward compatibility 比提前出第一阶段 demo 重要,未来有新需求需要调整数据结构或者实现时,改起来熵太高(后端规模远大于前端 / 前端 JS 解 JSON )

    其它的一些想法:

    1. 在设计和评审产品原型时,从时间和交互维度审视十分重要(这次其实原型就有问题)
    2. 产品经理几乎完全决定了一个产品的命运,很多时候向前端开发推进,需要先让产品经理认识到这个设计有问题(直接告诉前端要多点工作量可能挨骂)
    3. 理想主义在职场很难行得通,某种程度上我发展得的比我同事差(比较看 leader 和项目的 context 就是了,这点确实我做得不好)
    4. 即使我的主张合理,说服了大家做对的事情往往得不到任何好处,分外的事情,让市场和用户差评教产品做事就够了(自由市场也可能首先打我的脸)
    5. 和人交好很难,这件事看出同事应该是对我有不少意见,但是自己实在想不到哪里得罪了人家(感觉很多时候我已经比较注意了,比如有些会影响到大局的细节问题在评审时我想提一下,但觉得在那么多人的会上说可能不合适,毕竟我不是产品也不是设计,leader 也没开口,也是后面单独找产品旁敲侧击让他意识到有问题)

    也想听听大家的建议(比如技术方面或为人处事方面)

    嗯,再补充一些细节吧:

    1. 产品经理能 vibe coding 把原型网页做出来(虽然很粗糙),我模块的原型有问题要改结果一个星期还没改好,于是定接口时同事拿有问题的原型跟我对峙(产品想学习我理解,不过既然项目赶时间,老老实实上个 Figma 或者什么的不好吗)
      1. 原型里显示一个可能包含几十万个文件的文件夹没有分页,不加排序、过滤和搜索的情况下,期望用户能一下子找到自己想要的文件
      2. 原型过于简化,将操作/状态隐含在数据对象内,比如用户想临时关闭日程功能,做法是把之前辛辛苦苦写好的日程都删掉
    2. 同事写的 API 规范中,很多字段应该是谷歌翻译的(概念不合适且有不少拼写错误),以及他开始打算 HTTP 明文传输密码,后面其他人说不安全换成了传密码的 sha256 (不加 salt 和开始有什么区别...)

    (应该还有不少,就不浪费社会资源吐槽了)

    12 条回复    2025-10-19 18:11:04 +08:00
    lymanbernadette6
        1
    lymanbernadette6  
       2 小时 35 分钟前   1
    他行,让他来。
    他不给你发工资,你能挨他骂? 如果是好好说话,就好好探讨问题, 上来给你上强度就别惯着。
    chachi
        2
    chachi  
       2 小时 21 分钟前
    你们没研发经理?
    dsw0719
        3
    dsw0719  
       2 小时 20 分钟前
    你在工作中不发火就是不会工作。懂吗?别管对不对。下次他大声说你,你就加更大的声音顶回去。
    SGL
        4
    SGL  
       1 小时 33 分钟前   1
    朋友来了有酒肉,敌人来了有猎枪。
    rabbbit
        5
    rabbbit  
       1 小时 30 分钟前
    字太多看的脑壳痛,谁来总结下重点.
    意思是你想按功能分 api,前端想按他前端组件分 api?

    随便举个例子啊,有个页面里需要: 用户信息和商品列表.
    你的: 分两个 api 用户信息和商品
    他的: 调一个 api 把用户信息和商品给他
    Biem
        6
    Biem  
       1 小时 20 分钟前
    j 工是这样的。
    rabbbit
        7
    rabbbit  
       1 小时 7 分钟前
    上面理解错了,只是前端也把一部分接口写了.

    工作么,这玩意商量着来.
    特别是什么内部的 xx 管理系统,没人关心这玩意咋设计的.
    前端忙就后端多写点聚合的接口免得前端调来调去.
    后端忙就前端多调几次接口.
    实在解决不了那找领导.
    vonfry
        8
    vonfry  
       55 分钟前
    > 前端页面下一个子组件对应到一个 endpoint ,不再分级,组件全部信息放在一个相同的 JSON schema 里就好
    > 根据请求类型,后端自动去 request payload 里找需要的字段用或选择性更新 response body 里的部分字段

    听起来很像 graphql 的想法,如果要用 json 也有类似的框架。简单来说就是后端不把功能拆得非常细,而是由前端来控制数据的获取,这样其实对迭代会比较简单,后续维护很多需求可能都不用过后端。不过就是初期开发会有点成本,用框架的话会好一点。

    > 一年前上司曾批评过我过度设计,效率低

    我觉得得看人和项目。对很多企业来说,产品能跑就行,根本不关心内部质量。以技术角度来说我个人认为不可取,企业内,你自己想明白就行。我觉得满足自己最重要,再严重也就是丢份工作而已。

    > 他自称写过很多爬虫,也写过前端(他本职做 AI 算法的,211 硕)
    > 前端原型里部分组件 anti-pattern 的迹象很明显,一个模块里揉合状态信息、配置信息和控制指令,我倾向做 decomposition 拆到该 endpoint 的子路径里做(我很难接受前端把这种模式通过 API 扩散给后端)

    和学历无关,身边统计学。国内前端、AI 出身的大部分不关注代码质量。另外做过什么并不能说明代码能力。何况爬虫这种又是调库为主的;并不是去维护了爬虫库,做了很复杂的反爬,或是有很好的性能调优或者架构。说明不了什么。
    vonfry
        9
    vonfry  
       52 分钟前
    你有 leader ,也提了前身兼容这种要求。那么你应该和 leader 多沟通,确认技术细节。
    另外开会说的东西遗忘还蛮正常的,毕竟那么多内容,一般都主要关心自己的部分。这种会后开工前要对接的,提供沟通会比较合适。
    kneo
        10
    kneo  
       50 分钟前 via Android
    朋友,我看前面感觉可能是作为新员工的你太优秀了遭到同事妒忌。但是怎么感觉你写着写着就跑题了呢。不是很明白你要表达的重点。也不知道怎么回复。
    bbbblue
        11
    bbbblue  
       48 分钟前
    他这个应该是前端也写的菜 所以最好你一个接口就对应他页面/组件里全部数据吧
    数据组装全都在后端做 后面前端改后端跟着改

    你和他互换一下 你写前端 他写后端 搞不好就要反过来了

    他这个评价标准就是你们都要配合他 他怎么简单怎么来
    unbinilium
        12
    unbinilium  
    OP
       1 分钟前
    @rabbbit 是的,这是第一个分歧点,我比较 RESTful ,endpoint 想做成 `/{组件}/{功能}`

    第二个分歧点在 payload 部分,比如一个划定时间段的日程组件(`.../schedule`),对方倾向平铺 `{"monday":[{...},...],"tuesday":[...],...}`, 我是倾向规则化 `{"weekly":[{...},...],"exceptions":[...],...}`

    以上两个分歧延伸到了其他接口上,再举个例子就是磁盘管理组件:

    - 显示当前可用的磁盘、每个磁盘的状态
    - 用户对磁盘的配置(配额、清理策略等)
    - 用户执行的操作等(挂载、格式化等)

    由于上面几点在原型里比较模糊,产品迟迟没有给出确定的需求,我就自己打了个草稿:

    - 按功能把 endpoint 分了两级
    - response body 按磁盘->分区做了结构化的组合,然后加了一些冗余字段
    - 比如状态机区分:错误/格式化中/未挂载/正常/同步中/索引中
    - 状态机的冗余属性:格式化中状态下代表格式化进度(类型不变)
    - revision:用于将状态机与用户行为同步,比如用户请求格式化,重命名等( POST 非幂等)
    - 其他冗余字段如当前分区格式等...

    可能对比现有的原型确实复杂了点,之前确实也没这方面的项目经验
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2523 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 21ms UTC 10:12 PVG 18:12 LAX 03:12 JFK 06:12
    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