基本工作流上手之后,真正的考验来了:大型重构不是一两个小时能搞定的,跨越几周的任务怎么维持节奏?核心模块没有测试怎么重构才安全?性能问题、安全漏洞、架构债务同时存在,优先级怎么排?
这篇聊一些在生产环境里真正验证过的进阶方法。
一、上下文窗口管理:长期重构任务的秘诀
Claude Code 的上下文窗口是有限的。对于周期较长的大型重构项目,你需要主动管理对话上下文,否则越往后 AI 对项目的"记忆"越模糊,给出的方案质量会明显下降。
1.1 创建"重构日志"文件
在项目根目录创建一个 REFACTORING_LOG.md,每次会话结束时更新它:
markdown
# 重构进度日志
## 总体目标
将 ecommerce-backend 从单体架构重构为模块化单体(Modular Monolith),
为后续微服务化做准备。
## 已完成 ✅
- 2025-08-01:OrderService 拆分完成(4个子服务 + 门面类)
- 2025-08-02:统一异常处理机制(GlobalExceptionHandler + 自定义异常体系)
- 2025-08-07:OrderQueryService 添加单元测试(覆盖率 87%)
## 进行中 🔄
- ProductService 重构(计划按 产品管理/库存管理/价格管理 拆分)
- ✅ 第1步:新建骨架类
- ✅ 第2步:迁移 ProductQueryService
- 🔄 第3步:迁移 ProductInventoryService(发现循环依赖,方案待定)
- ⬜ 第4步:迁移 ProductPricingService
## 已知问题 ⚠️
- InventoryService 和 OrderCreationService 循环依赖(待用领域事件解决)
- UserService 中有 5 处直接 SQL 查询(@Query 注解+原生 SQL),重构风险较高
## 不要动的地方 🚫
- payment/ 模块(第三方支付接口集成,需要支付团队参与)
- legacy/ 目录(历史遗留代码,老板说先不管)
- 所有 */migration/*.sql 文件(数据库已迁移,不要修改)
新会话开始时:
objectivec
请先读取 REFACTORING_LOG.md 和 CLAUDE.md,了解当前重构进度,
然后我们继续处理 ProductInventoryService 的循环依赖问题。
1.2 压缩上下文:摘要式延续
当一个会话即将到达上下文限制时:
arduino
在我们结束这个会话之前,请生成一份简洁的"下次会话接力摘要",
包括:我们做了什么、当前状态、下一步计划,以及任何需要注意的事项。
我会把这份摘要作为下次对话的开头。
二、测试驱动重构(Test-First Refactoring)
最安全的重构顺序是:先写测试,再动代码。Claude Code 非常擅长这种方式。
2.1 为遗留代码生成特征测试
"特征测试"(Characterization Test)的目的不是测试正确性,而是记录现有行为,防止重构破坏它:
markdown
OrderService.calculateFinalPrice() 方法逻辑很复杂,我要重构它。
在重构之前,请帮我:
1. 阅读该方法的完整代码
2. 分析它处理的所有边界情况(折扣券、VIP折扣、满减、限时特价...)
3. 为每种情况生成一个测试用例,测试的目的是"记录当前行为",
不是验证业务逻辑正确性
4. 如果某些分支依赖数据库,使用 @MockBean 或测试数据
生成的测试类命名为 OrderPriceCalculationCharacterizationTest
这样,即使原有逻辑有 bug,重构后也能保证 "bug 和之前一样",而不是引入新 bug。
2.2 并行测试策略
重构高风险的核心服务时,可以让新旧实现并行运行:
markdown
在重构 OrderCreationService 期间,请实现一个"影子测试"机制:
1. 保留原有的 OrderService.createOrder() 不变
2. 新的 OrderCreationService.createOrder() 在旁边运行
3. 在一个 OrderCreationShadowComparator 组件中:
- 同时调用两个实现
- 比较结果是否一致
- 如果不一致,记录到日志(不影响正常流程,以旧实现的结果为准)
4. 添加一个 Feature Flag:shadow.mode.enabled=true/false
这样我们可以在生产环境中验证新实现的正确性,零风险。
2.3 契约测试:保护 API 稳定性
当重构可能影响 REST API 响应格式时:
markdown
我们需要确保重构后 /api/orders 接口的响应格式完全不变。
请:
1. 读取 OrderController 中所有 GET/POST/PUT/DELETE 端点
2. 为每个端点生成一个 Spring MVC Test 的集成测试
3. 测试中断言:HTTP 状态码、响应 JSON 的关键字段(不要断言全部字段,只断言调用方依赖的字段)
4. 这些测试放在 OrderApiContractTest.java 中
5. 在 CI 管道中,这些测试应该在每次重构提交后自动运行
三、性能重构:识别和解决 Spring 应用的性能问题
3.1 让 Claude Code 扫描 N+1 问题
ORM 框架最常见的性能陷阱是 N+1 查询:
sql
请扫描所有 Service 类,找出可能的 N+1 查询问题。
特征:
- 在循环内部调用 Repository 方法
- 使用 @OneToMany/@ManyToMany 但没有配置 EAGER 加载或 JOIN FETCH
- 在列表查询结果上逐个调用懒加载属性
找到后,给出修复建议(JOIN FETCH / @BatchSize / DTO Projection)
典型发现示例:
sql
发现3处 N+1 问题:
1. OrderService.listOrdersWithProducts()(第 234-248行)
在循环中对每个 Order 调用 order.getProducts()(触发懒加载)
修复:将查询改为 JPQL JOIN FETCH:
SELECT o FROM Order o LEFT JOIN FETCH o.products WHERE o.userId = :userId
2. ProductService.listProductsWithInventory()(第 178行)
使用了 @OneToOne(fetch = LAZY) 的 Inventory 关联
在列表页面场景,建议改为 DTO Projection,只查询需要的字段
3. UserService.listUsersWithRoles()(第 89行)
@ManyToMany(fetch = LAZY) 的 roles 关联在循环中被访问
修复:添加 @BatchSize(size = 20) 或改用 JOIN FETCH
3.2 缓存策略重构
css
当前项目的缓存使用不规范,存在:手写 Redis 操作代码、缓存 key 命名混乱、
没有统一的过期时间策略。
请帮我:
1. 找出所有直接使用 RedisTemplate 的地方(可能分散在多个 Service 中)
2. 分析哪些数据适合用 Spring Cache 注解替代手写缓存
3. 对适合的地方,重构为 @Cacheable/@CachePut/@CacheEvict
4. 设计一个统一的缓存 key 命名规范(格式:{模块}:{数据类型}:{唯一标识})
5. 在 application.yml 中统一配置各缓存的 TTL
注意:支付相关数据不缓存,用户权限缓存最长 5 分钟(安全要求)
四、架构模式重构:引入 DDD 思想
4.1 识别领域边界
diff
请分析 src/main/java/com/example 下的所有代码,
帮我识别潜在的"有界上下文"(Bounded Context)边界。
评估标准:
- 哪些类和方法在概念上是强相关的
- 哪些是弱耦合的跨模块调用
- 哪些地方用了相同名词但含义不同(比如 User 在订单模块和用户模块可能是不同概念)
用 Mermaid 格式输出一个上下文映射图。
4.2 引入领域事件替代直接调用
在遗留项目中,模块间经常直接相互调用,导致强耦合:
java
// 重构前:强耦合
@Service
public class OrderService {
@Autowired
private InventoryService inventoryService;
@Autowired
private NotificationService notificationService;
@Autowired
private PointsService pointsService;
public Order createOrder(CreateOrderRequest req) {
Order order = saveOrder(req);
inventoryService.deductStock(req.getItems()); // 强耦合
notificationService.sendOrderConfirmation(order); // 强耦合
pointsService.addPoints(order.getUserId(), order.getAmount()); // 强耦合
return order;
}
}
指令:
scss
OrderService.createOrder() 在保存订单后,调用了3个外部服务。
请用 Spring 的 ApplicationEventPublisher 重构这个方法,
实现:
1. 定义 OrderCreatedEvent 领域事件类(包含 orderId、userId、amount、items)
2. createOrder() 只发布事件,不直接调用其他服务
3. InventoryService、NotificationService、PointsService 各自实现
@EventListener 监听 OrderCreatedEvent
4. 库存扣减需要在同一事务内完成(@TransactionalEventListener(phase = BEFORE_COMMIT))
5. 发送通知和积分可以异步执行(@Async + @EventListener)
6. 添加错误处理:库存不足时需要回滚整个事务
4.3 聚合根设计重构
scss
当前 Order 实体的状态变更分散在多个 Service 方法中:
- OrderService.pay() 直接调用 order.setStatus("PAID")
- OrderService.ship() 直接调用 order.setStatus("SHIPPED")
- 没有状态流转的合法性校验(比如已取消的订单不能再支付)
请重构 Order 实体,将状态流转逻辑封装在聚合根内:
1. 将 status 字段改为私有,移除 setter
2. 在 Order 类中添加领域方法:pay(), ship(), complete(), cancel()
3. 每个方法内部校验当前状态是否允许该操作
4. 非法状态转换时抛出 InvalidOrderStateException
5. Service 层改为调用 order.pay() 而不是 order.setStatus("PAID")
五、代码质量重构:消除技术债务
5.1 系统性消除重复代码
markdown
请扫描整个项目,找出以下类型的重复代码:
1. 相似度高的 Converter/Transformer 类(Entity ↔ DTO 转换)
2. 多个 Controller 中重复的参数校验逻辑
3. 多个地方重复实现的分页查询包装代码
找到后,提出提取公共抽象的方案,并评估重构成本(改动文件数量)
5.2 统一异常处理
很多遗留项目的异常处理极不规范:
markdown
请分析项目中所有的异常处理方式,找出:
1. 被 catch 住但只打印日志的异常(信息被吞掉了)
2. 直接向上层抛出 checked exception 导致方法签名被污染的情况
3. 没有区分"业务异常"和"系统异常"的地方(应该用不同 HTTP 状态码)
4. Controller 层重复的 try-catch(应该由 @ControllerAdvice 统一处理)
然后帮我设计一个统一的异常体系:
- BusinessException(业务异常,HTTP 400)
- OrderNotFoundException(extends BusinessException)
- InsufficientInventoryException
- InvalidOrderStateException
- SystemException(系统异常,HTTP 500)
- ValidationException(参数校验异常,HTTP 422)
并实现 GlobalExceptionHandler 统一处理。
六、安全重构:发现和修复安全漏洞
6.1 SQL 注入扫描
markdown
请扫描所有 Repository 类和 Mapper.xml 文件,找出:
1. 使用字符串拼接构造 SQL 的地方(而非参数化查询)
2. MyBatis 中使用 ${} 而非 #{} 的地方(${}不会做参数化处理)
3. @Query 注解中的原生 SQL 是否有安全风险
找到后,给出修复方案。
6.2 敏感信息泄露检查
markdown
请帮我检查以下安全问题:
1. API 响应中是否有可能泄露敏感字段(密码 hash、手机号完整显示、身份证号等)
特别检查 User 实体是否有 @JsonIgnore 保护敏感字段
2. 日志中是否有可能打印敏感信息(搜索 log.info/log.debug 附近的变量)
3. application.yml 中是否有明文密码或密钥
4. 是否有接口缺少权限校验(@PreAuthorize 或 SecurityConfig 中的规则)
七、重构完成度评估:让 Claude Code 给项目打分
整个重构完成后,可以让 Claude Code 做一次综合评估:
markdown
重构工作已完成,请对项目进行全面的代码质量评估,
从以下维度打分(1-10分)并给出具体改进建议:
1. 分层架构清晰度(Controller/Service/Repository 职责是否明确)
2. 单一职责原则遵守程度(最大的类有多少行?有多少职责?)
3. 测试覆盖质量(核心业务逻辑的测试覆盖率)
4. 异常处理规范性(是否有统一的异常体系)
5. 配置管理规范性(是否有硬编码,配置是否集中)
6. 性能风险(是否有明显的 N+1 或大查询)
7. 安全性(是否有明显的安全漏洞)
生成一份可以发给团队的技术报告。
这篇文章里的方法,并不需要全部用上。真正的价值在于按需取用:重构周期长,就重视上下文管理;核心模块要动,就先补测试;看到性能告警,就跑一遍 N+1 扫描。
Claude Code 的上限其实取决于你给它的上下文质量。你把项目背景、约束、目标说得越清楚,它做出来的东西就越接近你想要的。这是一个需要磨合的过程,但一旦跑顺了,它能替你处理掉大量机械性的重构工作,让你专注在真正需要判断力的地方。