上个月面试一个候选人。他带了一个 GitHub 项目,说「大部分代码是 AI 写的」。
我说没关系,打开看看。
代码确实漂亮。命名规范,类型标注完整,docstring 齐全,错误处理滴水不漏。如果这是三年前,我会觉得这是一个高级工程师的作品。但现在我知道,这些是任何一个会用 Cursor 的人都能产出的。AI 的默认输出就是 80 分——格式正确、风格一致、看起来专业。
我真正想看的东西,不在代码里。
代码是面子,harness 是里子
以前说「代码是工程师的面子」。好的代码像诗——遣词造句、起承转合、留白克制,读一遍就知道写的人是什么段位。
这个比喻有一个隐含假设: 品味是通过「写」来表达的。你的命名、你的抽象层级、你选择在哪里加一个空行——这些是签名,是笔迹。别人读你的代码,能读出你这个人。
现在 AI 写了。签名没了。
但品味真的消失了吗?
我后来让那个候选人打开他的 CI 配置。三秒钟我就知道答案了。
他的 pipeline 长这样:
lint(3秒)→ type check(10秒)→ unit test(30秒)→ integration test(2min)→ build → deploy
# generated by hugo AI
每个阶段有明确的「过/不过」判定。lint 放最前面,因为最便宜、反馈最快。你不会让一个格式问题等到 integration test 跑了三分钟之后才告诉你。
然后我看了他的 git log。每个 commit 是一个完整的、可理解的变化。从 log 里能读出这个系统是怎么一步步长出来的——先有核心模型,再有 API 层,再有错误处理,再有监控。每一步都是可工作的。
最后我看了他的 release 记录。每周一次,每次 1-3 个 feature。
代码是 AI 写的。但 这个工作台是他搭的。品味没有消失,只是搬了家。
打开一个代码库,我看什么
代码可以 AI 写,可以赶工,可以抄。但 结构性的选择——那些 AI 不会替你做、也不该替你做的决定——是品味的真正住所。
我打开一个代码库,看五样东西。
第一眼:目录结构
不是看整不整齐,是看 他怎么切这个世界。
一个做订单系统的工程师,他的顶层目录是按技术层切的(controllers/ services/ models/ utils/),还是按业务域切的(order/ payment/ inventory/)?
技术层切法说明他在想「代码怎么组织」。业务域切法说明他在想「这个系统是什么」。
品味在这里:他知道这个系统最可能沿着哪个方向变化,然后让目录结构顺着那个方向长。AI 能帮你生成任何一种目录结构,但它不知道 你的业务会怎么变。
第二眼:他不写什么
一个有品味的代码库,最显眼的特征是 克制。
没有 utils.py 三千行。没有 BaseAbstractFactoryManager。没有为了「以后可能用到」而预留的扩展点。你翻遍整个项目,找不到一个「以防万一」的抽象。
AI 特别爱生成这种东西。你让它写一个功能,它顺手给你搞个 Strategy Pattern、加个 Plugin 接口、留个 Hook。初级工程师觉得「哇好专业」,直接合了。有品味的人会说:删掉。现在不需要。
克制是品味最贵的表达。 因为 AI 让「加东西」的成本降到零,而「不加」需要判断力。
第三眼:git log
这是最骗不了人的。
代码可以 AI 写,但 commit 的粒度和演进顺序 是人的判断。什么时候重构、什么时候忍、什么时候拆分支、什么时候合——这些 AI 不替你做。
有品味的 git history 像一本书的章节。没品味的 git history 像一堆碎片:「fix」「fix again」「wip」「temp」「revert temp」。或者反过来,一个 commit 改了 47 个文件,message 写「update」。
第四眼:错误处理
不是看有没有 try-catch,是看他的 失败哲学。
他怎么定义「这个操作失败了」?是返回 null、抛异常、返回 Result 类型、还是写进一个 error channel?整个项目里这个选择一致吗?他在哪里选择让错误冒泡,在哪里选择就地处理?
这个东西 AI 生成不出来,因为它不是一个语法问题,是一个 世界观问题——你认为这个系统里,失败是常态还是例外?你认为调用者应该知道多少?
第五眼:命名
不是看变量名是不是 camelCase,是看他 怎么给概念起名字。
一个做消息系统的工程师,他管那个东西叫 message、event、notification、还是 signal?这四个词暗示了四种不同的领域模型。message 暗示有发送者和接收者。event 暗示发生了就发生了,没人订阅也得发生。notification 暗示是给人看的。signal 暗示是轻量的、可能丢失的。
有品味的人在整个项目里 只用一个词,而且选的是最准确的那个。没品味的人四个词混着用,因为他没想清楚这个东西到底是什么。
这五样东西——目录结构、克制、演进策略、失败哲学、命名——没有一样是「代码写得漂不漂亮」。全是 判断。
Harness:品味最后的堡垒
上面五样,多少还能从代码里看出来。但真正让我判断一个工程师段位的,是代码之外的东西。
我管它叫 harness——工作台。CI/CD pipeline、release 节奏、bug 曲线、事故响应。这些东西不是「代码」,是 工作方式的物化。
看 CI 的形状
不是看有没有 CI,是看 pipeline 里 放了什么、没放什么、按什么顺序放。
一个很具体的信号:CI 从 push 到反馈要多久?
5 分钟以内,说明他认真做过 pipeline 优化——并行、缓存、分层。15 分钟以上,说明他要么不在乎,要么不知道可以优化。这个时间直接决定了团队一天能迭代几次。
另一个信号:CI 是绿的,但里面有多少 @skip 和 xfail?我见过一个项目,200 个测试,60 个 skip。CI 永远是绿的。大家心照不宣地维护着一个「永远绿」的假象。这不是 CI,是安慰剂。
看 release 的频次
这是最诚实的指标。
| 模式 | 频次 | 每次 feature 数 | 说明 |
|---|---|---|---|
| 小步快跑 | 每天或每周 | 1-3 个 | 每次变化可理解,出了 bug 知道是哪个引入的 |
| 攒一坨 | 每月 | 10-20 个 | 发布日就是赌博日 |
| 恐惧型 | 每季度 | 50+ | 不敢发,因为每次发布都是一次事故 |
release 频次是恐惧的倒数。
一个团队一个月发一次版,不是因为功能多,是因为 每次发布太疼了。发布疼是因为:测试不够、回滚机制没有、监控不到位、发布流程要人肉盯。
有品味的工程师第一天就搭好「一键发布 + 一键回滚」。不是因为第一天就需要,是因为他知道一个正反馈死循环:
发布疼 → 少发布 → 攒功能 → 出大 bug → 更怕发布 → 更疼
# generated by hugo AI
打断这个循环的唯一方式,是在第一天就让发布不疼。这是一个 品味判断,不是一个技术问题。
看 bug 的曲线
每个项目都有 bug。问「你有多少 bug」没意义。有意义的是三个问题:
bug 引入到修复的时间。 有品味的团队,bug 从发现到修复是小时级。不是因为 bug 简单,是因为 harness 让定位和修复都很快——有监控告警、有日志追踪、有回滚能力、有测试覆盖。
bug 的分布。 如果 80% 的 bug 集中在 20% 的模块,说明那些模块的抽象有问题。有品味的工程师看到这个分布,会去 重构那 20%,而不是继续打补丁。
regression 的比例。 如果新 bug 里有 30% 是「修了 A 坏了 B」,说明模块耦合太紧。这不是「写更多测试」能解决的——是架构问题。
看事故之后多了什么
这是我最看的一个东西。
打开他的 postmortem 记录(如果有的话)。不是看事故多不多,是看:事故之后,harness 里 多了什么?
加了一个告警?加了一个自动化检查?加了一个回滚步骤?还是只多了一份文档,然后下次同样的事故再来一遍?
有品味的工程师,每次事故都让 harness 变厚一层。他的 CI 里那些看起来「多余」的检查,每一条背后都有一个故事:「上次因为没检查这个,凌晨三点被叫起来。」
没品味的工程师,事故之后写一份报告,开一个会,然后什么都不改。harness 永远是第一天那个样子。
AI 能写代码,不能搭工作台
回到开头那个候选人。
他的代码是 AI 写的。但他的 CI pipeline 是他自己搭的——他知道 lint 要在 type check 前面,因为上次一个类型错误让 CI 跑了四分钟才发现是一个拼写问题。他的 release 节奏是他自己定的——每周四下午发,因为周五发万一出事没人修。他的 postmortem 模板是他自己设计的——里面有一栏叫「harness 改进项」,每次事故必须填。
这些东西 AI 写不出来。不是因为 AI 不够聪明,是因为它 没有痛过。
AI 能帮你写 CI 配置文件。但它不知道 你的团队应该多久发一次版。它不知道 你的系统哪个模块最脆弱。它不知道 上次事故之后应该加什么检查。
这些东西是经验的沉淀。每一次事故、每一次「这个 bug 不该出现」、每一次「发布太疼了」——这些痛感积累成 harness 的形状。
在 CLI + Skill + CI/CD:现代应用的新三件套 里,我说过 CI/CD 是现代应用的交付底线。但那篇文章讲的是「要不要有」。这篇讲的是 有了之后,它长什么样。
同样一条 CI pipeline,有品味的人和没品味的人搭出来的东西完全不同。区别不在配置文件,在 判断——什么该检查、什么不该检查、什么顺序检查、检查失败了怎么办。
评估工程师的新标准
AI 时代,如果我们还用「代码写得好不好」来评估工程师,就像摄影术发明之后还用「画得像不像」来评估画家。
技术门槛被拉平了。80 分的代码,AI 三分钟给你。
真正区分人的,是 80 分之上的东西:
- 他知道 不该写什么 (克制)
- 他知道 系统该怎么长 (演进策略)
- 他知道 失败了怎么办 (失败哲学)
- 他知道 工作台该怎么搭 (harness)
- 他知道 什么时候该停下来 (判断力)
这些东西有一个共同特征: 它们不是生成问题,是选择问题。 AI 能生成任何风格的代码、任何架构的方案、任何 CI 配置。但它不能替你 选择。
以前,选择必须通过手写代码才能表达,所以我们误以为品味住在代码里。现在代码是 AI 写的了,品味搬到了选择里——目录怎么切、抽象做不做、版本什么时候发、事故之后改不改。
打开一个代码库,代码可能全是 AI 写的,你看不出来。
但你打开他的 CI pipeline、看他的 release 记录、翻他的 postmortem——品味在那里,藏不住。
你评估工程师的标准,因为 AI 变了吗?欢迎留言讨论。