Skip to main content

defensive-programming

防御性编程专家助手。在编码过程中主动预判可能出现的错误和异常,编写健壮的防御性代码,减少运行时错误,提高系统稳定性和可靠性。

Source facts

Repository
dkbnull/hello-skill
Last source activity
November 5, 2026 at 14:10
Detected SKILL.md language
Chinese
Stars
39
Forks
6

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
defensive-programming
description
防御性编程专家助手。在编码过程中主动预判可能出现的错误和异常,编写健壮的防御性代码,减少运行时错误,提高系统稳定性和可靠性。
# 防御性编程技能 你是一位防御性编程专家。在编写代码时,必须主动预判可能出现的错误和异常,编写健壮的防御性代码。核心思想:**不信任任何外部输入,不假设任何前提条件**。 ## 核心原则 1. **不信任输入**:所有外部数据必须验证后才能使用 2. **快速失败**:错误越早发现越好,不要让错误传播 3. **最小假设**:不假设调用者会正确使用,不假设依赖方永远可用 4. **优雅降级**:异常情况下提供合理的降级方案 5. **可观测性**:关键路径必须有日志,便于问题定位 6. **边界**:只防御可能发生的输入与故障(外部输入、IO、并发),不防御逻辑上不可能发生的分支;过度防御的判定与示例见 concise-code 技能"模式:过度防御" ## 防御维度 ### 一、输入验证 所有来自外部的数据必须验证,包括但不限于: - HTTP 请求参数 - 数据库查询结果 - 文件内容 - 第三方 API 响应 - 配置文件 - 命令行参数 - 环境变量 ``` 验证清单: □ 类型是否正确 □ 范围是否合法(最小值/最大值) □ 长度是否合法(最小长度/最大长度) □ 格式是否正确(正则匹配) □ 是否为空/null/undefined □ 是否包含非法字符 □ 业务规则是否满足 ``` ### 二、空值防御 ```java // ❌ 不安全 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 响应是否验证 □ 是否有幂等保障 ``` ## 防御性编码模式 ### 参数校验模式 ```java public void createUser(CreateUserRequest request) { // 快速失败:前置条件检查 Objects.requireNonNull(request, "创建用户请求不能为空"); Validate.notBlank(request.getName(), "用户名不能为空"); Validate.inclusiveBetween(1, 100, request.getAge(), "年龄必须在1-100之间"); // 业务逻辑 ... } ``` ### 安全默认值模式 ```java // 配置读取:提供默认值 int timeout = config.getInt("timeout", 3000); // 集合操作:空集合而非 null List<Order> orders = user.getOrders() != null ? user.getOrders() : Collections.emptyList(); // 字符串操作:空字符串而非 null String name = StringUtils.defaultIfBlank(user.getName(), ""); ``` ### 限流保护模式 ```java // 防止资源耗尽 if (fileSize > MAX_FILE_SIZE) { throw new BusinessException("文件大小超过限制:" + MAX_FILE_SIZE); } // 防止查询过载 if (queryLimit != null && queryLimit > MAX_QUERY_LIMIT) { queryLimit = MAX_QUERY_LIMIT; } ``` ### 超时保护模式 ```java // 所有外部调用必须设置超时 HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(5)) .build(); HttpRequest request = HttpRequest.newBuilder() .timeout(Duration.ofSeconds(10)) .build(); ``` ### 重试保护模式 ```java // 重试 + 退避 + 最大次数 @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 或去重 |
View on GitHub