
AI 写完代码后,很多人会继续问:
text
帮我优化一下这段代码。
但"优化"是一个很宽泛的词。
AI 可能会:
- 修改变量名。
- 拆分函数。
- 引入新的语法。
- 减少循环次数。
- 增加缓存。
- 替换第三方库。
- 重新设计整个模块。
这些建议不一定都有必要。
有些建议能让代码更清楚,有些需要通过测试和数据验证,还有一些只是让简单问题变得更复杂。
这篇文章只解决一个问题:
面对 AI 给出的代码优化建议,我们应该怎样判断是否采纳?
一、代码优化不只是让程序跑得更快
代码优化通常可以分为三类。
| 类型 | 目标 | 常见做法 |
|---|---|---|
| 正确性优化 | 减少错误 | 补充校验、修复边界问题 |
| 可读性优化 | 更容易理解和维护 | 改名、拆分函数、减少重复 |
| 性能优化 | 减少时间或资源消耗 | 减少重复计算、优化查询 |
它们的优先级应该是:
text
先保证正确
↓
再保证容易理解
↓
最后根据数据优化性能
一段代码即使运行得很快,如果结果是错的,也没有价值。
二、一个简单案例
假设我们需要统计已支付订单的总金额:
javascript
function getPaidTotal(orders) {
let total = 0;
for (let i = 0; i < orders.length; i++) {
if (orders[i].status === "paid") {
total += orders[i].amount;
}
}
return total;
}
这段代码结构简单,也能完成基本功能。
如果把它交给 AI 优化,AI 可能给出下面的写法:
javascript
function getPaidTotal(orders) {
return orders
.filter((order) => order.status === "paid")
.reduce((total, order) => total + order.amount, 0);
}
第二种写法更接近"筛选后求和"的业务含义,但不代表它在所有方面都更好。
我们需要逐项判断。
三、哪些优化建议值得采纳
1. 修复真实错误的建议
原函数没有检查 orders 是否为数组,也没有确认 amount 是否为有效数字。
如果真实数据可能不完整,那么增加必要校验是有价值的:
javascript
function getPaidTotal(orders) {
if (!Array.isArray(orders)) {
throw new TypeError("orders 必须是数组");
}
return orders.reduce((total, order) => {
if (order.status !== "paid") {
return total;
}
if (typeof order.amount !== "number") {
throw new TypeError("已支付订单的 amount 必须是数字");
}
return total + order.amount;
}, 0);
}
是否采用这种处理,还要看业务规则:
- 无效金额应该抛错吗?
- 还是忽略该订单?
- 金额使用小数是否安全?
- 是否应该使用"分"作为单位?
AI 可以发现风险,但不能替你决定业务规则。
2. 降低理解成本的建议
下面这些建议通常值得考虑:
- 使用能表达含义的变量名。
- 把重复逻辑提取为函数。
- 减少过深的条件嵌套。
- 删除已经不用的代码。
- 把复杂判断拆成几个有名称的步骤。
判断标准很简单:
修改后,第一次看到这段代码的人是否更容易理解?
如果只是把普通写法替换成生僻语法,代码虽然更短,却不一定更好。
3. 有测试保护的小范围修改
优化会改变代码,所以修改前应该先确认原有行为。
例如至少测试:
javascript
import { describe, expect, it } from "vitest";
import { getPaidTotal } from "./order.js";
describe("getPaidTotal", () => {
it("只统计已支付订单", () => {
const orders = [
{ status: "paid", amount: 100 },
{ status: "pending", amount: 50 },
{ status: "paid", amount: 20 }
];
expect(getPaidTotal(orders)).toBe(120);
});
it("空数组返回 0", () => {
expect(getPaidTotal([])).toBe(0);
});
});
先让测试通过,再修改代码;优化后重新运行测试。
这样才能确认代码结构变了,但功能行为没有被意外改变。
四、哪些建议需要先验证
1. "这样性能更好"
AI 经常会说某种写法性能更好,但没有给出测量结果。
例如,filter 再 reduce 会遍历两次数组,而一次 reduce 只遍历一次。
在十几条订单数据中,这种差异通常没有实际意义;在大量数据和高频调用场景中,才可能值得关注。
性能建议至少要回答:
- 当前代码真的慢吗?
- 慢在哪里?
- 数据量有多大?
- 这段代码调用频率有多高?
- 优化前后差异是多少?
没有测量结果的性能结论,只能当作一个待验证的假设。
2. 引入缓存
缓存可以减少重复计算,但也会带来新问题:
- 数据变化后,缓存什么时候失效?
- 缓存会占用多少内存?
- 用户会不会看到旧数据?
- 维护成本是否大于收益?
如果当前计算只需要几毫秒,就没有必要急着增加缓存。
3. 引入新的第三方库
AI 可能建议使用一个库替代现有实现。
采纳前应该确认:
- 项目是否已经有相同能力。
- 这个库是否仍在维护。
- 是否兼容当前项目版本。
- 是否增加包体积或安全风险。
- 一个简单函数是否真的需要一个依赖。
五、怎样识别过度优化
出现下面这些情况时,可以先暂停:
- 代码没有明显问题,却被重写成复杂架构。
- 为极少发生的场景增加大量抽象。
- 为几条数据设计复杂缓存。
- 为一个函数创建很多接口和类。
- 为追求更少行数使用难懂的写法。
- 没有性能数据,却进行大范围重构。
- 优化后测试更难写,调试也更困难。
可以记住一个简单原则:
优化带来的收益,应该大于理解、测试和维护它的成本。
六、正确向 AI 提出优化需求
不推荐只说:
text
帮我优化代码。
推荐明确优化目标和限制:
text
请审查下面的 JavaScript 代码,先不要直接重写。
背景:
- 这段代码用于统计已支付订单金额。
- 每次大约处理 100 到 500 条数据。
- 当前功能结果正确,已有单元测试。
优化目标:
1. 提高可读性。
2. 检查明显的边界问题。
3. 不追求没有数据支持的性能优化。
限制:
1. 不新增第三方依赖。
2. 不改变函数输入和返回值。
3. 不修改无关文件。
请按下面格式回答:
1. 问题或建议。
2. 建议的依据。
3. 预期收益。
4. 可能风险。
5. 如何验证。
请把建议分为:
- 建议采纳。
- 需要验证。
- 暂不建议。
等我确认后,再给出最小修改代码。
这种提问方式可以让 AI 先做审查,而不是直接把代码全部改掉。
七、一份简短的优化判断清单
收到 AI 的优化建议后,逐项检查:
text
[ ] 它解决了一个真实问题吗?
[ ] 它会改变原有功能吗?
[ ] 修改后是否更容易理解?
[ ] 是否增加了新的依赖或抽象?
[ ] 是否有测试保护?
[ ] 性能结论是否有测量数据?
[ ] 修改范围是否足够小?
[ ] 收益是否大于维护成本?
如果无法回答其中几项,就不要急着采纳。
总结
使用 AI 优化代码时,建议遵循下面的顺序:
text
确认代码行为正确
↓
明确本次优化目标
↓
让 AI 先列建议和依据
↓
人工筛选建议
↓
小范围修改
↓
运行测试和性能测量
- 修复真实错误、减少重复、提高可读性的建议通常值得考虑。
- 涉及性能、缓存和新依赖的建议,需要用数据和项目实际验证。
- 代码更短不等于更容易维护。
- 没有真实问题和测量数据时,不要急着进行大范围性能优化。
- AI 可以提出建议,但是否采纳仍然由开发者决定。
可以把今天的内容浓缩成一句话:
不要问 AI 能把代码改得多复杂,而要问这次修改解决了什么真实问题。
下一篇文章,我们将继续学习:
《用 AI 写 README 和接口文档》
✍坚持原创,求关注,点赞,收藏