开发中许多线上事故的根源,并非算法错误,而是函数被传入了意料之外的参数,或者状态在并发下跃迁到了未定义的组合。防御性编程的核心就是在代码中显式定义“什么是对的”,让错误在早期被暴露。Claude在逻辑推导和结构化注释上的能力,恰好适合这类需要严谨性的任务。

目前有一些平台免费集成了Claude模型,比如 RskAi(b.rsk.cn),可以直接在网页上使用。

下面通过四个实战场景,演示如何用Claude把模糊的代码边界变成可验证的精确约束。

场景一:为现有函数自动生成完整的契约注释

接手遗留代码时,面对一个无注释的函数,往往需要逐行理解参数含义、返回值可能性和副作用。Claude可以分析函数体,反向生成包含前置条件、后置条件和不变式的契约注释。

操作步骤:

将一个需要梳理的函数代码粘贴进去,例如一个转账方法 transfer(Account from, Account to, BigDecimal amount),内部有余额检查、事务操作和日志记录。

输入以下提示:

请为以下方法生成一份严格的契约注释,包含:

前置条件(参数不可为null、金额必须大于0、账户状态必须为ACTIVE等)

后置条件(转出方余额减少、转入方余额增加、操作被审计日志记录)

可能抛出的异常及触发条件
使用Javadoc格式,并指出哪些条件是应该在调用方保证的,哪些由方法内部检查。

Claude会从代码中提取出 fromto 的非空判断、amount.compareTo(BigDecimal.ZERO) > 0 的校验,生成 @throws IllegalArgumentException if amount is negative or zero 等注释。它会聪明地将“账户必须存在且活跃”归为外部保证的前置条件,而“金额非负”归为方法内校验,帮助团队明确责任边界。

场景二:审查接口缺失的输入校验并补全断言

公开API如果不对调用方传入的数据做充分校验,脏数据会一直渗透到数据库。Claude能扫描控制器或服务层代码,找出未做校验的字段并生成校验逻辑。

操作步骤:

将一个接收JSON请求体的REST接口代码粘贴进去,例如一个用户注册接口,接收 usernamepasswordemailage,当前只有简单的非空判断。

输入以下提示:

审查以下接口的输入校验是否完备,请从以下角度逐一检查:

字符串长度限制(防止超长输入占用内存)

格式校验(邮箱正则、密码强度)

数值范围(age应在0-150之间)

业务唯一性约束(username是否应异步查重)
针对每个缺失项,生成可嵌入的校验代码(使用Java Bean Validation注解或assert语句),并给出统一异常处理的建议。

Claude会指出 password 未限制最小长度,可能接收到空字符串;age 未做范围校验,传入-1也能通过;email 仅做了非空判断,未检查格式。它会补全一组注解,如 @Size(min=8, max=64) @Pattern(regexp="^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).+$"),并在类级别添加 @Validated。对于唯一性这种非注解能覆盖的逻辑,它会建议在Service层用 assert 或抛出自定义 BusinessException

场景三:设计一个具有完整状态校验的状态机

订单、工单等对象的状态流转如果仅靠if-else散落在各处,容易遗忘某些非法跃迁。Claude擅长枚举所有状态和事件,生成无遗漏的状态机实现。

操作步骤:

描述状态流转规则:“订单状态有待支付、已支付、已发货、已完成、已取消。已支付可以变为已发货或已取消,已发货只能变为已完成,已取消和已完成是终态。待支付可以变为已取消。”

输入以下提示:

请根据上述订单状态流转规则,用Java实现一个状态机。要求:

使用枚举定义状态,枚举内部包含每个状态允许的下一状态集合

提供一个 transition(Order order, State target) 方法,内部校验流转合法性

如果不合法,抛出带有明确提示的 IllegalStateTransitionException

在注释中列出所有合法流转,并解释为什么使用状态模式而非硬编码if-else

Claude会生成一个 OrderState 枚举,每个枚举值(如 PAID)的构造参数中传入 EnumSet.of(SHIPPED, CANCELLED)transition 方法用 currentState.canTransitionTo(target) 进行前置校验。注释会说明“将流转规则集中在枚举中,新增状态时只需修改枚举定义,调用方无需变更”,体现防御性编程中“封装变化”的原则。

场景四:将模糊的业务规则转化为精确的断言和异常

业务人员常说“金额不能太高”“时间不能太晚”,这类模糊规则到了代码中必须量化为精确条件。Claude可以将自然语言规则转化为可测试的断言。

操作步骤:

描述模糊规则:“一个促销活动的折扣金额不能超过商品原价的70%,且每人每天最多领取3次。活动仅在2026年1月1日至6月30日有效。”

输入以下提示:

请将以下业务规则转化为Java代码中的防御性校验。要求:

将每条规则拆解为精确的布尔表达式

编写一个 validatePromotionClaim(User user, Product product, LocalDateTime now) 方法,内部用 assert 或显式抛异常

对于可能频繁变化的阈值(如70%、3次),建议抽取为常量或配置项

解释为什么使用 assert 适用于内部不可恢复错误,而面向外部调用时应抛受检异常

Claude会生成一个方法,内部断言 discountRate <= 0.7claimCount < 3now.isBefore(deadline)。它会将70%和3定义为 static final 常量,并解释 assert 默认在生产环境关闭,因此对外接口应使用 IllegalArgumentException 确保校验始终生效。这种转化让模糊的业务约束变得可自动化验证。

常见问题

1. Claude生成的契约注释是否与代码逻辑完全一致?
它会基于代码现有的判断逻辑生成,如果代码本身有未显式化的隐藏假设,可能不会被提取。建议生成后与开发者确认补充。

2. 状态机实现是否适用于复杂的流程引擎场景?
对于简单的订单、工单状态流转完全足够。如果涉及多角色审批、条件分支等,可以考虑引入工作流引擎,Claude会提示适用场景的边界。

3. 校验代码生成的注解能否直接用于Spring Boot?
生成的是标准Bean Validation注解,直接配合 @Valid 即可。如要自定义校验逻辑,Claude也会给出相应的自定义注解实现。

4. 模糊规则转化后,业务方不认可阈值怎么办?
这正是防御性编程的附带价值:将隐式阈值显式化后,业务方可以明确确认。你可以让Claude直接输出一份“业务规则确认表”供签字。

5. 这些契约和断言是否会增加运行时性能开销?
参数校验和状态检查的开销极小,且能避免更大代价的脏数据修复。如果确实存在性能热点,Claude会建议将校验放在测试代码中,生产环境仅在关键入口保留。

总结

将Claude用在防御性编程中,等于为代码增加了自动化的契约梳理、校验补全、状态机设计和规则量化能力。它不会替代开发者对业务的理解,但能系统性地减少因“没想到会传null”“忘判断这个状态”而引发的线上事故。当边界条件被明确写在代码里,代码的健壮性和团队的安全感都会同步增长。

【本文完】

更多推荐