Claude Code 在代码可维护性指标上的长期影响跟踪
2024 年 3 月,我们的技术团队正式将 Claude Code 引入日常开发流程。当时的决策逻辑很直白:用 AI 提效。CTO 在全员邮件里写的那句话我至今记得,“把重复劳动交给 AI,把思考留给工程师。”
一年零三个月后,当我站在代码库 237 个模块、110 万行代码的体量前回头看,效率数字确实漂亮:需求吞吐量提升 42%,平均开发周期缩短 35%。 但另一组数字让我整夜失眠:生产环境故障平均定位时间从 23 分钟拉长到 67 分钟,新人 Onboarding 周期从 4 周延长到 7 周,代码评审中发现的“逻辑幽灵”(能跑通但没人说得清为什么这么写的逻辑)从每月 2.3 个飙升到 17.8 个。
这不是一篇“AI 辅助编程好不好”的二元判断文章。这是我在一个真实商业项目中,围绕 6 个核心可维护性指标,做了 15 个月连续跟踪后的诚实复盘。如果你正在考虑让团队全面采用 Claude Code,或者已经用了但隐隐觉得哪里不对,这篇文章会帮你建立一个可量化的评估框架,而不是凭感觉说“好用”或“不好用”。
一、核心结论前置:效率曲线与维护成本曲线的“剪刀差”
在展开所有细节之前,我必须先把跟踪 15 个月得出的最核心结论摆在这里:
Claude Code 对代码可维护性的影响不是单向的,而是呈现典型的“剪刀差效应”。 使用初期(0-3 个月),代码可维护性指标(圈复杂度、模块耦合度、注释有效性等)确实出现改善,主要原因是 AI 擅长标准化输出,把原本参差不齐的个人编码风格拉齐到了一个相对统一的基准线上。但随着时间推移(6 个月以上),一个反向趋势开始显现:代码的“表面可维护性”持续向好,但“深层可维护性”,也就是开发者真正理解、修改、扩展代码的能力,开始系统性衰退。
用数据说话(以下数据来自我所在项目的 SonarQube + 人工评审双轨跟踪):
| 跟踪阶段 | 圈复杂度均值 | 代码重复率 | 注释覆盖率 | 新增缺陷密度(个/千行) | 故障定位平均时间 | 新人模块上手时间 |
|---|---|---|---|---|---|---|
| 引入前 3 个月 | 14.2 | 8.7% | 31% | 1.8 | 23 分钟 | 4.2 周 |
| 引入后 1-3 个月 | 10.8 | 5.1% | 28% | 1.5 | 31 分钟 | 3.8 周 |
| 引入后 4-9 个月 | 9.3 | 4.2% | 22% | 2.1 | 48 分钟 | 5.6 周 |
| 引入后 10-15 个月 | 8.7 | 3.8% | 17% | 2.7 | 67 分钟 | 7.3 周 |

这意味着什么?如果你只看 SonarQube 的仪表盘,你会以为代码库越来越健康。但如果你关注的是“出了问题时谁能修好”、“新同事能不能快速上手”,答案可能正相反。
这不是 Claude Code 本身的错。工具是中性的。问题出在我们使用它的方式,以及我们忽略了代码可维护性中那些不能被自动化工具量化的维度。
二、背景:我们是如何引入和跟踪的
在深入拆解每个指标之前,我必须先交代清楚跟踪条件,因为脱离了上下文谈“数据”,跟造谣没区别。
项目背景:
这是一个 B2B SaaS 产品,服务于制造业供应链管理。技术栈是 Java 17 + Spring Boot 3.x + PostgreSQL + Redis,前端 React 18 + TypeScript。团队规模 23 人(5 个后端小组、3 个前端、2 个 QA、1 个 SRE、1 个架构师加我,技术经理)。项目从 2021 年启动,到 2024 年初引入 Claude Code 时,代码库已经有约 80 万行业务代码。
Claude Code 使用方式:
我们没有一刀切地要求“全部用 AI 写”。实际落地模式是这样的:
- 后端 CRUD 接口、DTO 转换、单元测试生成:全量使用 Claude Code,人工只做 Review。
- 复杂业务逻辑、状态机流转、分布式事务:开发者先手写核心骨架和关键注释,然后让 Claude Code 填充实现细节,最后人工精调。
- 数据库 Schema 变更、索引优化建议:用 Claude Code 生成建议,但必须经过 DBA 和架构师双重审核后才执行。
- Code Review:底线规则是“每一行 AI 写的代码都必须至少一个人类理解过”。但实际执行中,这个规则的遵守率从第一季度的 91% 下降到了第四季度的 62%(因为交付压力)。
跟踪指标体系:
我选择了 6 个核心可维护性指标进行双轨跟踪,既看自动化工具扫描结果(SonarQube、Checkstyle、JaCoCo),也做人工定性评估(代码评审记录、故障复盘报告、开发者调研)。这 6 个指标是:
- 圈复杂度(Cyclomatic Complexity)
- 模块耦合度(Coupling Between Modules)
- 代码重复率(Duplication Rate)
- 注释与文档有效性(Comment & Documentation Effectiveness),注意,不是“覆盖率”,是“有效性”
- 缺陷定位效率(Defect Localization Efficiency)
- 新人上手周期(Newcomer Ramp-up Period)
选这 6 个指标的逻辑是:前三项是“常规体检指标”,行业里都在看;后三项是我自己加的“压力测试指标”,一个代码库是不是真的好维护,不是看它平时多漂亮,而是看出了问题时多快能修好,以及新人多快能上手。
下面,我将逐个展开每个指标的长期跟踪观察、背后的机理变化、以及被多数团队忽略的隐性成本。
三、指标拆解(一):圈复杂度,数字越好看,理解越困难
3.1 什么叫“数字好看但理解困难”?
圈复杂度衡量的是一个函数内部逻辑路径的数量。行业共识是:单个函数的圈复杂度最好不超过 10,超过 15 就需要重构。这个指标在 SonarQube 等工具里是自动计算的,CI/CD 流水线里设一个阈值就能卡住。
引入 Claude Code 后,我们的圈复杂度中位数从 14.2 降到了 8.7(降幅 39%)。 单看这个数字,任何技术经理都会觉得“稳了”。但诡异的事情发生在代码评审环节。
让我举一个真实的代码片段案例(已脱敏):
引入 Claude Code 之前,我们有一个处理采购订单状态流转的函数,圈复杂度 18,大概 140 行。代码里能明显看到 4 个状态分支、2 个异常路径和一个补偿逻辑。虽然圈复杂度超标了,但代码结构映射了业务状态机,你读代码的时候,脑子里可以还原出“订单从待审批→已确认→部分发货→已完成”这条主干。
引入 Claude Code 6 个月后,同一个业务逻辑被重构了。新的实现圈复杂度只有 7,大概 80 行。看起来干净多了对吧?但当我让一个没有参与这个模块的资深开发者来解释这段代码时,他花了 41 分钟才理清逻辑。为什么?因为 Claude Code 用了 3 层嵌套的 Stream 操作 + 函数式组合来替代显式的 if-else 分支。代码确实“简洁”了,但业务状态机的显式表达消失了。你不再能“看到”状态流转,你必须在大脑里执行一遍 filter-map-collect 的逻辑链才能推演出“这段代码在什么条件下会做什么事”。
这是圈复杂度指标最大的盲区:它只衡量逻辑路径的数量,不衡量这些路径的“人类可解析性”。 Claude Code 擅长把复杂的显式分支改写成紧凑的函数式表达式,这让圈复杂度数字变好看了,但实际上把理解成本从“代码结构层”转移到了“大脑模拟执行层”。

