到了今天,AI 编码工具已是入场标配。问题不再是“我们该不该用”,而是“怎么用才不至于失去对代码库的掌控”。这个区分很重要,因为激进采用 AI 的失败模式很隐蔽:看起来干净却没人真正理解的代码;表面上的生产力提升,实则是向未来的维护债借来的速度;以及由模型自信地误用凭证或用户数据所引发的安全事故。

本文是写给已经度过新鲜期的工程师的实践指南——你已见识过 AI 编码工具能做什么,你想认真地用它,并且想用一种让你和团队变得更强而非更依赖的方式。我们会讲职业人士遵守的不可妥协的实践、最常被低估的陷阱,以及如何建立全团队的规范来收割收益而不付出隐藏成本。

⚡ 速览要点
  • 你提交的每一行都归你所有——审查每一份 AI 生成的 diff 不可妥协;签下这次 commit 的不是模型,是你。
  • 理解不是可选项。如果你在 PR 评审或调试时讲不清这段代码,你就不该 merge 它。
  • 让 AI 写测试并自我验证。让模型生成测试并运行,在你读到输出之前就闭合了反馈回路。
  • 小步、频繁的迭代胜过单次大生成。窄 diff 更易审查、更易回退,产出也更好。
  • secret、PII 与合规是你的责任。模型会乐呵呵地把密码打进日志,或建议把 token 存进 localStorage——你必须拦下它。
  • 诚实地度量生产力。每天交付的代码行数不是生产力指标;缺陷率、评审耗时、事故间隔时间才是。
tldr

AI 编码工具给了你一个强大但毫无批判力的协作者。用它跑得更快;用你的判断保持正确。审查每份 diff、维持你的理解、刻意管理上下文、尊重合规边界、度量真实结果——而非活动量。做对这件事的团队会变得真正更快;做不对的则积累起隐形债务,最终以事故的形式爆发。

永远审查每一份 diff

这是其余一切据以推导的根本规则。当你不读就提交 AI 生成的代码时,你不只是在赌那一份 diff——你在侵蚀你将来凌晨两点排障时所需的心智模型。你也在向自己和团队示意:作者身份与理解是可分离的——而它们并不可分。

审查 AI 生成的代码不同于审查同事的 PR。人类协作者带来上下文、判断力,以及对你代码库的理解。模型一样都不带;它带来的是对训练数据的模式匹配。这意味着失败模式也不同:

这些失败没有一个能被“看起来合理”抓住。它们要求你带着“这真的对吗?”而不是“这大致符合我的要求吗?”去读代码。

一份实用的 AI diff 审查清单

维持你对代码的理解

AI 编码的生产力陷阱在于:交付你没完全理解的代码太容易了。你第一次不理解就 merge 一个非平凡函数时,就接受了一笔负债:当那个函数出问题时——它一定会——你将花调试时间去建立本该在 merge 时就有的理解,但这次是在压力下、在生产环境、有客户受影响的情况下。

“merge 前先理解”这条规则不只关乎事故响应。它关乎长期可维护性。团队里没人完全理解的代码,往往被绕过而非被演进——开发者会加 hack 而不去改他们推理不清的代码,架构于是退化得比本该更快。

维持理解的技巧

这里有个重要的标定:“理解”不等于“能从零重写”。它意味着“能解释它做什么、为什么做出那些主要设计选择、需求若变了什么得改”。这个门槛,对你 merge 的每个函数都是可达的。

用 AI 写测试并自我验证

AI 辅助开发中最强大的工作流之一,是自动闭合循环:生成代码、生成测试、跑测试、迭代。这对能执行命令的 agentic 工具尤其有效,因为模型能在你什么都不做的情况下抓住自己的错误。

自我验证工作流

  1. 描述你想要的函数或 feature,把验收标准写成具体的、可测试的行为。
  2. 让模型先写测试(若 spec 复杂到你不信任模型能正确推导,就自己写)。
  3. 让模型实现代码直到测试通过,每次迭代后跑 go test / pytest / jest
  4. 把最终实现与测试一起读——测试记录了期望行为,也让实现更易理解。
