代码审查不是挑刺,是“代码人生”的修行

运营说要今天
2025-12-18 12:17
阅读 702

上周五晚上十点半,我盯着 MacBook Pro 的屏幕,一边喝着已经凉透的冰美式,一边在 GitLab 上 Review 一个后端同事提交的 PR。PR 里有个看似无伤大雅的小改动:把某个接口的 GET 请求改成了 POST。理由写得冠冕堂皇:“为了兼容未来可能的复杂参数”。但我知道——这背后是某位产品经理临时加了个需求,还号称“就改一行代码”,结果后端兄弟被迫重构了半个 Controller。

我当时差点想直接 comment:“你确定这不是在埋雷?”但手指停在键盘上几秒后,我还是删掉了那句带刺的话,换成了:“建议评估是否真的需要 POST,如果只是参数变多,可以考虑 query string + DTO 校验,避免破坏 RESTful 约定。”

写完这句话,我突然意识到:从当年那个天天被开发怼“需求不闭环”的产品经理,到现在坐在工位上边刷 LeetCode 边 Review 代码的技术人,我对“代码审查”这件事的理解,早就变了味儿。


转型之后,才懂 PR 不只是过流程

三年前,我还在会议室里拿着 Figma 原型跟开发拍桌子:“这个动效必须要有!用户感知很强!” 那时候我以为代码就是实现 UI 的工具,Review?那是测试和 QA 的事吧。

直到自己亲手写了第一个 React 动画组件,发现 requestAnimationFrame 没清理导致内存泄漏,线上页面卡成 PPT;又因为一个没处理的 Promise rejection,让整个 SPA 白屏——我才真正明白,每一行代码背后,都是真实用户的时间、耐心,甚至是信任

现在作为前端兼一点后端(对,斜杠青年就是这么硬核),我参与的项目节奏快得像打仗。上个月双11大促前一周,我们团队同时推进三个 Feature,每个 PR 都带着“今晚必须合进主干”的 deadline 标签。压力山大,但越是这种时候,越不能跳过 Code Review。

为啥?因为没有 Review 的代码,就像没系安全带就飙车——一时爽,出事全家哭


我们团队的 Code Review “潜规则”

我不是在大厂,也不是在硅谷,就是一个二线城市中等规模的 SaaS 公司。但我们对 Code Review 的态度,比很多所谓“敏捷”团队认真得多。这里没有形式主义,只有血泪教训总结出来的几条“潜规则”:

1. 不审逻辑,只审边界

后端同事最烦那种上来就改命名风格的 Reviewer。我们约定:除非影响可读性或违反团队规范,否则不纠结变量名。重点看:

  • 异常处理是否完备(特别是数据库连接超时、第三方 API 失败)
  • 是否有潜在的 N+1 查询
  • 权限校验有没有漏掉(别笑,去年真有人忘了加 @PreAuthorize,导致普通用户能删管理员账号)

举个真实例子:有次一个同事写了个批量导出接口,本地测试跑得好好的,但上线后 CPU 直接飙到 90%。Review 时我发现他用了 findAll() 再 in-memory 过滤——数据量小的时候没问题,一旦客户有上万条记录,服务器直接原地升天。改成分页 + 流式写入后,问题迎刃而解。

2. 动画和交互,也要写进 Review 清单

作为曾经的产品经理,我现在特别关注前端交互细节。比如:

  • 按钮点击后有没有 loading 状态?
  • 错误提示是不是用户能看懂的(而不是“Error 500”)?
  • 动画是否会造成布局抖动(layout shift)?

有一次我 Review 一个表单提交的 PR,发现同事用 opacity: 0 隐藏错误信息,但 DOM 依然占位。结果用户输入错误时,下面的按钮突然“跳”了一下。我直接 comment:“这体验会让我当年的 PM 自己砸自己电脑。” 后来改成 display: none + 过渡动画,丝滑多了。

3. 拒绝“LGTM”文化

“Looks Good To Me” 是 Code Review 最大的毒瘤。我们团队明令禁止这种敷衍行为。如果你没时间细看,就直接说“今天太忙,明天上午再 Review”,而不是点个赞完事。

我甚至在 .gitlab-ci.yml 里加了一条规则:PR 至少需要两个 Approve,且其中一个必须来自不同模块的开发者。强制跨职能视角,避免“自己人护短”。


后端代码的那些“隐形坑”

虽然我现在主攻前端,但因为项目架构是 BFF(Backend For Frontend),我也要写不少 Node.js 接口。这让我对后端代码的 Review 有了新视角:

问题类型 新手常见写法 推荐做法
数据库查询 User.find({}) 全查 用分页 + 字段白名单限制
日志记录 console.log() 结构化日志(如 pino)+ 关键 traceId
错误处理 try/catch 后 return null 统一错误中间件 + HTTP 状态码映射
安全校验 信任前端传参 DTO 校验(class-validator)+ 敏感操作二次确认

最让我后怕的一次,是看到一个 PR 里直接拼接 SQL 字符串:

// 千万别学!
const sql = `SELECT * FROM orders WHERE user_id = ${userId}`;

我当场冷汗直流,在评论里贴了 OWASP Top 10 链接,并附言:“兄弟,咱公司还没富到能请得起危机公关团队的地步。”


代码人生:从“交付功能”到“交付责任”

说实话,准备跳槽这段时间,我刷了很多系统设计题,也重读了《重构》《Clean Code》。但真正让我成长的,不是算法题 AC 了多少道,而是每一次认真 Review 别人代码时,对自己写的代码也多了一份敬畏

Code Review 不是找茬,而是一种协作式的代码冥想。你在看别人如何思考问题、如何权衡取舍,也在反思自己会不会犯同样的错。

记得上个月,我提交了一个 WebSocket 心跳机制的 PR,自认为逻辑严密。结果一位资深后端同事指出:“如果客户端网络抖动,连续发两个心跳包,你的状态机可能会进入非法状态。” 我当时愣住——完全没考虑到并发场景。那一刻,我真心感谢他,而不是觉得被冒犯。

优秀的团队,不是没有 Bug,而是 Bug 在合并前就被温柔地揪出来


给正在刷题跳槽的同行一句真心话

如果你也在边工作边准备面试,别只盯着 LeetCode。花点时间好好 Review 代码,尤其是那些你觉得“写得比我好”的人的代码。你会学到:

  • 如何用最小改动解决复杂问题
  • 如何写出让三个月后的自己也能看懂的注释
  • 如何在 deadline 和代码质量之间找到平衡点

这些,才是面试官问“你有什么开发心得”时,你能掏出的真家伙。


最后,分享一个小习惯:每次 Review 完一个 PR,我会在 Notion 里记下一条“今日收获”。比如:

2024-06-14:学习了同事用 Zod 做运行时校验的方式,比 Joi 更轻量,下周试试迁移到我们的 API 层。

积少成多,这些碎片最终会拼成你的代码人生地图

所以,下次当你打开一个 PR,别急着点 approve。泡杯咖啡,深呼吸,然后告诉自己:

这不是在挑刺,这是在守护我们共同构建的世界。

毕竟,每一行被认真对待的代码,都是对用户、对团队、对自己的尊重

(完)

P.S. Windows 用户别打我——我确实只用它测 IE11 兼容性,然后立刻切回 Mac。谁让我是个“有原则”的斜杠青年呢 😉

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