001.用 AI 重构屎山代码
出处:掘金
原作者:ErpanOmer
我们团队维护着一个有 5 年历史的史诗级中后台项目。在这座屎山里,有一个叫 handleOrderSubmit.js 的文件
可以下载瞧一瞧,有多屎👉 handleOrderSubmit.js
它是一个长达 500 多行的 React useEffect 钩子函数
它混合了订单数据的本地校验、价格计算、优惠券应用、API 请求、全局状态更新、以及错误弹窗处理……所有的逻辑,都塞在一个函数里,用 if/else 和 try/catch 层层嵌套
没人敢动它
每次产品经理提一个小需求,比如在提交订单时,增加一种新的优惠券类型,我们整个团队的表情都像被雷劈了。因为我们知道,改这个函数,要么加班一周,要么就等着 P0 级事故
上周,产品经理要求我们在这个函数里,加入一个全新的风控逻辑
我评估了一下,手动重构,至少需要一个资深工程师一周的时间,而且风险极大
我受够了。我决定,把这个烫手的任务,扔给我的实习生 —— AI(我用的是 GPT-5 mini,穷😂)
这篇文章,就是我人机协作,啃下这块硬骨头的完整复盘,大家继续看
我不能直接说重构它
我犯的第一个错误,是直接把 500 行代码贴给 AI,然后说:帮我重构这段代码
AI 很听话,它给我的,是一段看起来更整洁的代码 —— 它把 if/else 换成了 switch,提了几个变量……这不叫重构,这叫重新排版,毫无意义
我很快意识到:AI 是一个能力超强、但没有灵魂的执行者。我,作为开发者,必须给它提供一个清晰的方案
于是,我制定了一个五步重构法
我的 Prompt 和思考
我的核心思想是:AI 负责执行,我负责决策。 我要像一个指挥家一样,一步一步地引导 AI,把这 500 行的代码,拆解成高内聚、低耦合的模块
第一步:先让 AI 读懂屎山
我不能上来就让 AI 改。我得先确认,它和我对这段代码的理解,在一个频道上
Prompt:
你是一个资深的 React 架构师。请分析下面这段 500 行的
useEffect代码
- 告诉我它做了几件主要的事情?(职责分析)
- 找出所有的副作用(比如 API 请求、
localStorage操作、全局状态更新)- 找出所有的纯逻辑(比如数据校验、价格计算)
- 评价它的可维护性和可测试性

GPT 的回答,给了我一个惊喜。它清晰地列出了:
- 职责:它承担了至少 5 个职责:表单校验、价格计算、库存检查、创建订单、处理 UI 反馈
- 副作用:
api.post(...),setLoading(true),showToast(...)... - 纯逻辑:
validateForm(...),calculateTotalPrice(...)... - 评价:可维护性极低,单一职责原则被严重违反,几乎不可测试
很好,AI 看懂了!我们就可以可以开始了
第二步:先分离纯逻辑代码
这是最关键的一步。我要把计算和动作分开
Prompt:
非常好。现在,请你只针对纯逻辑部分(表单校验、价格计算)进行重构
- 把这些逻辑,从原函数中提取出来,变成独立的、可导出的纯函数
- 这些函数必须是纯的:不能有任何副作用(不能调用
api或setLoading)- 使用 TypeScript,为这些新函数的入参和返回值,提供清晰的类型定义

AI 立刻唰唰唰地给了我几个文件:
export function validateOrder(formData: OrderForm): string | null {
if (!formData.user) return '用户信息不能为空';
if (formData.items.length === 0) return '商品不能为空';
// ... 10 more rules
return null;
}
export function calculateTotalPrice(items: Item[], coupon: Coupon): number {
let total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
if (coupon.type === 'PERCENT') {
total *= (1 - coupon.value / 100);
}
// ... 20 more rules
return total;
}
第三步:让 AI 为自己的代码做测试
我怎么知道 AI 提炼的逻辑,是对的还是错的?答案:让它自己写单元测试来证明
Prompt:
你现在是一个 QA 工程师。请使用
Vitest,为你刚才提取的validateOrder和calculateTotalPrice这两个函数,编写全面的单元测试用例。 必须覆盖所有边界情况,包括正常、异常、和边缘值
AI 再次给了我惊喜。它生成的测试用例,比我手写的还要全:
import { describe, it, expect } from 'vitest';
import { calculateTotalPrice } from './calculator';
describe('calculateTotalPrice', () => {
it('should return 0 for empty cart', () => {
expect(calculateTotalPrice([], null)).toBe(0);
});
it('should apply percent coupon', () => {
const items = [{ price: 100, quantity: 1 }];
const coupon = { type: 'PERCENT', value: 10 };
expect(calculateTotalPrice(items, coupon)).toBe(90);
});
// ... 省略更多
});
我把这些测试用例跑了一遍,全部通过。我现在信心大增
第四步:重写协调层
现在,纯逻辑已经被分离并验证了。原来的 500 行屎山,只剩下副作用和流程控制代码了。是时候重写它了
Prompt:
干得漂亮。现在,我们来重构那个原始的
useEffect函数
- 它现在唯一的职责是协调
- 调用我们刚才创建的
validateOrder和calculateTotalPrice纯函数- 把所有的副作用(API 请求、
setLoading、showToast)清晰地编排起来- 使用
async/await,让异步流程更清晰,用try/catch处理错误
这次,AI 给我的,是一个只有30 行左右的、清晰的流程代码:
// 重构后的 useEffect
useEffect(() => {
const submitOrder = async () => {
setLoading(true);
try {
// 1. 协调:验证 (纯)
const errorMsg = validateOrder(formData);
if (errorMsg) {
showToast(errorMsg);
return;
}
// 2. 协调:计算 (纯)
const totalPrice = calculateTotalPrice(formData.items, formData.coupon);
// 3. 协调:副作用(不纯)
const result = await api.post('/order/submit', { ...formData, totalPrice });
// 4. 协调:响应(不纯)
if (result.code === 200) {
showToast('订单提交成功!');
router.push('/success');
} else {
showToast(result.message);
}
} catch (err) {
showToast(err.message);
} finally {
setLoading(false);
}
};
if (isSubmitting) { // 假设一个触发条件
submitOrder();
setIsSubmitting(false);
}
}, [isSubmitting, formData /* ...其他依赖 */]);
第五步:最后守卫工作,加入新功能
别忘了,我重构的目的,是为了加风控这个新功能
Prompt:
最后一步。请在 API 请求之前,加入一个风控检查的逻辑(调用
riskControl.check(...))。这是一个异步函数,如果检查不通过,它会抛出一个错误
AI 在第 2 步和第 3 步之间,加了几行代码,完美收工
总结
这次重构,我总共花了大概 5 个小时,而不是原计划的一周
总觉得 AI 不会淘汰会写代码的工程师,只会降维打击那些只会堆砌代码的工程师
那段 500 行的屎山,在过去,是我的噩梦;现在,有了 AI 的帮助,它变成了我的靶场
这种感觉,真爽