我让AI给前端项目做了一次完整的Code Review——它和人类的差距,比我想的大得多
用AI写代码快了10倍,但代码写完之后呢?Review变成了新的瓶颈。我拿Claude Code对着一个React项目做了一轮完整的Code Review,结果发现:有些问题它比人类敏锐得多,有些地方它犯的错比实习生还离谱。
起因:Review堆积如山
团队开始用AI写代码之后,PR数量翻了一倍。代码写得快了,但Review的速度没跟上。每天打开GitLab,十几个待Review的MR盯着你,每个都是AI生成的几百行代码。
GitLab发布的AI Accountability Report里有个数据:85%的受访开发者认为,AI已经把瓶颈从"写代码"转移到了"Review代码"。
既然AI制造了这个问题,那能不能让AI自己来解决?
我做了一个实验:拿Claude Code对一个中等规模的React前端项目(约200个组件,3万行代码)做一次完整的Code Review,看看它到底能发现什么、会漏掉什么。
AI Review能抓到的5类问题——人类真的容易忽略
先说结论:在某些维度上,AI Review确实比人类强。不是强一点,是强很多。
1. 未处理的边界条件
这是AI最强的领域。它会不厌其烦地检查每一个变量可能为空的情况。
// AI 标记的问题:data 可能是 undefined
function UserProfile({ userId }) {
const { data } = useQuery(['user', userId], fetchUser);
return (
<div>
<h1>{data.name}</h1> {/* 💥 data 还没加载时直接炸 */}
<p>{data.email}</p>
</div>
);
}
// AI 建议的修复
function UserProfile({ userId }) {
const { data, isLoading, error } = useQuery(['user', userId], fetchUser);
if (isLoading) return <Skeleton />;
if (error) return <ErrorFallback error={error} />;
if (!data) return null;
return (
<div>
<h1>{data.name}</h1>
<p>{data.email}</p>
</div>
);
}
人类Review的时候,看到 useQuery 就默认"肯定有loading状态处理",往往扫一眼就过了。AI不会。它会逐行检查每个属性访问是否安全。
2. 性能反模式
AI对React的重渲染问题特别敏感。
// AI 标记的问题:每次渲染都创建新的对象引用
function Dashboard() {
const filters = { status: 'active', role: 'admin' }; // 每次渲染都是新对象
return <UserList filters={filters} />; // UserList 每次都会重渲染
}
// AI 标记的问题:在 map 中定义内联函数
function TodoList({ todos, onToggle }) {
return todos.map(todo => (
<TodoItem
key={todo.id}
todo={todo}
onToggle={() => onToggle(todo.id)} // 每次渲染都是新函数
/>
));
}
这种问题在小项目里无所谓,但组件多了之后会让页面卡到怀疑人生。人类Review很少有耐心一个个检查对象引用和回调函数的稳定性,AI能做到。
3. 安全漏洞
这是最让我"后背发凉"的部分。
// AI 标记的 XSS 风险
function Comment({ content }) {
return <div dangerouslySetInnerHTML={{ __html: content }} />;
}
// AI 标记的问题:URL 参数直接拼接,存在注入风险
function SearchPage() {
const query = new URLSearchParams(window.location.search).get('q');
fetch(`/api/search?q=${query}`) // 没有编码,可以注入
.then(res => res.json())
.then(setResults);
}
有个数据挺吓人的:研究显示AI生成的代码中,61%功能上是正确的,但只有10.5%是安全的。 也就是说,代码能跑,但全是漏洞。
AI Review在检查自己写的代码的安全性时反而很在行——它知道自己容易犯什么错。
4. 命名和一致性问题
// AI 标记的命名不一致
const getUserInfo = async (id) => { ... } // 用 Info
const fetchUserData = async (id) => { ... } // 用 Data
const loadUserDetail = async (id) => { ... } // 用 Detail
// AI 标记的风格不一致
const isActive = user.status === 'active'; // 布尔值用 is 前缀
const hasPermission = checkPermission(user); // 布尔值用 has 前缀
const canEdit = user.role === 'admin'; // 布尔值用 can 前缀
const userLoggedIn = !!token; // 💥 这个忘了加前缀
这种问题人类Review的时候经常"算了,能跑就行"。AI不会放过。
5. 重复代码和可抽取的公共逻辑
// AI 发现这段 loading + error 处理在 14 个组件中重复出现
function OrderList() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
fetchOrders()
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, []);
if (loading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
// ...
}
// AI 建议抽取自定义 Hook
function useAsync(asyncFn, deps = []) {
const [state, setState] = useState({
data: null, loading: true, error: null
});
useEffect(() => {
setState(prev => ({ ...prev, loading: true }));
asyncFn()
.then(data => setState({ data, loading: false, error: null }))
.catch(error => setState({ data: null, loading: false, error }));
}, deps);
return state;
}
AI能扫描整个项目找到相似的代码片段,这一点人类Review几乎做不到——你Review单个PR的时候不会去翻其他文件对比。
AI Review的5个致命盲区——这些它永远搞不定
说完优点,来说说AI翻车的地方。不是小翻车,是那种"听了它的建议会出大事"的翻车。
1. 业务逻辑是否正确——AI根本不懂你的产品
// AI 认为这段代码"没问题"
function PriceDisplay({ price, discount }) {
const finalPrice = price - discount;
return <span>¥{finalPrice.toFixed(2)}</span>;
}
AI看不出问题。但做过电商的人一眼就知道——finalPrice 可能是负数。当折扣大于原价的时候,用户看到的是 ¥-15.00。
这种业务层面的约束,AI不知道"折扣不能大于原价",也不知道"价格为负应该显示为0"。它只检查代码逻辑,不理解业务规则。
2. 架构决策——局部最优 ≠ 全局最优
AI给每个文件的建议都是对的,但合在一起可能是灾难。
AI 的建议:
✅ "这个组件应该用 React.memo 优化"
✅ "这个数据应该用 Context 共享"
✅ "这个列表应该用虚拟滚动"
实际情况:
这三个建议如果同时执行,Context 值变化 → 所有 memo 组件重渲染
→ 虚拟滚动的状态全部重置 → 用户体验比优化前还差
AI看不到组件之间的依赖关系和数据流走向。它给每个零件都做了最优解,但拼在一起不是最优系统。
3. 用户体验和交互细节
// AI 觉得这段代码没问题
function DeleteButton({ onDelete }) {
return <button onClick={onDelete}>删除</button>;
}
AI检查不出来的问题:
- 删除操作没有确认弹窗,用户误触直接没了
- 按钮没有 loading 状态,用户不知道有没有删成功
- 连续快速点击会触发多次删除请求
- 没有撤销机制
这些都是人类用过产品才知道的问题。AI没用过你的产品,它只看代码。
4. 跨模块的副作用
// 文件 A:用户模块
export function updateUserRole(userId, newRole) {
return api.patch(`/users/${userId}`, { role: newRole });
}
// 文件 B:权限模块(AI Review 文件 A 时看不到这个)
function PermissionGuard({ children, requiredRole }) {
const { user } = useAuth(); // 缓存的用户数据,不会自动更新
if (user.role !== requiredRole) return <Forbidden />;
return children;
}
改了用户角色,但权限守卫用的是缓存数据,不会自动刷新。用户改了角色后看到的还是"无权限"页面,刷新才生效。
AI Review单个文件的时候一切正常。但它不会告诉你"改了这里会影响那里"——因为它的上下文窗口装不下整个系统。
5. "正确但有害"的重构建议
这是最隐蔽的坑。AI经常建议一些"看起来更好"的写法:
// 原始代码(AI 认为"不够优雅")
if (type === 'admin') {
return <AdminPanel />;
} else if (type === 'editor') {
return <EditorPanel />;
} else if (type === 'viewer') {
return <ViewerPanel />;
}
// AI 建议的"优化"
const PANEL_MAP = {
admin: AdminPanel,
editor: EditorPanel,
viewer: ViewerPanel,
};
const Panel = PANEL_MAP[type];
return Panel ? <Panel /> : null;
看起来更优雅对吧?但三个月后新来的同事要加一个 moderator 角色,他不会去翻 PANEL_MAP 这个常量——他会直接在原来应该写 else if 的地方加代码,然后发现加不进去,因为 if-else 已经被"优化"掉了。
不是所有重构都是好的。有时候"笨代码"比"聪明代码"更容易维护。
实战速查表:哪些Review交给AI,哪些必须人工
| Review维度 | AI能力 | 人类能力 | 结论 |
|---|---|---|---|
| 空值/边界检查 | ⭐⭐⭐⭐⭐ | ⭐⭐ | 交给AI |
| 性能反模式 | ⭐⭐⭐⭐ | ⭐⭐ | 交给AI |
| 安全漏洞(XSS/注入) | ⭐⭐⭐⭐ | ⭐⭐⭐ | AI先扫,人工复核 |
| 命名/风格一致性 | ⭐⭐⭐⭐⭐ | ⭐⭐ | 交给AI |
| 重复代码检测 | ⭐⭐⭐⭐⭐ | ⭐ | 交给AI |
| 业务逻辑正确性 | ⭐ | ⭐⭐⭐⭐⭐ | 必须人工 |
| 架构合理性 | ⭐⭐ | ⭐⭐⭐⭐ | 必须人工 |
| 用户体验影响 | ⭐ | ⭐⭐⭐⭐⭐ | 必须人工 |
| 跨模块副作用 | ⭐ | ⭐⭐⭐⭐ | 必须人工 |
| 重构是否值得 | ⭐⭐ | ⭐⭐⭐⭐ | 必须人工 |
一句话总结:AI管"正不正确",人类管"该不该这么做"。
我现在的Review流程
实验之后,我调整了Review方式:
第一遍:AI扫描(5分钟搞定)
- 边界条件、空值检查
- 性能反模式
- 安全漏洞
- 代码风格一致性
第二遍:人工Review(只看AI管不了的)
- 这个需求理解对了吗?
- 这个方案是最简单的吗?
- 改了这里会不会炸那里?
- 用户用起来会不会骂人?
以前一个PR要Review半小时,现在AI扫完第一遍,我只需要花10分钟看业务逻辑和架构决策。效率提升了,质量反而更高——因为AI帮我把那些"注意力不集中就会漏掉"的机械性检查全做了。
但有一条铁律:AI标记"没问题"的代码,不代表真的没问题。它只是说"在我能看到的范围内没问题"。业务逻辑对不对、架构合不合理、用户体验好不好——这些永远是人的活。
你们团队用AI做Code Review了吗?发现过什么AI特别擅长或者特别离谱的场景?评论区聊聊。
更多推荐



所有评论(0)