AI 写代码越来越猛,但你的技术债谁来还?
后台私信炸了。各大群也在聊同一个话题:AI 写出来的代码,很难维护。
这句话我记了 10 多年
十多年前我还是个刚入行不久的开发,老板是个技术出身的老兵。有次我跟他汇报说想在项目里引入一个新框架,他听完没直接说行不行,就甩了一句话:
"不管你用的什么技术,核心是你要驾驭它。"
当时觉得这话有点虚 —— 不就是"学好再用"吗?但这些年过来,我越来越觉得这句话的分量。
放在今天 AI 辅助编码的时代,这话更是金玉良言。
AI 写代码,到底出了什么问题?
最近收到太多类似的反馈:
- "用 Claude/Codex/Copilot 生成了一堆代码,功能是实现了,但三个月后自己都看不懂"
- "AI 给的方案能跑,但架构一塌糊涂,改个需求牵一发动全身"
- "项目越写越像意大利面,AI 不断往里面塞代码,没人敢重构"
说实话,这些问题的根源
不在 AI,在于我们把 AI 当成了"自动写代码机",而不是"辅助工具"。
我见过两种极端:
第一种:完全不用 AI。 抱着键盘从头敲到尾,觉得用 AI 就是"作弊"。这种人会慢慢被效率淘汰。
第二种:什么都让 AI 写。 Prompt 一丢,代码一贴,功能一跑,交差。三个月后面对一堆"能跑但看不懂"的代码,开始骂 AI。
这两种都走偏了。
驾驭的核心:你得先懂,才能借力
我写 Rust 的时候有个很深的体会:编译器不会替你思考,它只会替你检查。
AI 也是一样。它不会替你做架构决策,不会替你理解业务上下文,不会替你判断"这段代码放在这个位置合不合适"。它能做的是:在你已经想清楚的前提下,帮你加速实现。
举个例子。我之前写一个 CLI 工具,需要处理配置文件解析。我跟 AI 说:
"用 clap 解析命令行参数,配置文件用 toml 格式,支持环境变量覆盖,配置优先级是 CLI > 环境变量 > 配置文件 > 默认值"
AI 给出的代码能跑,但结构是这样的:
// AI 给的——能跑,但耦合严重
fn main() {
let cli_args = parse_cli();
let config_file = read_config_file(&cli_args.config_path);
let env_vars = read_env_vars();
let config = merge_all(cli_args, config_file, env_vars);
// ... 后面 300 行全堆在 main 里
}功能没问题。但如果我要加一个新的配置来源,或者写测试,或者支持不同的输出格式——得大改。
我知道该怎么做,所以我跟 AI 说:
"把配置解析拆成独立的 Config 层,用 trait 抽象配置来源,支持组合和优先级覆盖"
这次出来的东西就不一样了:
// 配置来源抽象
trait ConfigSource {
fn get(&self, key: &str) -> Option<String>;
}
// 优先级组合
struct ConfigChain {
sources: Vec<Box<dyn ConfigSource>>,
}
impl ConfigChain {
fn get(&self, key: &str) -> Option<String> {
self.sources.iter()
.find_map(|s| s.get(key))
}
}你看,第一次是"我告诉 AI 做什么",第二次是"我告诉 AI 怎么做"。 区别在哪?在于我自己懂 Rust 的 trait 系统,知道怎么用抽象来解耦。
如果我不懂,我只会说"帮我写个配置解析",AI 就给我一个能跑的意大利面。
对技术要有敬畏之心
"敬畏"这个词听起来有点重,但我想表达的不是恐惧,是认真对待。
我见过太多人(包括早年的自己)犯同一个错误:
对工具的理解停留在"能用"的层面,从来没想过"用好"。
- Python 能写脚本,也能写大型服务 —— 但如果你只把它当脚本语言用,项目一大就会失控
- Go 的 goroutine 用起来很方便 —— 但如果你不理解调度器和 channel 的语义,写出的并发代码可能比单线程还慢
- Rust 的所有权系统很严格 —— 但如果你只是"让编译器不报错"地写代码,而不是理解为什么这么设计,你永远写不出地道的 Rust
- Java 的 Spring 生态很成熟 —— 但如果你只会注解驱动开发,不理解底层的 IoC 和 AOP,遇到复杂问题就抓瞎
每门语言背后都有一套设计哲学。 你用它,就得尊重它的哲学,而不是用 A 语言的思维写 B 语言的代码。
我自己写 Rust 的时候,最深的体会是:
你越理解编译器为什么这么设计,你写代码就越顺。
一开始跟编译器 battle 觉得它烦,后来发现它每一次报错都在帮你避免一个潜在的 bug。这种"敬畏"让我写出了更可靠的代码。
AI 时代的正确姿势
回到正题。AI 到底该怎么用?
我的做法是:把 AI 当成一个"手很快但不懂业务的初级工程师"。
- 你可以让它帮你写样板代码(boilerplate)——但你得 review
- 你可以让它帮你查 API 用法——但你得确认它给的是对的
- 你可以让它帮你重构一段代码——但你得告诉它重构的方向
- 你可以让它帮你写测试——但你得定义清楚要测什么
关键在于:你在主导,AI 在执行。 不是反过来。
我用 AI 写 Rust 代码的时候,基本流程是这样的:
- 我自己先想清楚架构——模块怎么拆、接口怎么定义、数据流怎么走
- 把具体的实现交给 AI——"帮我写一个实现了这个 trait 的 struct,字段是这些"
- 我 review 每一行代码——不是走马观花,是真的读一遍,确认它符合我的设计意图
- 发现不对就纠正——"这里应该用 enum 而不是 String,因为状态只有这几种"
这个流程下来,代码质量是可控的。因为
设计在我脑子里,AI 只是帮我把想法变成代码。
不管你用什么语言,道理都一样
有人可能觉得这是 Rust 独有的问题——毕竟 Rust 对开发者的要求比较高。但其实不是。
任何语言,如果你不理解它的设计哲学,你写出来的代码都会有问题。
- 用 Go 不理解"少即是多",你就会写出一堆过度抽象的代码
- 用 Python 不理解鸭子类型和协议,你就会写出一堆 type hint 堆砌但逻辑混乱的代码
- 用 Zig 不理解显式内存管理的哲学,你就会用着 unsafe 然后奇怪为什么 segfault
- 用 C 不理解指针和内存布局,你就会写出一堆 buffer overflow 的安全隐患
AI 只是放大了这个问题。以前你不懂语言哲学,写出来的代码只是"不太地道";现在有了 AI 帮你量产代码,不懂语言哲学写出来的是"大量不地道的代码"。
量变引起质变,技术债滚雪球一样越滚越大。
说到底,敬畏是一种态度
敬畏不是说你要把每门语言都学到专家级别,而是:
- 你知道自己不知道什么——遇到不熟的领域,会去查文档、读规范,而不是直接丢给 AI
- 你会 review AI 的输出——不是无脑信任,而是带着批判性思维去看
- 你愿意花时间理解"为什么"——不只是"怎么用",还有"为什么这么设计"
- 你尊重语言的设计哲学——用它擅长的方式解决问题,而不是强行把它掰成你熟悉的样子
我老板那句话,放在 10 年前是对技术栈的要求,放在今天是对"人 + AI"协作模式的要求。
AI 是你的加速器,不是你的自动驾驶。
你可以让它帮你跑得更快,但方向盘得在你手里。
最后
如果你现在用 AI 写代码,我的建议很简单:
- 先把基础打扎实。 不管你用什么语言,理解它的核心概念和设计哲学。这是你驾驭 AI 的前提。
- AI 生成的代码,每一行都要过脑子。 不是说不能用,而是你要知道它在干什么、为什么这么干。
- 定期重构。 AI 倾向于"堆叠"解决方案,不会主动帮你整理代码。这个活儿得你自己干。
- 对技术保持敬畏。 不是因为它会惩罚你,而是因为认真对待写出的代码,会让你走得更远。
说句掏心窝的话:
技术工具一直在变,但"驾驭工具"这个能力是永恒的。
10 年前我老板教我的这句话,今天我送给你。
不管你是写 Rust、Zig、C、Go、Python 还是 Java —— 敬畏它,理解它,驾驭它。
这才是一个工程师该有的态度。