AI 写代码总跑偏?我逼它回到“函数级颗粒度”

一、AI 编码的真相:它是个"跑偏大师"

我用 AI 写代码快一年了,发现一个残酷的事实:

AI 在"写 Demo"上无敌,在"写能用的系统"上拉胯。

你让它"写一个智能家居控制页面",它能 30 秒给你一个漂亮的 Vue 组件。你让它"把这个模块对接你的三层缓存架构",它就开始跑偏了------变量命名乱飞、边界条件漏掉、错误处理全靠 console.log

更致命的是,AI 总是想"多写一点"。你让它写 tap 函数,它顺手把 swipelongPressdrag 全写了。看起来省事,但当你发现 tap 的坐标校验有问题时,你已经不忍心删掉它写的另外 200 行代码了。

AI 的创造力,在 Demo 阶段是优势,在系统构建阶段是灾难。

二、我的反制策略:复古到"函数级颗粒度"

在被 AI 气到无数次之后,我选择了一个"复古"的策略:

不再让 AI 写模块,只让它写函数。

一个模块一个模块地生成 → 跑偏率 60%。

一个文件一个文件地生成 → 跑偏率 30%。
一个函数一个函数地生成 → 跑偏率降到 5% 以下。

为什么?

因为"写一个函数"对 AI 来说,是没有歧义的确定性任务

任务 AI 的理解 跑偏概率
帮我写一个设备管理模块 模糊,需要 AI 自己设计边界 极高
帮我写 device.ts,包含注册和发现 较清晰,但内部结构仍需 AI 决定 中等
帮我写 registerDevice(id, driver, config) 函数,要求返回 Device 对象 完全确定,AI 只需要翻译签名 极低

函数是 AI 编码的"最小确定性单元"。

三、我的 Spec 怎么写:先写验收标准,再写函数签名

我现在写 Spec,不再是"功能描述",而是"函数清单"。

每个函数在 Spec 里长这样:

markdown

复制代码
## 函数:registerDevice

### 签名
registerDevice(id: string, driver: Driver, config: DeviceConfig): Device

### 职责
向设备注册表添加一个新设备,返回注册后的 Device 对象。

### 边界条件
- id 为空 → 抛出 `InvalidDeviceIdError`
- id 已存在 → 抛出 `DeviceAlreadyExistsError`
- driver 未初始化 → 抛出 `DriverNotReadyError`

### 验收标准(测试用例)
1. 正常注册 → 返回 Device 对象,`device.id` 等于传入 id
2. id 为空 → 抛出指定错误
3. id 重复 → 抛出指定错误
4. driver 未连接 → 抛出指定错误

这不是文档,这是合同。

AI 生成代码后,我只需要跑四个测试用例。全过了,验收通过。有一个没过,AI 重写。

我把这叫做 "验收驱动开发"------不是先写代码再补测试,而是先定义验收标准,再让 AI 写代码。

四、文件预估行数:强制单一职责的紧箍咒

在我的 Spec 里,每个文件都标注了预估行数:~150行~200行~250行

这不是炫技,是给 AI 套上的紧箍咒

当你告诉 AI "写一个 device.ts",它可能给你生成 800 行,从注册到发现到状态同步全塞进去。

当你告诉 AI "写 device/registry.ts,约 200 行,只负责设备注册",它就被限制住了。

行数限制是强制单一职责的手段。

我的 Spec 里有这样的目录结构:

text

复制代码
device/
├── index.ts           # 导出入口(~50行)
├── types.ts           # 类型定义(~150行)
├── registry.ts        # 设备注册(~200行)
├── discovery.ts       # 设备发现(~250行)
├── state-manager.ts   # 状态管理(~250行)
└── ttl-manager.ts     # TTL 管理(~200行)

每个文件只做一件事。一个文件超了 300 行,立刻拆。

AI 在"小文件"里跑偏的概率,远低于"大文件"。

五、核心原则验收表格:AI 无法绕过的护栏

我把项目的核心原则,全部变成了验收表格:

原则 说明 验收标准
三层意图缓存 L1→L2→L3 逐层降级 L1 < 10ms, L2 < 100ms, L3 < 3s
本地优先 SQLite 存储,断网可用 无外部数据库依赖
一切皆 CLI 每个能力是独立命令行工具 可单独测试、可管道组合
文件细颗粒度 每个文件 300 行左右 单一职责,高内聚低耦合

这张表的作用是:任何 AI 生成的代码,都必须能通过这张表的验收。

不符合"文件细颗粒度"?拆。不符合"一切皆 CLI"?重写。

验收标准不是注释,是测试用例。Spec 不是文档,是合同。

六、组装:从函数到系统的逆向工程

函数级颗粒度有一个"副作用":你需要自己组装。

但这不是负担,是控制权

AI 写好了 50 个纯函数,每个都有独立的测试用例。你要做的,是用这些函数拼出你的系统。

registerDevice + discoverDevices + getDeviceState → 设备管理模块。
matchRule + searchExperience + reactLoop → 三层意图引擎。

组装的过程,就是你理解系统的过程。

以前 AI 帮你写了整个模块,你根本不知道里面有什么。现在 AI 只写了函数,你亲自把它们拼起来,每一行代码的来龙去脉你都知道。

七、这套方法的收益

我用这套方法重构了 HomeSense 的 graph.ts------从 1400 行拆成 8 个文件,每个文件 150-250 行。

指标 重构前 重构后
总行数 1400 1100(拆开后更清晰)
单文件最大行数 1400 250
测试覆盖率 未知 80%+
AI 跑偏率 高(每次都要修) 低(基本直接可用)

省下的不是 Token,是"修 AI 代码"的心力。

八、写在最后

AI 时代的开发,最大的陷阱是"快"。

AI 能在 30 秒生成一个模块,但你花 3 小时修它的 bug。

我的方法是"复古":回到函数级颗粒度,先写验收标准,再让 AI 生成代码,最后自己组装。

慢了,但稳了。

Demo 可以快,系统必须稳。

如果你想用 AI 写出"能用的系统",而不是"炫技的 Demo",试试这套方法:

  1. 先写 Spec,颗粒度到函数

  2. 每个函数配验收标准

  3. 文件预估行数,强制单一职责

  4. 核心原则表格化,逐条验收

  5. 自己组装,掌控每一行代码

AI 是你的"函数工人",你才是"系统建筑师"。

相关推荐
fanly111 天前
AgentForge 智能体组件:与云驿插件平台构建全生态化的微服务一体化智能开发引擎
微服务·ai·agent
冬奇Lab1 天前
Agent 系列(16):工具链设计——让 LLM 用对工具的五个原则
人工智能·llm·agent
冬奇Lab1 天前
每日一个开源项目(第125篇):taste-skill - 给 AI 装上审美,让前端不再千篇一律
人工智能·开源·agent
字节跳动开源1 天前
你的 Agent 每次都“失忆”?这个工具彻底治好了我的前端开发焦虑
大数据·开源·agent
Python私教1 天前
给AI代理选大脑:别只盯着『谁最强』,这6个维度才决定上限
agent·ai编程·claude
leeyi1 天前
多租户隔离:一条 RLS 策略怎么防数据串
llm·agent
92year1 天前
用 browser-use 让 AI 自己操作浏览器:从安装到自动填表全流程
python·ai·浏览器自动化·browser-use
leeyi1 天前
长期记忆:Agent 怎么“记住“用户
llm·agent
leeyi1 天前
工具调用:Agent 的手和眼
llm·agent