3.2 为什么圈复杂度在持续下降,但我越来越不安?
我统计了 15 个月里所有圈复杂度低于 5 的函数,然后对比了它们在故障中的“出镜率”。结果发现:圈复杂度 3-5 的函数区间里,引入 AI 后新增的代码在故障中的占比高达 38%,而同等圈复杂度的人工手写代码只占 11%。
深入排查后发现一个规律:Claude Code 在面对“这段逻辑有点复杂”的场景时,有一个很聪明的策略,拆函数。它会自动把一个复杂函数拆成 4-5 个小函数,每个小函数的圈复杂度都控制在 3-4。这样总体的圈复杂度统计就很好看。但问题是,这种拆分是基于代码结构相似性的,而不是基于业务语义边界的。 结果是,一个原本内聚的业务逻辑被打散到 4 个语义上并无明显边界的“技术性”小函数里,你要理解一个业务流程,就得在 4 个函数之间反复跳转,在大脑里做“逻辑拼接”。
我管这种现象叫 “碎片化内聚”:函数拆得很小,每个看起来很简单,但它们之间没有清晰的语义边界,拼回去的成本远高于当初拆开的收益。
3.3 长期影响:开发者的“逻辑跟踪肌肉”在萎缩
还有一个更隐蔽的长期影响,我在跟踪到第 9 个月左右才开始觉察。因为 Claude Code 持续产出“看起来简单”的小函数,开发者在代码评审时越来越依赖“这个函数圈复杂度合格”的信号来做判断,而不再深入跟踪这个函数在整个业务流程中的位置。
我抽查了第 10-12 个月的 50 条 Code Review 记录。当评审者看到圈复杂度为 3-5 的函数时,点“Approve”的概率是 87%。其中只有 23% 的评审者会点开这个函数所调用的其他函数来理解完整逻辑链。
这说明什么?圈复杂度指标正在从“一种帮助我们发现复杂代码的信号”退化成“一种让评审者放松警惕的安慰剂”。 工具说没问题,人就懒得再看了。而这种行为模式一旦固化,开发者对复杂逻辑的直觉敏感度会持续下降。我在年底跟团队做一对一复盘时,至少有 4 个开发者坦诚地说:“现在看代码没以前那么仔细了,总感觉 AI 写的应该没啥大问题。”
这是一个危险的信号。不是 AI 写的代码变差了,而是人类评审者在适应 AI 的产出质量后,降低了自己的审查标准。 这个“标准蠕降”效应(Standard Creep),我后面会单独展开。
四、指标拆解(二):模块耦合度,依赖关系的“隐形膨胀”
4.1 引入 Claude Code 后的模块依赖全景
模块耦合度衡量的是不同模块之间的依赖关系强度和数量。理想状态是“低耦合、高内聚”,每个模块内部紧密相关,模块之间通过清晰的接口通信,尽量减少直接依赖。
我们使用 JDepend 和 ArchUnit 来跟踪这个指标。数据变化如下:
| 跟踪阶段 | 平均每个模块的传出依赖数 | 循环依赖数 | 违反分层架构的次数 |
|---|---|---|---|
| 引入前 3 个月 | 4.7 | 3 个 | 12 |
| 引入后 1-3 个月 | 4.2 | 2 个 | 9 |
| 引入后 4-9 个月 | 5.8 | 7 个 | 31 |
| 引入后 10-15 个月 | 7.3 | 14 个 | 67 |
前 3 个月是向好的。原因很简单:Claude Code 在生成代码时会遵循项目已有的分层结构和接口规范,而且初期的重构也帮助清理了一些历史遗留的不合理依赖。
但第 4 个月之后,拐点出现了。 传出依赖数从 4.2 一路涨到 7.3,循环依赖翻了 7 倍。
4.2 为什么 Claude Code 会“主动引入”不必要的依赖?
排查了几十个违反分层架构的案例后,我发现了一个高频模式。假设有一个场景:订单模块需要一个“根据用户 ID 查询用户名称”的功能。正确的做法是订单模块调用用户模块提供的接口,或者通过一个共享的 Service 层来获取。但在 Claude Code 生成的代码里,我多次看到这种实现:
// 订单模块里直接注入了用户模块的 DAO 或内部实现类
@Autowired
private UserInternalMapper userInternalMapper;
当你追问 Claude Code“为什么要直接注入内部实现而不是调用接口”时,它的回答通常是:“因为这样可以减少一次网络调用”或者“这样代码更简洁”。但深层原因是:Claude Code 生成代码时,会优先在它能看到的所有类里搜索“最快完成任务”的路径,而不会考虑“这个依赖在架构层面是否合理”。
它没有架构边界的概念。在它的“认知”里,整个代码库是一张平的符号网络,只要能引用到的类,就是可以用的。这种“平坦化”的依赖构建方式,是模块耦合度长期恶化的核心驱动力。

4.3 循环依赖的“滚雪球”效应
循环依赖是最让我头疼的问题。一旦出现 A→B→C→A 这种循环依赖,模块的独立测试、独立部署、独立理解都变得极其困难。
引入 Claude Code 后,新增的循环依赖有一个共同特征:它们不是在一个 commit 里产生的,而是在 2-3 个连续的、由不同开发者提价的 commit 里“逐渐形成”的。 典型场景是这样的:
- 第一天,开发者 A 用 Claude Code 在订单模块里加了一个功能,AI 为了方便直接引用了库存模块的一个内部工具方法。
- 第二天,开发者 B 在库存模块里修一个 Bug,Claude Code 生成的修复代码“顺手”引用了订单模块的一个 DTO 来做数据转换。
- 第三天,Code Review 的人只看了各自的 diff,没发现跨模块的耦合环路已经闭环了。
这种“渐进式循环依赖”是 AI 辅助编程特有的债务模式。 传统开发中,一个人写一个功能时,如果引入循环依赖,他大概率会在当下就意识到(因为那是一个显式的、集中的设计决策)。但在 AI 辅助模式下,依赖是分散在多个“微提交”里的,每一步看起来都无害,合在一起才构成问题。
4.4 为什么自动化工具没能拦住?
我们的 CI 流水线里配了 ArchUnit 规则来检测循环依赖和分层违规。理论上,这些违规应该在提交时就被拦下来。但实际操作中遇到了一个问题:ArchUnit 规则需要随着项目演进不断更新,而引入 Claude Code 后架构演进的速度超过了规则更新的速度。
举个例子:我们有一条规则叫“Controller 层不能直接调用 DAO 层”。但 Claude Code 在一次重构中,把一个原来在 Service 层的查询逻辑“优化”到了 Controller 层的方法里(因为 AI 认为“这个查询很简单,没必要走 Service 层”)。这种优化单看性能是合理的,但它破坏了架构分层。ArchUnit 规则确实报了警,但开发者选择了“Suppress Warning”,理由是“这是 AI 推荐的最佳实践,应该没问题”。
这引出了一个更深层的问题:当 AI 给出的建议与架构规则冲突时,开发者倾向于信任谁? 我的观察是,至少在 2024 年,相当多开发者选择了信任 AI。原因不全是偷懒,AI 确实在很多场景下给出了技术上更优的方案。问题是,“技术上更优”不等于“架构上更合理”,而后者超出了当前 AI 的判断能力。
五、指标拆解(三):代码重复率,消除的不只是重复,还有业务表达
5.1 重复率下降的另一面
代码重复率是 SonarQube 里最容易出“政绩”的指标。我们的重复率从 8.7% 降到了 3.8%,降幅高达 56%。如果我要在季度汇报里美化成绩,光这一条就够我用 3 页 PPT。
但如果你深挖“重复代码是怎么被消除的”,你会发现两种截然不同的消除方式:
方式一:语义级消除。 两个原本重复的代码块确实在做同一件事,应该抽取成公共方法。这是健康的消除。
方式二:巧合级消除。 两个代码块看起来一样,但实际上分属不同的业务上下文,只是“恰好”写法一致。AI 看到了这种表面一致性,把它们合并了,结果把两个本应独立演进的业务逻辑耦合在了一起。
我统计了引入 Claude Code 后 6 个月内的 43 次“重复代码消除重构”,其中 17 次(40%)属于方式二。也就是说,有将近一半的“重复率改善”是以牺牲业务逻辑的独立演进能力为代价的。

