用 AI 写代码快了 10 倍,但代码写完之后呢?Review 变成了新的瓶颈。我拿 Claude Code 对着一个 React 项目做了一轮完整的 Code 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 确实比人类强。不是强一点,是强很多。
这是 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 不会。它会逐行检查每个属性访问是否安全。
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 能做到。
这是最让我"后背发凉"的部分。
// 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 在检查自己写的代码的安全性时反而很在行——它知道自己容易犯什么错。
// 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 不会放过。
// 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 翻车的地方。不是小翻车,是那种"听了它的建议会出大事"的翻车。
// AI 认为这段代码"没问题"
function PriceDisplay({ price, discount }) {
const finalPrice = price - discount;
return <span>¥{finalPrice.toFixed(2)}</span>;
}
AI 看不出问题。但做过电商的人一眼就知道——finalPrice 可能是负数。当折扣大于原价的时候,用户看到的是 ¥-15.00。
这种业务层面的约束,AI 不知道"折扣不能大于原价",也不知道"价格为负应该显示为 0"。它只检查代码逻辑,不理解业务规则。
AI 给每个文件的建议都是对的,但合在一起可能是灾难。
AI 的建议:
✅ "这个组件应该用 React.memo 优化"
✅ "这个数据应该用 Context 共享"
✅ "这个列表应该用虚拟滚动"
实际情况:
这三个建议如果同时执行,Context 值变化 → 所有 memo 组件重渲染
→ 虚拟滚动的状态全部重置 → 用户体验比优化前还差
AI 看不到组件之间的依赖关系和数据流走向。它给每个零件都做了最优解,但拼在一起不是最优系统。
// AI 觉得这段代码没问题
function DeleteButton({ onDelete }) {
return <button onClick={onDelete}>删除</button>;
}
AI 检查不出来的问题:
这些都是人类用过产品才知道的问题。AI 没用过你的产品,它只看代码。
// 文件 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 单个文件的时候一切正常。但它不会告诉你"改了这里会影响那里"——因为它的上下文窗口装不下整个系统。
这是最隐蔽的坑。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 能力 | 人类能力 | 结论 |
|---|---|---|---|
| 空值/边界检查 | ⭐⭐⭐⭐⭐ | ⭐⭐ | 交给 AI |
| 性能反模式 | ⭐⭐⭐⭐ | ⭐⭐ | 交给 AI |
| 安全漏洞 (XSS/注入) | ⭐⭐⭐⭐ | ⭐⭐⭐ | AI 先扫,人工复核 |
| 命名/风格一致性 | ⭐⭐⭐⭐⭐ | ⭐⭐ | 交给 AI |
| 重复代码检测 | ⭐⭐⭐⭐⭐ | ⭐ | 交给 AI |
| 业务逻辑正确性 | ⭐ | ⭐⭐⭐⭐⭐ | 必须人工 |
| 架构合理性 | ⭐⭐ | ⭐⭐⭐⭐ | 必须人工 |
| 用户体验影响 | ⭐ | ⭐⭐⭐⭐⭐ | 必须人工 |
| 跨模块副作用 | ⭐ | ⭐⭐⭐⭐ | 必须人工 |
| 重构是否值得 | ⭐⭐ | ⭐⭐⭐⭐ | 必须人工 |
一句话总结:AI 管"正不正确",人类管"该不该这么做"。
实验之后,我调整了 Review 方式:
第一遍:AI 扫描(5 分钟搞定)
第二遍:人工 Review(只看 AI 管不了的)
以前一个 PR 要 Review 半小时,现在 AI 扫完第一遍,我只需要花 10 分钟看业务逻辑和架构决策。效率提升了,质量反而更高——因为 AI 帮我把那些"注意力不集中就会漏掉"的机械性检查全做了。
但有一条铁律:AI 标记"没问题"的代码,不代表真的没问题。它只是说"在我能看到的范围内没问题"。业务逻辑对不对、架构合不合理、用户体验好不好——这些永远是人的活。
你们团队用 AI 做 Code Review 了吗?发现过什么 AI 特别擅长或者特别离谱的场景?评论区聊聊。