自我验证 prompt(agentic 工具)
# 发给 agentic 工具的 prompt(如 Claude Code)
Implement a sliding-window rate limiter in ratelimit/ratelimit.go.

Spec:
- func NewLimiter(limit int, window time.Duration) *Limiter
- func (l *Limiter) Allow(key string) bool
- Thread-safe; use sync.Mutex
- Pure in-memory; no external dependencies

First, write the table-driven tests in ratelimit/ratelimit_test.go
covering: under limit, at limit, over limit, window reset, concurrent
access (use t.Parallel + race detector).

Then implement until `go test -race ./ratelimit/...` passes.
Show me the test output before and after.

一个关键的微妙之处:当你让模型为它自己写的代码写测试时,有风险——测试编码的是模型的假设,而非正确的规格。对任何 spec 含糊或风险高的场景,自己写测试——或至少像审查实现一样仔细审查它们。测试即规格;让模型写样板,但行为断言你自己拿主意。

保持迭代小步

用 AI 编码工具时的诱惑,是用一个 prompt 描述一个大 feature 让它全部生成。这很少奏效:输出更难审查、更难理解、更难回退,且往往比小而聚焦的生成更不正确。模型的注意力在长而复杂的任务上会退化;约束满足度随约束数量增长而变差。

小步迭代也强制更紧的反馈回路。如果你生成一个函数、跑测试、它挂了,你确切知道该看哪个函数。如果你跨五个文件生成一百行而测试挂了,你面对的是个难得多的调试问题。

实践中的“小”是什么意思

这种纪律当下感觉更慢,但端到端更快。一个十步迭代、每步五分钟、每步都测试,是三十分钟你心里有底的时间。同等范围的一次性生成,花三十分钟审查、出错时再花一小时调试,是更慢,而非更快。

刻意的上下文管理

每次 AI 编码会话都活在一个上下文窗口里。窗口里有什么,决定了模型对你代码库、约定、约束的了解。把上下文管理交给运气——让工具自动决定纳入什么,或从不提供相关文件——是输出质量波动的一大来源。

需要显式管理的东西

agentic 工具的上下文卫生

对 Claude Code 这类维持长时会话的工具,上下文压实(摘要旧回合)是自动的但有损。长会话早期声明的重要约束,等模型做到第 7 步时可能已被遗忘或权重过低。防御性习惯是:在每个主要步骤的开头重申关键约束,而不只在会话开始时说一次。

为 agentic 步骤重申上下文
# 每个主要步骤开头 —— 重申不变量
Step 3 of 5: implement the payment reconciliation job.

Invariants (apply to all code in this session):
- Go 1.22, no new dependencies beyond what's in go.mod
- All DB writes must be in explicit transactions; never autocommit
- Log at key decision points with key=value format using slog.Default()
- Do not touch files outside the /jobs/ directory

Current state: Steps 1-2 are done. The job is registered in scheduler.go
and the DB schema migration (jobs/migrations/20260512_reconcile.sql)
is applied. Now implement jobs/reconcile.go with the reconcile logic...

何时不该用 AI 编码工具

AI 工具是强大的默认选项,但并不总是正确选择。识别何时该放下工具、自己思考,是工程成熟度的标志。

安全关键代码

加密实现、认证逻辑、授权检查,应当极其谨慎地编写。不是因为模型在这些上特别糟——它们常产出看起来正确的代码——而是因为隐蔽错误的后果严重,而错误本身又隐蔽。模型也许为密码生成了时序安全的比较,却没注意到你还通过另一条代码路径暴露了一个次级 oracle。对安全关键代码,优先用经过良好审计的库、阅读实现源码,并无论代码怎么写都考虑一次专门的安全评审。

新颖或文档稀少的领域

模型在现有代码上训练。如果你为一个新协议、一个内部专有系统,或一个在模型知识截止后发生重大变化的 API 写代码,模型会从已知的东西外推,可能对具体细节自信地出错。这些情况下,永远对照一手文档验证,而不只是看模型的输出。

