大型代码库 + AI——上万行代码时 AI 还管用吗
大型代码库 + AI——上万行代码时 AI 还管用吗
适读人群:维护过老项目的工程师、Tech Lead | 阅读时长:约14分钟 | 核心价值:10万行代码库里AI辅助开发的真实边界和可用策略
去年接手了一个运行了8年的 Java 单体项目,代码量大约 11 万行,没有完整的文档,原始开发团队大部分已经离职。
接手第一天,我就想着用 AI 辅助——毕竟我已经在小项目里用顺手了。然后我发现,当代码库达到这个量级,AI 的使用方式要完全重新想。
这篇文章就是我在这个项目里摸索出来的经验,包括哪些地方 AI 还管用,哪些地方它开始犯错,以及我用的应对策略。
问题在哪里:上下文窗口是假象
很多人说现在的模型上下文窗口很大,几十万 token,大代码库不是问题了。
这个说法对了一半,错了一半。
窗口大了,能放进去的代码确实更多了。但"能放进去"和"能有效理解"不是一回事。
我做过一个测试:把整个核心模块(大约 15000 行代码,约 50000 token)全部塞进上下文,然后问模型关于某个具体业务逻辑的问题。
结果:模型给出了看似合理的答案,但有两处关键细节是错的——它把两个不同模块里相似命名的方法搞混了,给出了一个逻辑上说得通但实际上对应错误代码路径的解释。
更麻烦的是,这种错误很难发现。模型说得头头是道,如果你不去实际跑代码验证,很容易就信了。
核心问题是:超出一定量级之后,模型的注意力会分散,对"不重要"的部分处理会变粗糙。
哪些场景 AI 依然靠谱
明确了边界,我们来说什么场景还能用好 AI。
场景一:局部函数分析和重构
这是我用得最多的场景。把一个独立的方法(通常不超过 100 行)连同它直接依赖的类定义一起给 AI,让它:
- 解释这个方法在做什么
- 找潜在的 bug 或边界情况
- 给出重构建议
这个上下文通常在 2000-5000 token 以内,模型处于最佳工作状态,质量很稳定。
举个真实例子。项目里有个方法我看了半天没看懂:
public BigDecimal calcFinalAmount(Order order, List<Coupon> coupons, boolean isVip) {
BigDecimal base = order.getAmount();
BigDecimal discount = BigDecimal.ONE;
if (isVip && order.getType() != OrderType.FLASH_SALE) {
discount = discount.multiply(new BigDecimal("0.95"));
}
for (Coupon c : coupons) {
if (c.getMinAmount() != null && base.compareTo(c.getMinAmount()) < 0) {
continue;
}
if (c.getType() == CouponType.PERCENT) {
discount = discount.multiply(BigDecimal.ONE.subtract(c.getValue()));
} else if (c.getType() == CouponType.FIXED) {
base = base.subtract(c.getValue());
}
}
return base.multiply(discount).setScale(2, RoundingMode.HALF_UP);
}我把这段代码加上 Order、Coupon、OrderType、CouponType 的定义给 AI,问它有没有问题。
AI 给出了两个有价值的观察:
- 折扣叠加顺序问题:FIXED 类型的优惠券先扣减
base,再乘以折扣率。但如果 PERCENT 和 FIXED 的优惠券都有,处理顺序会影响最终金额,代码里没有对顺序做任何保证。 - 精度问题:
BigDecimal("0.95")用字符串构造是对的,但c.getValue()如果是从数据库里读出来的 double,在赋值时可能已经精度丢失了。
这两个问题,第一个我后来跟业务确认,确实是历史遗留的计算口径不一致问题;第二个我去查了数据库表结构,value 字段确实是 decimal(10,4),但 Hibernate 映射用的是 Double,有精度风险。
AI 没有全知全能,但这两个发现帮我省了不少时间。
场景二:测试用例生成
老项目的测试覆盖率通常很低。我这个项目,核心业务代码的测试覆盖率大概只有 18%。
手写测试很枯燥,但给 AI 做这件事效果很好:把一个方法的实现给它,让它生成覆盖正常路径、边界情况、异常情况的测试用例。
// AI 为上面那个 calcFinalAmount 生成的测试(节选)
@Test
void testVipDiscountNotAppliedForFlashSale() {
Order order = new Order();
order.setAmount(new BigDecimal("100.00"));
order.setType(OrderType.FLASH_SALE);
BigDecimal result = service.calcFinalAmount(order, Collections.emptyList(), true);
// VIP 折扣不应用于秒杀订单
assertEquals(new BigDecimal("100.00"), result);
}
@Test
void testCouponMinAmountThreshold() {
Order order = new Order();
order.setAmount(new BigDecimal("50.00"));
Coupon coupon = new Coupon();
coupon.setType(CouponType.FIXED);
coupon.setValue(new BigDecimal("10.00"));
coupon.setMinAmount(new BigDecimal("100.00")); // 门槛100,订单只有50
BigDecimal result = service.calcFinalAmount(order, List.of(coupon), false);
// 未达到使用门槛,优惠券不生效
assertEquals(new BigDecimal("50.00"), result);
}
@Test
void testPercentCouponAndVipStackDiscount() {
Order order = new Order();
order.setAmount(new BigDecimal("200.00"));
order.setType(OrderType.NORMAL);
Coupon coupon = new Coupon();
coupon.setType(CouponType.PERCENT);
coupon.setValue(new BigDecimal("0.10")); // 九折
coupon.setMinAmount(null);
BigDecimal result = service.calcFinalAmount(order, List.of(coupon), true);
// VIP 95折 × 优惠券90折 = 85.5折
// 200 * 0.90 * 0.95 = 171.00
assertEquals(new BigDecimal("171.00"), result);
}这些测试用例我跑了一遍,有 2 个 fail,恰好发现了代码里的一个边界问题。测试本身的质量不错。
场景三:SQL 和数据库查询分析
老项目里经常有复杂的原生 SQL,有时候加了大量 JOIN、子查询,看起来头疼。
把 SQL + 表结构给 AI,让它解释查询意图,效果很好。这类任务上下文不大,AI 基本不会犯错。
场景四:日志分析和异常排查
给 AI 一段异常堆栈 + 相关代码,让它分析可能的原因。这个场景上下文可控,准确率很高。
哪些场景 AI 开始犯错
场景一:跨文件的全局分析
"分析整个订单模块的数据流" 这类问题,需要同时理解几十个类之间的关系。把所有代码堆进去,模型开始犯各种混淆错误。
我的策略:分层切割。先让 AI 分析入口(Controller),理解接口和参数。再分析 Service 层的核心方法。再分析 Repository 层的查询。每一层单独问,自己在头脑中整合。
场景二:隐式业务规则
老代码里有大量隐式的业务规则,散落在各种 if 判断里,没有注释,只有做过这个项目的人才知道背后的含义。
AI 会把这些规则照字面理解,但无法知道"为什么这么写"。这类问题只能去找残存的文档或者老同事问。
场景三:需要运行时信息的分析
"这个代码在生产环境里为什么慢" 这类问题,不加运行时数据(慢查询日志、Profiler 结果),AI 只能猜。它猜的方向不一定错,但很容易猜偏。
我的实际工作流
针对大型代码库,我总结出了一套相对稳定的工作方式:
第一步:用 AI 做模块地图
让 AI 分析项目的包结构,生成一个模块职责说明。这是它擅长的工作,输出的结果可以当作我自己后续工作的参考索引。
第二步:以方法为单位工作
绝大多数日常开发任务,我把粒度控制在单个方法或最多一个类的范围内。需要理解上下游依赖时,手动把相关类的关键部分补进去,不全量导入。
第三步:对 AI 给的结论做验证
特别是涉及业务逻辑的分析,我会在代码里跑一下,或者写个简单的测试验证 AI 的判断。大代码库里 AI 犯错的概率比小项目高,验证是必要习惯。
第四步:让 AI 写测试,自己跑
测试生成是 AI 在大代码库里价值最稳定的场景。生成之后我自己跑,失败的测试反过来成了我深入理解代码的线索。
一个数据参考
在这个 11 万行的项目里工作了差不多 3 个月,AI 辅助让我的效率提升大概有 30%——但这个提升几乎全部来自"局部分析"和"测试生成"这两个场景,全局分析类的任务基本没什么帮助,有时候反而耗时间(因为要过滤掉 AI 的错误信息)。
所以我的建议是:不要对 AI 有全知全能的期待,要对它的能力边界有清醒认识,然后把它用在它真正擅长的地方。
大型代码库里,AI 是一个好的局部助手,不是一个能理解全局的架构师。