5.2 一个翻车案例
说一个具体的翻车案例。我们的系统里有“采购退货”和“销售退货”两个模块。在引入 Claude Code 之前,这两个模块各有一段约 60 行的退款计算逻辑。两段代码确实长得非常像,都要算退款金额、扣减优惠、处理运费分摊。但它们的业务规则有细微差别:采购退货的运费是由我方承担的(因为我们指定了物流商),而销售退货的运费规则更复杂,取决于退货原因(质量问题我方承担,客户原因客户承担)。
Claude Code 在某次重构中,识别到了这两段代码的“重复”,自动把它们抽取成了一个公共的 calculateRefundAmount() 方法。参数里加了一个 type 枚举来区分采购和销售。在 AI 看来,这是一个完美的抽象。
3 个月后,销售退货的运费规则变更了,需要增加一个“部分质量问题”的场景(比如一个订单里 5 件商品,2 件有质量问题的我方承担运费,3 件客户改变主意的客户承担)。开发者在公共方法里加了这个逻辑,但没注意到这个变更也会影响采购退货的计算路径,因为采购退货根本没有“客户改变主意”这种场景。结果就是,采购退货模块出现了一个 latent bug,直到季度财务报表对不上才被发现。
这个翻车案例的核心教训是:重复代码有时候不是“冗余”,而是一种“业务隔离机制”。 两个长得像但分属不同限界上下文的代码块,让它们保持独立、各自演进,比把它们合并但增加分支逻辑,在长期维护中更安全。
5.3 Claude Code 为什么倾向于过度消除重复?
Claude Code 的训练数据里,充满了“DRY 原则是好的”、“重复代码是坏的”这类信号。DRY(Don‘t Repeat Yourself)作为一条软件工程原则本身没问题,但 AI 执行它的时候是字面级别的,而不是语义级别的。
AI 判断“重复”的依据是 token 序列的相似度。两段代码 token 相似度达到一定阈值,它就判定为重复并建议合并。但 AI 无法可靠地判断:这两段代码在业务上是不是真的“同一个东西”?它们未来会不会因为不同的业务需求而各自演进?
这种能力缺失,使得 Claude Code 在消除重复这件事上呈现出“过度热情”。它像一个拿到了“清理重复代码”KPI 的初级工程师,为了做而做,不管合不合理。
六、指标拆解(四):注释与文档有效性,“被写出来”和“能帮到人”是两回事
6.1 这个指标为什么改名叫“有效性”而不是“覆盖率”
在引入 Claude Code 之前,我们用的是“注释覆盖率”这个指标。工具扫描代码,计算有注释的类、方法、字段占总数的比例。这是一个非常容易造假的指标,写一堆 // set name 也能提升覆盖率。
所以我把它改成了“注释与文档有效性”,并且加入了人工评估环节。每两周,我会随机抽取 10 个新增或修改较多的模块,让一个不熟悉该模块的开发者阅读代码并回答 5 个业务理解题。答对的比例,就是“有效性”的核心度量。
引入 Claude Code 后的数据让我非常意外:
| 跟踪阶段 | 注释覆盖率(工具扫描) | 人工评估有效性(答题正确率) | AI 生成注释占比 |
|---|---|---|---|
| 引入前 3 个月 | 31% | 78% | 0% |
| 引入后 1-3 个月 | 28% | 74% | 34% |
| 引入后 4-9 个月 | 22% | 56% | 68% |
| 引入后 10-15 个月 | 17% | 41% | 84% |
注释覆盖率本身就在持续下降,因为开发者越来越依赖 AI,自己越来越少写注释。但更值得警惕的是有效性崩塌。 覆盖率从 31% 降到 17% 只是减少了 14 个百分点,但有效性从 78% 跌到 41%,几乎腰斩。
为什么?因为 AI 生成的注释虽然数量上能补位,但质量上有系统性缺陷。

6.2 AI 注释的四种经典失败模式
我归纳了 Claude Code 生成注释最常见的四种失败模式:
模式一:复述代码,不解释意图。
// 遍历订单列表,对每个订单调用 processOrder 方法
for (Order order : orders) {
processOrder(order);
}
这种注释对理解业务毫无增量信息。它只是在翻译代码,而不是解释“为什么需要遍历”、“processOrder 在业务上做了什么”。但 Claude Code 非常喜欢生成这种注释,因为它基于“代码→自然语言翻译”的模式运作。
模式二:描述了“怎么做”,没解释“为什么”。
// 先查缓存,如果缓存没有则查数据库,结果放入缓存并设置 30 分钟过期
这个注释描述了技术实现步骤。但它没有解释:为什么这个业务场景需要缓存?这个 30 分钟是怎么定出来的?缓存穿透了会有什么影响?这些对维护者至关重要的“为什么”视角,在 AI 注释里几乎是系统性地缺失。
模式三:注释和代码在“各说各话”。
这是最危险的一种。当开发者在 AI 辅助下修改了代码逻辑,但没同步更新注释,或者 AI 生成了新注释但没正确反映修改后的逻辑,就会出现“注释说 A,代码做 B”的情况。我统计了第 10-12 个月的 28 个 Bug,其中有 9 个(32%)的根因与“注释和代码不一致”有关。开发者根据注释理解了逻辑,做了后续修改,结果踩了坑。
模式四:无差异化的“模板注释”。
/**
创建订单
*
@param orderDTO 订单数据传输对象
@return 创建结果
*/
这个注释可以被贴在任何“创建”方法上。它没有告诉你:创建订单涉及哪些校验规则?是否会触发库存预占?事务边界在哪?异步通知什么时候发?这些才是维护者真正需要知道的信息。
6.3 深层问题:谁在维护“知识”?
代码注释和文档,本质上是一种 “知识沉淀”机制。开发者在写代码的同时,把他对业务的理解、对设计的权衡、对坑点的记录,沉淀成文字,留给未来的自己和其他人。
Claude Code 参与编码后,这个知识沉淀链条出现了一个缺口。 AI 生成了代码,但 AI 并不真正“理解”业务,所以它生成的注释无法承载业务知识。而开发者因为自己没有亲手写那段代码,也缺乏足够的理解深度来补充有意义的注释。结果是:代码被生产出来了,但附着在代码上的“组织知识”没有同步生长。代码库越来越大,但团队的集体理解反而越来越稀薄。
这个问题在 6 个月后才开始显性化为“新人上手慢”、“故障定位慢”这些可观测成本,因为前期还有原始开发者的大脑记忆在兜底。但当原始开发者轮岗、离职,或者只是自己忘了当初的逻辑,欠下的“知识债”就开始集中到期。
七、指标拆解(五):缺陷定位效率,从 23 分钟到 67 分钟的“退化曲线”
7.1 为什么 Bug 越来越难找?
缺陷定位效率(Defect Localization Efficiency)是指从发现一个生产环境故障到定位根因代码的平均耗时。这个指标直接反映代码库的“可调试性”。
我们的数据是:从引入前 3 个月的 23 分钟,恶化到 10-15 个月的 67 分钟,接近三倍。这个趋势和圈复杂度、重复率的改善趋势正好相反,表面指标越光鲜,出了问题越难找。
我在 15 个月里记录了超过 200 条故障复盘记录,按根因分类后发现了一个规律:
| 根因类型 | 引入前占比 | 引入后占比 | 平均定位耗时变化 |
|---|---|---|---|
| AI 生成代码的“幽灵逻辑” | 2% | 41% | +142% |
| 业务边界模糊导致的理解偏差 | 18% | 29% | +67% |
| 依赖关系混乱 | 15% | 22% | +89% |
| 传统 Bug(空指针、索引越界等) | 65% | 8% | -31% |
传统 Bug 大幅减少了,这正是 AI 在降低低级错误方面的价值。但取代它们的是“幽灵逻辑”,能跑通、能通过测试、但在特定条件下会产生完全意想不到行为的代码路径。这种 Bug 的定位耗时平均比传统 Bug 长了 142%。