架构决策

AI 工具擅长在架构内实现,而非选择架构。问模型“这个集成该用消息队列还是直接 HTTP 调用?”会得到一个合理的答案,但那答案基于通用模式,而非你的具体约束——团队规模、容错度、运维预算、现有基础设施。需要时用模型探索权衡,但决策你自己拿。

当你需要深入理解新东西时

如果你在学一门新语言、新框架或新概念,让 AI 替你写所有代码适得其反。手动写代码、犯错、调试的挣扎,正是理解形成的方式。把 AI 当补充(解释概念、检查你的工作)很有价值;把它当替代(生成所有代码)会让你得到一个能跑的程序和一份浅薄的理解。

secret、隐私、许可与合规

这些是 AI 编码工具制造真实组织风险的领域,也是许多团队准备不足之处。

secret 与凭证

永远不要把凭证、API key、数据库密码或私钥贴进发往任何云端模型的 prompt。这本该显而易见,但实践中经常被违反,往往是无意的——开发者贴一个配置文件去问某个设置,忘了它含有生产凭证。建立一个习惯:把任何文件或代码块贴进 prompt 前,扫一遍看有没有像 secret 的东西。例子里用环境变量;贴之前把真实值脱敏成 YOUR_API_KEY_HERE

PII 与敏感数据

同样地,不要把真实用户数据——姓名、邮箱、支付信息、健康数据——当例子,或放进你正在调试的错误信息里。用匿名化或合成数据。对许多组织,这不只是好做法;在 GDPR、HIPAA 等框架下是法律要求。查你组织的 AI 工具政策,看哪些数据能与哪些服务共享的具体要求。

AI 生成的代码与安全漏洞

模型会引入人类审查者未必能立刻识别为漏洞的安全问题。AI 生成代码里最常见的类别:

漏洞类别AI 工具如何引入缓解
SQL 注入 模型用旧模式时在查询里做字符串插值 永远用参数化查询;grep 出 DB 调用里的字符串格式化
不安全的默认值 禁用 TLS 校验、宽松 CORS、调试端点开着没关 显式审查 config 与 middleware 选项
日志里的敏感数据 模型常为调试而记录函数参数;这些可能含密码或 token 审计日志语句里的敏感字段名
依赖混淆 幻觉出的包名恰好作为恶意包真实存在 安装前对照官方 registry 验证每个新依赖
路径穿越 未做脱敏的朴素文件路径处理 用 filepath.Clean / os.Open 配合谨慎校验;审查任何受用户影响的路径

许可与 IP

AI 模型在海量开源代码上训练。对多数组织和多数输出,这不是实际顾虑——模型生成的是样板模式,而非复制特定的受版权保护的实现。然而,对商业场景的生产代码,值得了解你组织的政策。有些企业只批准了特定 AI 工具用于特定用例;另一些则一刀切限制。不确定就咨询法务或政策团队。

AI 引入的技术债与“看起来对”陷阱

AI 编码最阴险的失败模式之一,是看起来像干净代码的技术债。人写的技术债通常可辨认——一条 TODO 注释、命名不一致、一个明显的 hack。AI 生成的技术债往往风格干净、格式规整、结构上与周围代码一致。它只是做了糟糕的设计选择,而这些选择要到后来才显现。

AI 技术债的常见形态

“看起来对”陷阱被一个事实放大:这些问题往往能通过代码评审。评审者在做“这代码看起来像在做它该做的事吗?”的模式匹配,而非“这是对的设计吗?”。显式的设计评审——独立于正确性评审——对任何非平凡的 AI 生成改动都很有价值。

团队协作与规范

当团队采用一致规范、而非把个人用法放任自流时,AI 编码最有价值——也最安全。没有规范的团队最终会有一个代码库:有些代码被仔细审查过,有些是自动驾驶 merge 的,而你无从分辨。

值得建立的规范

