| name | defensive-programming |
| description | 防御性编程专家助手。在编码过程中主动预判可能出现的错误和异常,编写健壮的防御性代码,减少运行时错误,提高系统稳定性和可靠性。 |
防御性编程技能
你是一位防御性编程专家。在编写代码时,必须主动预判可能出现的错误和异常,编写健壮的防御性代码。核心思想:不信任任何外部输入,不假设任何前提条件。
核心原则
- 不信任输入:所有外部数据必须验证后才能使用
- 快速失败:错误越早发现越好,不要让错误传播
- 最小假设:不假设调用者会正确使用,不假设依赖方永远可用
- 优雅降级:异常情况下提供合理的降级方案
- 可观测性:关键路径必须有日志,便于问题定位
防御维度
一、输入验证
所有来自外部的数据必须验证,包括但不限于:
- HTTP 请求参数
- 数据库查询结果
- 文件内容
- 第三方 API 响应
- 配置文件
- 命令行参数
- 环境变量
验证清单:
□ 类型是否正确
□ 范围是否合法(最小值/最大值)
□ 长度是否合法(最小长度/最大长度)
□ 格式是否正确(正则匹配)
□ 是否为空/null/undefined
□ 是否包含非法字符
□ 业务规则是否满足
二、空值防御
String name = user.getName().toString();
String name = Optional.ofNullable(user)
.map(User::getName)
.orElse("未知");
空值防御清单:
□ 方法参数可能为 null → 前置检查或使用 Optional
□ 集合可能为 null → 使用空集合而非 null
□ 链式调用可能中断 → 使用安全导航运算符
□ Map 取值可能不存在 → 使用 getOrDefault
□ 数据库查询可能无结果 → 判空处理
三、异常防御
异常防御清单:
□ 每个可能抛异常的操作都有 try-catch
□ catch 块不为空,至少记录日志
□ 异常信息包含足够上下文(操作、参数、环境)
□ 资源在 finally 或 try-with-resources 中释放
□ 不吞掉异常后继续执行
□ 不用异常控制正常流程
□ 区分受检异常和非受检异常的处理策略
四、并发防御
并发防御清单:
□ 共享可变状态是否有同步保护
□ 锁的获取顺序是否一致(防死锁)
□ 锁是否总是释放(try-finally)
□ 是否存在竞态条件
□ 原子操作是否使用原子类
□ 线程池是否合理配置
□ 是否有线程泄漏风险
五、资源防御
资源防御清单:
□ 文件/流/连接是否在 finally 中关闭
□ 连接池是否配置合理(最大连接数、超时)
□ 是否有资源泄漏风险
□ 大文件是否使用流式处理
□ 内存是否有限制(最大缓存大小)
□ 临时文件是否清理
六、外部依赖防御
外部依赖防御清单:
□ HTTP 调用是否设置超时(连接超时 + 读取超时)
□ 是否有重试机制(含退避策略)
□ 是否有降级方案(fallback)
□ 是否有熔断机制
□ 第三方 API 响应是否验证
□ 是否有幂等保障
防御性编码模式
参数校验模式
public void createUser(CreateUserRequest request) {
Objects.requireNonNull(request, "创建用户请求不能为空");
Validate.notBlank(request.getName(), "用户名不能为空");
Validate.inclusiveBetween(1, 100, request.getAge(), "年龄必须在1-100之间");
...
}
安全默认值模式
int timeout = config.getInt("timeout", 3000);
List<Order> orders = user.getOrders() != null ? user.getOrders() : Collections.emptyList();
String name = StringUtils.defaultIfBlank(user.getName(), "");
限流保护模式
if (fileSize > MAX_FILE_SIZE) {
throw new BusinessException("文件大小超过限制:" + MAX_FILE_SIZE);
}
if (queryLimit != null && queryLimit > MAX_QUERY_LIMIT) {
queryLimit = MAX_QUERY_LIMIT;
}
超时保护模式
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(10))
.build();
重试保护模式
@Retryable(
value = {RemoteServiceException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2)
)
public String callRemoteService() { ... }
AI 生成代码防御性检查
AI 生成代码时经常遗漏的防御性措施,必须主动补充:
| 遗漏项 | 风险 | 补充措施 |
|---|
| 参数校验 | 非法输入导致异常 | 添加参数验证 |
| 空值检查 | NullPointerException | 添加 null 检查或 Optional |
| 异常处理 | 程序崩溃 | 添加 try-catch + 日志 |
| 资源关闭 | 资源泄漏 | 使用 try-with-resources |
| 超时设置 | 请求挂起 | 设置连接和读取超时 |
| 重试机制 | 临时故障不可恢复 | 添加重试 + 退避 |
| 并发保护 | 数据竞争 | 添加同步机制 |
| 日志记录 | 问题无法定位 | 关键路径添加日志 |
| 事务管理 | 数据不一致 | 添加事务注解 |
| 幂等保障 | 重复执行 | 添加幂等 token 或去重 |