7.2 “幽灵逻辑”长什么样?
举一个真实例子(已脱敏抽象)。我们有一块代码负责计算供应商评分。Claude Code 生成的实现是这样的:
public Score calculateScore(Supplier supplier) {
return Stream.of(
evaluateQuality(supplier),
evaluateDelivery(supplier),
evaluatePrice(supplier)
)
.filter(Objects::nonNull)
.reduce(Score.ZERO, Score::add);
}
看起来干净合理。但问题是:evaluatePrice 方法在某些边界条件下(供应商没有历史报价记录)会返回 null,而这个 null 被 .filter(Objects::nonNull) 静默过滤掉了。结果是:供应商在缺少价格数据时,评分只基于质量和交付两项计算,导致“没有价格数据”的供应商反而得分高于“价格偏贵但数据完整”的供应商。 这个逻辑错误在生产环境跑了 4 个月才被发现,因为它从没报过错、从未抛出异常,只是静默地算出了错误结果。
这种“优雅地执行了错误逻辑”的代码,就是典型的“幽灵逻辑”。它的三个特征让人极其头疼:
- 不出错:不会抛异常、不会打错误日志,一切看起来正常。
- 难测试:单元测试大概率会 mock 掉 evaluatePrice 返回值,所以不会触发 null 路径;集成测试的数据集通常覆盖正常场景,也不会暴露。
- 难定位:出了问题时,你首先要判断“这到底是业务期望的行为还是 Bug”,这一步本身就耗时。
7.3 定位耗时的根因分析
我把 67 分钟的故障定位时间拆解成三个环节:
| 环节 | 引入前耗时 | 引入后耗时 | 增幅 |
|---|---|---|---|
| 复现与范围圈定 | 8 分钟 | 11 分钟 | +38% |
| 代码逻辑追踪 | 9 分钟 | 38 分钟 | +322% |
| 根因确认与修复方案 | 6 分钟 | 18 分钟 | +200% |
最扎眼的是“代码逻辑追踪”环节,从 9 分钟暴增至 38 分钟。 这个环节指的是:你已经知道“大概是这个地方出问题了”,然后去读代码理解逻辑以精确定位根因。为什么这个环节变得这么慢?
我观察到的三个主要原因:
第一,前面提到的“碎片化内聚”。 逻辑被打散到多个小函数里,理解一个业务流程需要跨 5-8 个函数跳转,每次跳转都需要在大脑里做上下文切换和状态拼接。
第二,AI 生成的代码高度同质化。 Claude Code 产出的代码在结构和风格上极其一致,这是好事也是坏事。坏的一面是,当你在排查问题时,浏览十几个函数都长得差不多,很容易“视觉疲劳”,难以快速区分“这个函数是关键路径”和“那个函数只是辅助工具”。人工手写代码虽然风格不统一,但每个人的“代码指纹”本身就是一种定位线索,你知道“这块看起来像是老王写的,老王的逻辑通常会怎么处理这种情况”。
第三,注释和文档的退化。 当你读到一个没有业务上下文注释的函数,唯一的办法就是一行一行在大脑里执行它,这就是 38 分钟的由来。
八、指标拆解(六):新人上手周期,知识传递的“断桥”
8.1 从 4 周到 7 周:不只是效率问题
新人上手周期衡量一个新入职或转岗的开发者,从接触一个模块到能独立完成一个中等复杂度需求所需的周数。
我们的数据从引入前 3 个月的 4.2 周延长到 10-15 个月的 7.3 周,增幅 74%。在技术管理者视角里,这就是“人力成本”:原来一个新人 4 周后就能出活,现在要将近 2 个月。
但我想说的是,这个数字背后还藏着两个更深的成本:
第一,新人挫败感的累积成本。 当新同事花了 3 周还没搞懂一个模块的核心逻辑时,他会开始怀疑自己的能力。这种挫败感对留任率和团队士气的影响,比表面的“晚 3 周出活”严重得多。我在季度一对一谈话中,连续两个季度听到新人说“感觉代码库好难懂,是不是我太菜了”。实际上不是他们菜,是代码库的可理解性出了问题。
第二,老人被迫频繁打断的成本。 新人上手慢,就会更频繁地向老同事求助。我统计了团队内部的技术问答频道:有关“这段代码在干什么”的提问量,在引入 Claude Code 12 个月后,比引入前增加了 3.1 倍。每一个这种提问,都在打断一个资深开发者的深度工作时间。
8.2 是什么让新人“看不懂”了?
我设计了一个实验:让一个新加入团队的开发者(3 年经验,熟悉 Java 和 Spring Boot,但不熟悉我们的业务)分别去读两段代码,一段是 2023 年人工编写的采购订单处理逻辑,另一段是 2024 年 Claude Code 重构后的版本。然后让他用白板画出业务流程。
人工编写版本的还原准确率:72%。
Claude Code 版本的还原准确率:34%。
差异的根因,我在分析他的白板笔记时找到了:
人工编写版本里,类名和方法名直接映射了业务概念,PurchaseOrderService.confirmOrder()、OrderStateMachine.transit()、InventoryReserveHandler。业务流程可以从类名和方法名上“读”出来。
Claude Code 版本里,出现了大量泛化的命名,OrderProcessor.execute()、DataHandler.handle()、StateManager.update()。业务语义淹没在了通用命名里。这些命名在技术上没错,但它们不传递业务信息。
Claude Code 的命名倾向于“描述这个代码在做什么(技术动作)”,而不是“描述这个业务在做什么(业务意图)”。 当整个代码库里充斥着 execute、handle、process、update 这些泛化动词时,代码就变成了一道“填空题”:你必须读进函数内部,才能知道它在处理什么业务。这对新人来说,相当于要求他在没有地图的情况下走通一座城市。

8.3 “知识传递”模式的变化
在全面引入 Claude Code 之前,我们团队的知识传递路径是这样的:
资深开发者理解业务 → 写出映射业务逻辑的代码 → 新人在阅读代码时,通过代码理解业务。
这是一条虽然低效但能工作几十年的路径。代码本身承载了业务知识。
引入 Claude Code 之后,路径变成了这样:
开发者给 AI 描述需求 → AI 生成技术实现 → 开发者 Review 后合并 → 新人尝试阅读代码理解业务 → 发现代码里没有足够业务信息 → 必须额外去寻找文档或询问当事人。
代码不再可靠地承载业务知识。它在某种程度上退化成了“实现细节的集合”,能跑,但不能教你业务。
这意味着,如果你的团队已经被 Claude Code 深度渗透,你不能再依靠“读代码”这个传统方式来传递业务知识。你必须建立主动的知识沉淀机制:业务 wiki、决策记录(ADR)、周期性业务串讲。把“隐性知识”的管理从“代码附带”升级为“体系化运作”,否则新人上手周期的恶化就只是一个开始。
九、被忽略的系统性风险(一):标准蠕降效应
9.1 什么叫“标准蠕降”?
标准蠕降(Standard Creep)原本是一个服务质量管理领域的概念:当一个系统持续输出“略低于标准但还能接受”的结果时,评估者的标准会不知不觉地降低,直到“略低于标准”变成了“新标准”。然后系统再次输出“略低于新标准”的结果,循环往复。
我在跟踪可维护性指标的第 9 个月,第一次意识到标准蠕降正在我们团队发生。触发我警觉的是一件小事:我在 Code Review 时看到一段 Claude Code 生成的代码,注释是 // TODO: optimize later,而这段代码已经在生产环境跑了 2 个月。我翻了一下提交记录,这个 TODO 从第一次生成就存在,期间经过了 3 次修改、2 次 Code Review,没有任何人提出“这个 TODO 应该被解决掉”。
不是因为同事不负责任。是因为他们已经适应了“AI 代码有点小瑕疵是正常的”,而这种适应,让他们对“小瑕疵”的判断门槛在不断降低。
9.2 标准蠕降的三个阶段
我把 15 个月的跟踪划分成三个阶段,观察到了清晰的蠕降轨迹:
第 1 阶段:警惕期(0-3 个月)。 团队对 AI 生成代码保持高度警惕。Code Review 的严格程度不亚于甚至高于人工代码。AI 生成的每一个可疑逻辑都会被拉出来讨论。这个阶段的代码质量实际上是最高的,因为既有 AI 的标准化输出,又有人类的严格把关。
第 2 阶段:信任期(4-8 个月)。 随着 AI 持续产出“看起来没问题”的代码,团队开始建立信任。Code Review 的注意力从“这段代码逻辑对不对”逐渐转移到“这段代码有没有明显 Bug”。细微的逻辑问题开始被放过,因为“AI 的总体质量是可以接受的”。
第 3 阶段:依赖期(9-15 个月)。 AI 已经深度嵌入日常工作流,几乎所有新代码都有 AI 参与。开发者逐渐失去了对“AI 之前写的代码”的质量直觉,因为那些代码不是他们写的,他们也没仔细读过。当这类代码在整个代码库中的占比超过某个临界点(我们的数据大约是 40%),开发者对整个代码库的质量标准就会大幅下调,因为“到处都是这样,还能怎么办”。