PR 模板新增示例
## AI 辅助代码清单(如适用)
- [ ] 我已读懂这份 diff 里的每一行
- [ ] prompt 中未包含任何 secret 或 PII
- [ ] 所有新依赖已对照官方 registry 验证
- [ ] 错误处理已审查 —— 无被悄悄吞掉的错误
- [ ] 日志语句已审查 —— 输出中无敏感数据
- [ ] 验收标准已测试,而非只是“它能跑”

诚实地度量生产力

组织常用每天交付的代码行数,或开发者完成工单快了多少,来度量 AI 编码生产力。这两个指标都极易被 AI 工具以不代表真实生产力提升的方式刷高。

一个用 AI 把每天行数翻倍、却一行都不仔细审查的工程师,并没有两倍生产力——他在以双倍速率积累未来的调试会话、事故与重构。真正的生产力问题不是“我们交付得多快”,而是“我们多快交付了我们能维护的正确代码”。

更好的指标

误导性指标为何误导更好的替代
每天代码行数 AI 轻松刷高;量 ≠ 价值 交付后仍在生产、30 天后未被改动的 feature 数
每个 sprint 关闭的工单 AI 能更快关单,同时制造重开与回归 缺陷逃逸率(每交付 feature 漏到生产的 bug 数)
首次 commit 耗时 初始代码生成很快;费时的是审查与迭代 从开始到 PR merge 的周期时间(含多轮评审)
AI 接受率 高接受坏建议比低接受更糟 与 AI 使用相关联的 merge 后缺陷率

对有良好纪律地采用 AI 编码工具的团队,一个现实的预期:在定义良好的任务上,端到端周期时间真正改善 20–40%,集中在样板、测试生成与文档上。这很可观。声称 5 倍提升的团队,通常要么在度量错的东西,要么还没付技术债的账单。

开发者满意度与技能成长

一个常被忽视的维度,是开发者随时间推移的体验。用得好的 AI 工具往往提升满意度——枯燥样板消失,开发者花更多时间在有趣问题上。用得糟的 AI 工具——开发者感觉自己只是在审查看不懂的代码——往往增加焦虑、降低投入。追踪这一点。定期的团队 AI 工具使用复盘很有价值,不只为流程,更因为它揭示工具到底是真在帮忙,还是只是加了一层不透明。

建立长期能力,而非依赖

关于 AI 编码最重要的长期顾虑,是技能萎缩的风险。如果你两年里什么都用 AI,你不靠它写代码的能力会怎样?当 AI 的模式匹配失效、你需要真正的理解时,你调试复杂系统的能力会怎样?

答案不是少用 AI 工具,而是刻意地用。一些保持并发展技能的具体习惯:

在一个拥有强大 AI 编码工具的世界里最有价值的工程师,不是 prompt 写得最流畅的——那种技能会商品化。而是那些深入理解自己所建系统、能调试任何出错之处、能做出稳健架构决策的工程师。AI 工具是这些工程师的力量倍增器;对那些已经外包了自己理解的工程师,它则是负债制造器。

takeaway

AI 辅助编码是一门纪律,而不只是一套工作流。工具强大到能让你真正更快——又随性到能让你悄悄变差。获得持久价值的工程师,是那些审查每份 diff、维持自己的理解、认真对待安全与合规、并度量真正重要的结果的人:不是交付的行数,而是他们能自信拥有的、正确且可维护的系统。

🎯 面试尖锐观点

激进采用 AI 编码最大的风险是什么?理解的萎缩与隐形技术债——看起来干净、能过评审、却慢慢积累设计问题的代码,只在运维压力下才浮现。
团队该如何度量 AI 编码生产力?缺陷逃逸率与到 merge 的周期时间,而非代码行数或关闭的工单——后两者极易被刷,且不反映代码质量。
为什么“看起来对”不足以作为 AI 代码的审查标准?AI 输出默认风格干净;它的失败模式是逻辑错误、被违反的约束、隐蔽的安全问题——这些都不会从表面阅读中浮现,而需要理解代码实际做了什么。

← 上一篇
面向代码的提示工程