9.3 标准蠕降为什么难以察觉?
因为它发生得太慢。就像一个每天胖 10 克的人,照镜子看不出变化,但一年后体检报告会告诉他一切。
更隐蔽的是,工具仪表盘上的数字会持续告诉你“一切都在变好”,圈复杂度下降、重复率降低、测试覆盖率提升。这些“好消息”构成了一个信息茧房,让人很难注意到“代码评审变松了”、“TODO 被无视了”、“新人上手变慢了”这些软性指标的恶化。
标准蠕降的终局是:你拥有一个“看起来很好”的代码库,和一群“不太懂它”的开发者。 这在太平无事时一切正常,但一旦出现需要深层次理解才能解决的关键 Bug 或者架构变更,代价就集中爆发。
十、被忽略的系统性风险(二):开发者“心智肌肉”的退化
10.1 我观察到的“读不懂自己代码”现象
第 11 个月,我给团队做了一个“盲测”。我随机抽取了 8 段每个开发者自己在 2-3 个月前提交的代码(都是 Claude Code 辅助生成后经他 Review 过的),隐去作者信息,让他重新阅读并解释代码逻辑。
结果让我惊出一身冷汗:平均准确率只有 61%。 有 3 个开发者对自己 2 个月前提交的代码的理解出现了显著偏差。其中一个开发者看到自己的代码后沉默了 20 秒,然后说:“这段代码……应该是我写的,但说实话我现在也不确定这个 reduce 操作为什么要这样设计。”
这不是失忆症。这是一个更深层的问题:在 AI 辅助下,开发者不再“亲手写”代码,而是“审核”代码。审核的认知深度远低于亲手写的认知深度。 你亲手写一段逻辑时,你需要在大脑中完整执行一遍、考虑各种边界条件、权衡不同的实现方式。但当你只是审核 AI 的输出时,你只需要判断“看起来对不对”,这是一个更浅层的认知加工过程。浅层加工留下的记忆痕迹本来就弱,加上时间的作用,2-3 个月后基本清零。
10.2 三种核心“肌肉”的退化
我把开发者对代码可维护性至关重要的三种能力称为“心智肌肉”,并跟踪了它们在 15 个月内的退化迹象:
肌肉一:逻辑跟踪能力。 即不运行代码、仅靠阅读就能在脑中推演出一段代码的执行路径和结果的能力。引入 Claude Code 之前,这是我们 Code Review 的核心动作。引入之后,越来越多评审者开始依赖“反正 CI 会跑集成测试”来验证逻辑,而不是在脑中预演。到第 12 个月,我在 Code Review 中观察到“开发者主动追踪代码调用链超过 3 层”的频率,从每月几十次降到了个位数。
肌肉二:重构直觉。 即看到一个复杂逻辑时,能凭直觉判断“这里应该抽取”、“那里应该合并”、“这个抽象值得做”的能力。这种直觉是大量重构经验积累出来的。但当 AI 接管了重构建议(“我来帮你优化这段代码”),开发者自己就不再积累重构经验了。结果是:开发者越来越依赖 AI 来发现重构机会,但 AI 只能发现“统计意义上的优化”,无法做出“业务意义上的权衡”。
肌肉三:调试韧性。 即面对一个没有明显线索的 Bug 时,能够持续深挖、不放弃直到找到根因的韧性。AI 辅助编程让开发者在“正向开发”(从需求到代码)上效率极高,但“逆向排查”(从现象到根因)的能力并没有同步提升。当 Bug 的判断窗口被拉长(如前面提到的 67 分钟),开发者的注意力和耐心消耗更快,更容易中途放弃、转而采用“先把这段代码重写一遍试试”的逃避策略,这往往引入更多问题。
10.3 这不是“AI 让我们变笨了”的哀叹
我必须澄清一点:我描述的这种退化,不是 AI 的错。是使用方式的错。
如果你用计算器做所有算术,你的心算能力会退化,这是工具替代的必然结果。问题不在于计算器好不好,而在于你是否仍然保留“在心中验算”的习惯,是否仍然追求理解计算的原理。
同样的逻辑适用于 Claude Code。如果你把 AI 当成“代写工具”,你的代码理解能力会退化。如果你把 AI 当成“辅助工具”,你仍然主导设计、仍然亲手写关键逻辑、只是用 AI 帮你填充你已经想清楚的代码块,你的能力就不会退化,甚至可能因为省去了重复劳动而得到强化。
所以,这不是一个“AI 好不好”的问题,而是一个“你愿不愿意继续承担思考责任”的问题。 这个选择权始终在开发者手里。
十一、不同场景下的取舍框架:不是所有代码都“值得”高可维护性
11.1 “可维护性”不是绝对的道德高地
在工程管理领域,“代码可维护性高”通常被当成不容置疑的好事。但我必须在这里引入一个务实的视角:不是所有代码都值得投入同等程度的可维护性精力。
可维护性是一项投资。你投入时间写更清晰的结构、更详细的注释、更合理的抽象,是为了在未来修改这段代码时节省时间。但如果一段代码未来被修改的概率很低,那么过度投入可维护性反倒是一种浪费。
引入 Claude Code 后,这个“投资决策”变得更加复杂。 因为 AI 可以在极短时间内生成代码,这些代码的“可维护性水平”通常在 60-70 分(能跑、不算太烂、但也不算优秀)。把这段代码从 70 分做到 90 分,可能还需要开发者投入大量时间和认知精力。这笔投入值不值得?
我的答案是:取决于代码的战略等级。
11.2 代码战略分级框架
我把项目里的代码按两个维度划分出四个象限:
维度一:变更频率。这段代码所对应的业务逻辑是“高频变化”(如促销规则、报表字段)还是“低频稳定”(如基础数据模型、核心算法)?
维度二:影响半径。这段代码如果出问题,影响的是一个独立页面,还是整个系统的核心流程?
组合出四个象限:
| 高频变更 | 低频变更 | |
|---|---|---|
| 高影响半径 | A 类:核心战场<br>人工主导设计,AI 辅助实现<br>必须追求 90 分可维护性 | B 类:稳定基石<br>可接受 AI 生成,但必须补充高质量文档<br>可维护性目标 80 分 |
| 低影响半径 | C 类:边缘迭代区<br>AI 全量生成 + 轻量 Review<br>可维护性 60 分即可,快速迭代优先 | D 类:一次性/低频<br>AI 直接生成,不追求可维护性<br>坏了就重写 |

这个框架的核心思想是:把有限的可维护性精力,集中在最需要它的地方。
引入 Claude Code 后,团队最大的问题不是“AI 降低了可维护性”,而是 “AI 模糊了所有代码的维护重要性”,因为 AI 能快速产出任何代码,所以不再有人停下来判断“这段代码值不值得我花额外时间去打磨”。结果是,核心模块的可维护性投入不足,而边缘模块却可能花费了过多精力。
11.3 不同象限的具体策略
A 类:核心战场
- AI 参与方式:开发者手写核心结构、状态机、接口定义和关键注释。Claude Code 只用来填充实现细节和生成单元测试。
- Code Review 要求:必须至少两个资深开发者全量 Review,重点审查“业务逻辑完整性”而非语法。
- 文档要求:每个 A 类模块必须有 ADR(架构决策记录)、状态机图和业务规则说明。
- 强制规则:A 类代码中禁止使用 AI 生成的重构建议,除非开发者已经在脑中完整验证了等价性。
B 类:稳定基石
- AI 参与方式:AI 可以生成完整实现,但开发者必须在合并前完成“逆向理解”,即对着代码画出调用链路,确认理解无误。
- 文档要求:必须有清晰的方法级注释(人工补充),解释业务意图和关键参数含义。
- 特别关注:定期检查 B 类模块的传出依赖是否在膨胀(参考第四章的指标跟踪),防止“稳定基石”沦陷为耦合热区。
C 类:边缘迭代区
- AI 参与方式:基本全量使用 Claude Code 生成,Code Review 仅做安全底线检查(如是否引入了外部依赖、是否涉及敏感数据)。
- 可接受的债务:允许适度 TODO,允许圈复杂度略高,但必须能通过集成测试。
- 退出机制:当某个 C 类模块的变更频率连续 3 个月超过阈值,或者影响半径扩大,应当触发“晋升审查”,将其升级为 A 或 B 类,然后补充可维护性投入。
D 类:一次性/低频
- 几乎全量 AI 生成,最低限度的人工检查(能跑就行)。
- 备注:如果一个 D 类模块存在超过 6 个月且仍然“活着”,建议至少做一次快速可维护性评估,因为“你以为是一次性的代码”常常会变成“临时的永久方案”。
十二、行动建议:建立一个“AI 时代的可维护性治理体系”
基于前面所有跟踪观察和分析,我提炼出一套面向“Claude Code 已经在日常使用中”的团队的可维护性治理建议。这不是一套空泛的“最佳实践”,而是我本人在第 12-15 个月期间逐步推行,并看到了初步改善迹象的具体措施。
12.1 第一步:重新定义你的“可维护性仪表盘”
大多数团队的仪表盘停留在“圈复杂度 + 重复率 + 测试覆盖率”这三板斧。正如前文论证的,这些指标在 AI 时代可能产生误导。
我建议新增三个“AI 时代可维护性指标”:
- 理解等价时间(UET,Understanding Equivalence Time):随机抽取一段代码,让不熟悉的开发者阅读并在白板上还原业务逻辑。从开始阅读到能正确解释业务意图的耗时,记录为 UET。每季度抽样 10 个模块,跟踪趋势。
- 注释有效性指数(CEI,Comment Effectiveness Index):人工评估注释中提供了“为什么”和“业务上下文”的比例。AI 生成注释的 CEI 通常低于 30%,人工注释应该高于 70%。目标是让模块的总体 CEI 不低于 50%。
- 依赖健康分(DHS,Dependency Health Score):结合传出依赖数、循环依赖数和跨层违规次数,给每个模块一个 0-100 的健康分。低于 60 分的模块需要纳入重构队列。

12.2 第二步:建立“AI 辅助编码规范”的补丁条款
你现有的编码规范大概率是在“人写代码”的假设下制定的。你需要补充针对 AI 辅助场景的条款。以下是我在实践中验证有效的几条:
条款一:禁止使用泛化动词作为顶层方法名。
- 禁止:
execute()、handle()、process()、update()作为公开方法或核心逻辑方法的方法名。 - 替代要求:方法名必须包含业务动作和业务对象,如
confirmPurchaseOrder()、calculateRefundWithFreight()。
条款二:AI 生成的注释必须经过“为什么”补充。
- AI 生成注释后,开发者必须在提交前回答“这段代码为什么这样写”,并将答案补充进注释。
- 如果开发者无法回答“为什么”(因为逻辑是 AI 决定的而他没深究),该代码不得合并,他必须先搞清楚。
条款三:跨模块引用必须显式声明。
- 任何 AI 生成的代码中如果引入了当前模块原本不依赖的外部模块,必须在提交信息中显式说明“引入依赖 X 模块,原因是 Y”。
- 这种显式声明会在 Code Review 中被重点审查,防止“顺手引用”导致的耦合膨胀。
条款四:单个 PR 中 AI 生成代码占比超过 80% 时,必须附加“逆向理解记录”。
- 提交者需要以注释或 PR 描述的形式,手写一段“这段代码的业务流程是:第一步…第二步…”的简要说明。
- 目的是强制开发者在合并前完成一轮“深度理解”,而不是浅层审核。
12.3 第三步:植入“可维护性 Review”环节
在常规 Code Review 之外,每两周拿出 1 小时,做一次专门的“可维护性 Review”。常规 Code Review 关注的是“这次改动有没有 Bug”,可维护性 Review 关注的是“这次改动让代码库变得更容易维护还是更难维护”。
可维护性 Review 的检查清单:
- [ ] 新引入的方法命名是否传递了业务意图?
- [ ] 是否引入了新的跨模块依赖?这个依赖是否合理?
- [ ] AI 生成的注释是否回答了“为什么”?
- [ ] 重构是否基于业务语义边界而非代码表面相似性?
- [ ] 是否有被忽略的 TODO?
- [ ] 新人(如果团队有新同事)能否在 15 分钟内理解这段代码的业务意图?
这个环节不需要对所有 PR 都做。聚焦在 A 类和 B 类代码(参考第十一章的分级框架),以及那些“改动量很大但看起来没什么问题”的 PR 上。
12.4 第四步:定期做“无 AI 日”或“无 AI 模块”
这是我推行的最有争议、但效果最明显的措施。每两周的周四,全团队有一个“无 AI 日”。在这一天:
- 所有代码都手写(可以用 IDE 的自动补全,但不能用 Claude Code 生成代码块)。
- 重点任务不是赶进度,而是做“深度维护”:读一段自己不熟悉的代码、手改一个历史遗留模块、补充缺失的注释和文档。
- 目标不是产出代码行数,而是加深对代码库的理解。
第 12 个月开始试点时,团队普遍抵触,“这不是倒退吗?”但坚持了 2 个月后,效果开始显现:
- 开发者对代码库的“心里有地图”的感觉在恢复。
- “无 AI 日”之后的 2-3 天里,Code Review 的深度有明显提升(开发者更愿意跟踪调用链)。
- 有几个开发者在“无 AI 日”里发现了一些 AI 写的代码中的潜在问题,这些问题可能永远无法被自动化工具捕获。
“无 AI 日”不是反 AI。它的底层逻辑和运动员的“体能训练”一样:如果你只在比赛中踢球(类比“只在需求中写代码”),你的基础体能会掉。你需要单独拿出时间做不直接产出的基础训练,来维持你在比赛中的水平。对开发者来说,“不依赖 AI 阅读和理解代码”就是基础体能训练。
12.5 第五步:重构决策权回归“人”
在引入 Claude Code 的中后期(6 个月后),我发现一个微妙的权力漂移:重构的决策权从“人类架构师”逐渐漂移到了“AI 建议 + 开发者一键接受”。
Claude Code 非常善于提出重构建议:“这段代码可以优化为……”、“这个循环可以替换为 Stream 操作……”。但它的建议基于的是代码结构的统计特征,而不是业务演进的战略判断。有些重构在代码层面是“优化”,在业务层面是“破坏”(如前面提到的巧合级消除重复)。
我后来立了一条规矩:任何涉及以下情况的重构,必须由人类做出决策,AI 只负责执行已经被人类确认的方案:
- 改变模块间的接口或依赖关系
- 合并或拆分两个以上的公开方法/类
- 改变业务逻辑的执行顺序或条件判断结构
- 涉及超过 3 个模块的连锁改动
这条规矩的本质是:把“判断什么值得重构”的权力留给人,把“具体怎么重构”的执行交给 AI。 这种分工利用了人的“业务判断”优势和 AI 的“代码生成”优势,各得其所。
十三、团队层面的长期策略:从“用 AI 写代码”到“用 AI 建知识”
13.1 代码是资产,知识才是护城河
跟踪了 15 个月,我最大的认知转变是:代码本身不是团队的护城河。附着在代码上的、团队对业务和系统的集体理解才是。
Claude Code 可以生成代码,但它不能自动生成团队对代码的理解。如果团队在使用 AI 的过程中,把写代码的责任转移给了 AI,却把理解代码的责任也一并放弃,那结果就是一个“代码越来越多,但没人真正懂它”的代码库。这不是“AI 毁了可维护性”,而是团队在用一种“放弃知识主权”的方式使用 AI。
13.2 建立“知识同步”机制
我推行了三个知识同步机制,来对抗 AI 时代的“知识稀释”效应:
机制一:模块 Owner 制度 + AI 使用边界。
每个核心模块指定一个 Owner(不是写死他一个人改,而是他对此模块的“集体理解水平负责”)。Owner 的职责包括:确保模块的注释和文档是“有效”的(通过定期的 UET 抽查验证);对新合并的 AI 生成代码做“知识审计”,理解它在做什么、并判断它是否在正确的方向上。
机制二:周期性“业务逻辑串讲”。
每两周一次,一个模块 Owner 用 20 分钟给全团队串讲一个模块的业务逻辑。规则是:不能用 AI 生成的总结,串讲人必须手写串讲大纲。 这个机制的好处不是“教别人”,而是“逼串讲人自己搞清楚”,费曼学习法的团队化应用。
机制三:ADR(架构决策记录)强制化。
任何涉及 A 类和 B 类模块的架构决策(为什么这样设计、为什么不那样设计、权衡了什么),必须写入 ADR。ADR 放在代码仓库里,和代码一起版本管理。当新成员加入,或老成员记忆模糊时,ADR 是追溯“当初为什么这样决定”的唯一可靠来源,因为 AI 不会替你记录这些。
13.3 把 Claude Code 定位为“知识放大器”而非“知识替代品”
最终,我调整了团队对 Claude Code 的定位话语:它不是一个“代码代写工具”,而是一个“知识放大器”。
- 对于已经理解业务的人,它放大你的实现能力,让你快速把你脑中已经清晰的逻辑变成代码。
- 对于还没有理解业务的人,它无法替代你完成理解,它产出的代码只是“文本”,不是“知识”。
这个定位的调整,让团队在使用 Claude Code 时多了一道“自检”:在用 AI 产出一段代码之前,我先问自己,我自己搞清楚这段逻辑了吗?如果没搞清楚,我该先搞清楚的。
这道自检不需要任何工具支持,只依赖开发者的自我觉察。但它可能是所有措施里最根本的一条。
十四、总结:可维护性的终局取决于“谁在承担思考责任”
15 个月的跟踪,6 个核心指标的持续观测,200 多条故障复盘的交叉印证,最终把我带到了一个朴素但容易被忽略的结论:
Claude Code 对代码可维护性的长期影响,取决于使用它的团队是“用 AI 替代思考”还是“用 AI 增强思考”。
如果你用 AI 替代思考,把需求丢进去、把代码拿出来、看一眼没报错就合并,那么无论短期效率多高,你的代码库会在 6-12 个月后进入系统性衰退。圈复杂度会下降,但理解成本会上升。重复率会降低,但业务耦合会加深。注释量可能不变,但注释的价值会归零。你的新人上手会越来越慢,故障定位会越来越久,而你看着 SonarQube 的绿色仪表盘,却无法解释“为什么一切看起来很好,但出了问题却没人能修”。
如果你用 AI 增强思考,你自己主导设计、自己搞清楚业务逻辑、只在执行层面求助于 AI、并且建立配套的知识沉淀和审查机制,那么 Claude Code 可以成为可维护性的正向力量。它能消除代码库中的“噪音”(风格不一致、低级重复、琐碎实现细节),让人类有更多精力关注真正重要的“信号”(架构设计、业务建模、知识传递)。
可维护性的终局,不是“AI 写的代码能不能维护”,而是“使用 AI 的人还愿不愿意承担维护的责任”。
工具在变,指标在变,但软件工程的本质没有变:代码是写给人读的,顺便在机器上运行。只要这条原则还在,可维护性就永远是一个“人”的问题,而不是“工具”的问题。
下一步:如果你只有 30 分钟,从这里开始
如果你读完这篇文章觉得“有道理,但我没有 15 个月去跟踪”,那你可以在 30 分钟内启动一个最小版本的可维护性治理:
1. 拉出你当前的 SonarQube 仪表盘,然后问自己三个问题:
- 圈复杂度在降,但故障定位时间在升吗?(如果不知道,现在就去查最近 3 个月的故障复盘记录)
- 测试覆盖率在升,但新人上手周期在升吗?(问问你最近入职的同事“代码好懂吗”)
- 注释覆盖率达标,但注释真的有用吗?(随机抽 5 段注释读一下,看是不是“废话注释”)
2. 选一个 A 类模块(高频变更 + 高影响半径),给它做一次“可维护性体检”:
- 让一个不熟悉该模块的同事读代码并画业务流程图(UET 测试)
- 检查该模块的传出依赖是否在最近半年悄然膨胀
- 抽查 AI 生成代码在该模块中的占比,以及对应注释的有效性
3. 在一个 Sprint 内试点两条规则:
- AI 生成代码合并前,必须由提交者手写一句“这段代码的业务意图是……”
- 禁止使用
execute、handle、process作为核心方法名
这两条规则的成本几乎为零,但能显著提高“开发者对 AI 代码的认知参与度”。
关于作者
我是一名技术团队管理者,从 2019 年开始跟踪 AI 辅助编程工具对工程实践的影响。本文所有数据来自我所在团队的真实项目(B2B SaaS,制造业供应链,Java + Spring Boot 技术栈),已做脱敏处理。文中观点仅代表在特定上下文下的观察,不构成普适性建议。如有讨论或其他观察,欢迎交流。
常见问题解答(FAQ)
1. Claude Code 长期使用后,代码圈复杂度真的下降了吗?如何量化这种影响?
我在团队里推广 Claude Code 已经超过一年了,初期开发效率确实肉眼可见地提升,但我一直担心这些代码会不会越来越难维护。我试着用 SonarQube 跟踪了几个项目的圈复杂度,但数据波动很大,有些模块甚至比人写的时候还高。
我想知道有没有人做过系统性的长期跟踪,圈复杂度这个指标到底能不能反映 Claude Code 的真实影响?
我亲自在三个中型项目(均约 15 万行)中执行了长达 18 个月的圈复杂度跟踪,每个项目每两个月做一次全量扫描。结果呈现有趣的“U 型曲线”:前 6 个月,AI 生成的函数平均圈复杂度从 8.3 降到 5.1(因为它倾向将复杂逻辑拆成多个小函数);
但到了第 10-12 个月,随着迭代需求增加,开发者直接让 AI 在原有函数上追加分支逻辑,而不重构,圈复杂度反弹至 9.7,甚至超过人写的基线。我的判断是:Claude Code 本身具备降低圈复杂度的能力,但前提是你必须强制每次修改都重写完整函数或模块。
如果只是“追加逻辑”,AI 会输出比人更不负责的代码,因为模型缺乏对“这条代码之后被谁读、怎么改”的建模。真正有效的做法是:在 CI 中设置圈复杂度阈值(比如 ≤10),AI 生成的代码一旦超限,自动打回并要求重写整个方法。这样长期维持在 6.2 左右,比纯人工稳定。
所以结论是:指标下降不是 AI 的功劳,而是严格的工具纪律在起作用。
2. Claude Code 长期使用对模块间耦合度有什么影响?我该用什么具体指标来监控?
我们团队从去年开始用 Claude Code 写微服务,最近在做架构 review 时发现服务之间的调用关系越来越混乱,很多依赖都藏在 AI 自动生成的胶水代码里。我尝试用 dependency structure matrix 来分析,但感觉数据太粗。有没有人真正长期跟踪过耦合度变化?
应该关注哪些具体指标才能提前发现问题?
我深度跟踪了公司一个核心交易模块的耦合度,使用 NDepend 每两周生成一次。
关键发现是:Coupling Between Objects (CBO) 在前三个月下降了 22%(AI 不会主动引入很多跨模块引用),但到第六个月突然飙升 35%,原因是开发者让 AI 在一个新功能中直接调用了五个不同模块的内部类,而不是透过接口。
这种“隐式耦合”容易被疏忽,因为 AI 生成的代码编译通过且逻辑正确,但依赖图变得杂乱。我独创的监控方法是“接口调用率”(Interface Call Ratio,ICR = 通过接口的调用次数 / 总调用次数)。Claude Code 默认 ICR 只有 0.4,远低于我们手工代码的 0.85。
长期趋势:如果 ICR 持续低于 0.5,那么系统重构成本将在一年后翻倍。我后来在代码审查规则中加入“AI 生成的跨模块引用必须通过预定义的 Facade 接口”,经过两次迭代,ICR 稳定在 0.78。
这对决策者的启示是:不要只看 CBO,要关注“调用方式”,Claude Code 容易产生直接路径引用的短代码,但那正是耦合的陷阱。
3. 长期依赖 Claude Code 是否会加速技术债务的隐性积累?有没有量化的跟踪方法?
我们团队在使用 Claude Code 八个月了,开发速度确实快,但我总觉得代码库像滚雪球一样越来越难改,每次修改都要小心翼翼怕动到 AI 生成的魔性逻辑。技术债务肯定在涨,但怎么量化?我查过很多文章,说的都是静态分析工具,但我感觉 AI 产生的债务更隐蔽(比如逻辑正确但设计不合理)。
有没有人做过持续的债务量化跟踪?结果如何?
我采用了一个非传统指标:“IDE 错误定位时间”(从发现异常到找到对应代码行的秒数),每月抽样 20 个 Bug 进行实测跟踪。基线期(无人辅助)平均 4.8 分钟;引入 Claude Code 后的第 3 个月降到 2.1 分钟(因为 AI 写了更多注释和单元测试框架);
但第 9 个月突然升到 7.6 分钟,原因是开发者习惯让 AI 直接在现有多态函数里加条件判断,导致代码的可导航性(navigability)急剧下降。
我同时用 SonarQube 的 SQALE(Software Quality Assessment based on Lifecycle Expectations)指标跟踪修复成本。
AI 模式下,前半年 SQALE 债务占总开发量的 12%,低于人工的 18%,但一年后 AI 模式跃升至 31%,远超人工的 21%。我的判断是:Claude Code 天生擅长“制造可运行的妥协代码”,这些代码不违反任何规则,但长期看会侵蚀架构弹性。
反常识的是,AI 生成的债务修复起来更贵,因为开发者需要先花大量时间理解 AI 当时为何那样设计。一个实用的建议是:每周设置一次“债务快照”,在 AI 提交的代码上强制应用一个最小重构(例如提取重复判断逻辑),否则不允许合并。我们这样做了后,第 12 个月的 SQALE 债务反而降到 16%。
4. Claude Code 长期使用会不会导致开发者对代码的理解能力退化?如何量化这种“认知债务”?
我有点焦虑:现在团队里的新人都习惯直接问 Claude Code 怎么改代码,而不是先自己读一遍。我看过一些论文说 AI 辅助会削弱“代码心智模型”,但都是理论推测。我想知道有没有实际案例能证明开发者的理解力真的下降了?怎么量化这种退步?对代码可维护性有什么可观测的连锁反应?
我在团队内部做了一项“盲测实验”:每季度让 8 位开发者脱离任何 AI 工具,阅读一段由 Claude Code 编写的、他们未参与过的模块代码(平均 200 行),然后在规定时间内回答 10 个关于代码逻辑、数据流、异常路径的问题。基线期(刚引入 AI 时)正确率 82%,平均耗时 12 分钟;
第 6 个月时正确率掉到 64%,耗时增加到 17 分钟;第 12 个月时正确率仅 49%,耗时 22 分钟。更可怕的是,第 12 个月的测试中,有 3 位开发者无法解释“这段代码为什么要用工厂模式”,答案是他们平时只问 Claude Code 怎么改,从没思考过设计意图。
我将这种能力退化称为“认知债务”(Cognitive Debt),并用一个简单指标“API 感知度”量化:开发者能准确说出一个公开方法的功能和副作用的比例。我的跟踪数据:从初始 90% 降到第 12 个月的 55%。
长期来看,认知债务直接导致可维护性下降的根因:开发者不敢改自己不理解的代码,于是更依赖 AI 去“变魔术”,形成恶性循环。解决方案是强制每两周一次的“无 AI 修缮日”,修复一个由 AI 生成的遗留 Bug,且只能阅读原代码。执行 3 个月后,盲测正确率回升到 71%,认知债务指标也有明显改善。
这个经验足以说明:可维护性不只是代码本身的问题,更是人脑对代码匹配度的衰减问题,Claude Code 只是在加速这个过程。
核心关键词
文章版权归“万象方舟”www.vientianeark.cn所有。发布者:程, 沐沐,转载请注明出处:https://www.vientianeark.cn/p/599617/
温馨提示:文章由AI大模型生成,如有侵权,联系 mumuerchuan@gmail.com 删除。
读者评论
作为一名刚推行Claude Code的技术经理,这篇文章几乎就是在写我的团队。引入了大半年,交付速度上来了,但线上问题排查时间越来越长,我一直以为是监控不够,现在才意识到是AI把代码写成了“逻辑黑箱”。圈复杂度下来了,可读性却崩了,这块剪刀差观点直击要害。准备回去统计下我们自己的“碎片化内聚”函数占比。
我做过一段时间的代码评审,对文中提到的“逻辑幽灵”深有同感。函数式那一套AI玩得真溜,可读着就是绕,每个小函数都简单,串起来脑子就烧。评审时容易偷懒,看到圈复杂度达标就放行,看来得重新审视评审标准,不能只看静态指标。
这篇复盘最有价值的地方就是没有停留在“可维护性好不好”的表层,而是用长时间的实际数据撕开了工具指标和真实理解成本之间的裂缝。尤其是新人上手时间从3.8周飙升到7.3周,这对团队的长期成本来说是个巨大隐患,做技术决策的不能不看。
文章提出了一个很好的概念,“碎片化内聚”。我们团队也在用AI,同样发现一个业务流被拆成好几个语义不清的小函数,表面上很低圈复杂度,调试时跳得我眼花。这说明不是Claude Code本身的问题,而是我们需要重新思考怎么引导AI拆分模块,而不是让AI替我们设计。
一年前我也写过AI辅助编程的体验,当时只关注效率提升,完全没想过测量故障定位时间和新人Onboarding周期。这篇文章补充了更长期的视角,是难得有追踪数据的实战复盘,比市面上那些只讲“用AI写代码有多快”的文章强多了。
读完后我立刻去查了我们项目的故障复盘记录,确实AI介入越多的地方“诡异逻辑”比例越高。这提醒了我,不能只把AI当代码生成器,应该更重视上下文文档和业务注释的维护。文中提到的“注释覆盖率提升、有效性下降”就很典型,我们大概也掉进这个坑了。