first commit
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
---
|
||||
name: java-coding-style
|
||||
description: 面向 Vibe Coding Agent 的 Java 编写、修改、重构、审查与验证规范,以《阿里巴巴 Java 开发手册》为质量基线并适配现代 JDK 与项目既有约定。凡任务涉及 Java、Spring、Jakarta、Quarkus、MyBatis、JPA、Maven、Gradle、单元测试、并发、异常日志、数据库访问或 Java 代码 Review 时使用。
|
||||
---
|
||||
|
||||
# Java 代码风格
|
||||
|
||||
将本 Skill 作为 Java 任务的语言级质量规范;将项目的任务治理 Skill 作为流程级规范。两者同时触发时,先执行任务分级与门禁,再在实现、Review 和验证阶段执行本 Skill。
|
||||
|
||||
## 规则优先级
|
||||
|
||||
按以下顺序解决冲突:
|
||||
|
||||
```text
|
||||
平台安全规则与用户本次明确要求
|
||||
→ 已确认的需求、接口和验收标准
|
||||
→ 作用域最近的 AGENTS.md、项目规范、构建配置与 formatter
|
||||
→ 相邻代码中稳定且合理的架构惯例
|
||||
→ 本 Skill 的必须项
|
||||
→ 本 Skill 的推荐项
|
||||
```
|
||||
|
||||
不得以“遵循阿里规范”为由破坏兼容性、绕过项目门禁或批量改写无关代码。发现项目惯例存在明显缺陷、安全问题或与必须项冲突时,说明证据、影响和建议,不得静默复制缺陷。
|
||||
|
||||
## 规则等级
|
||||
|
||||
- **必须**:默认不可违反。仅在更高优先级规则明确要求时例外,并记录原因。
|
||||
- **推荐**:无冲突时采用;不采用时应有可说明的工程理由。
|
||||
- **参考**:根据 JDK、框架、性能数据和业务上下文选择。
|
||||
|
||||
规则等级用于约束 Agent,不代表已配置静态检查。只有实际运行的检查才能报告为通过。
|
||||
|
||||
## 开始实现前
|
||||
|
||||
1. 查找并读取作用域内的 `AGENTS.md`、README、构建文件、formatter、Checkstyle、PMD、SpotBugs、Error Prone 和测试配置。
|
||||
2. 确认 Java/JDK 版本、框架版本、模块边界、包结构、依赖管理方式及相邻实现惯例。
|
||||
3. 从用户需求或已确认文档提取可观察行为、边界条件、异常语义、兼容性约束和验收证据。
|
||||
4. 检查工作区已有改动,避免覆盖、格式化或修复任务范围外的代码。
|
||||
5. 按任务内容加载本 Skill 的参考文件:
|
||||
- 命名、格式、常量、注释:读取 [references/01-命名格式与注释.md](references/01-命名格式与注释.md)。
|
||||
- 类型、OOP、API、空值:读取 [references/02-类型OOP与API设计.md](references/02-类型OOP与API设计.md)。
|
||||
- 集合、并发、日期时间:读取 [references/03-集合并发与时间.md](references/03-集合并发与时间.md)。
|
||||
- 异常、日志、安全:读取 [references/04-异常日志与安全.md](references/04-异常日志与安全.md)。
|
||||
- 分层、持久化、依赖:读取 [references/05-工程分层与数据访问.md](references/05-工程分层与数据访问.md)。
|
||||
- 测试、Review、验证:实现和审查阶段读取 [references/06-测试审查与验证.md](references/06-测试审查与验证.md)。
|
||||
|
||||
只加载与任务相关的规则;进行完整 Java Review 时加载全部参考文件。
|
||||
|
||||
## 编写代码
|
||||
|
||||
遵循以下顺序:
|
||||
|
||||
```text
|
||||
确认行为与边界
|
||||
→ 找到最小改动点
|
||||
→ 先写或调整能失败的测试
|
||||
→ 实现最小充分代码
|
||||
→ 清理命名、结构和重复
|
||||
→ 执行静态审查
|
||||
→ 运行相关验证
|
||||
```
|
||||
|
||||
必须:
|
||||
|
||||
- 保持单一职责和清晰依赖方向,不为了“更优雅”引入无需求支撑的抽象、框架或设计模式。
|
||||
- 优先复用项目内已验证的组件;新增公共工具前确认没有等价实现。
|
||||
- 把校验放在信任边界,把业务不变量放在领域或服务边界;不要依赖控制器校验保护所有调用路径。
|
||||
- 维持 API、序列化、数据库和异常契约兼容;任何破坏性变化都必须显式列出并获得相应确认。
|
||||
- 仅修改任务需要的代码。不要顺手全局格式化、升级依赖或清理无关告警。
|
||||
- 对非显然的业务决策写“为什么”的注释;不要用注释复述代码。
|
||||
- 不生成凭据、真实个人信息、生产数据或可被误用的安全绕过代码。
|
||||
|
||||
## Java 专项审查
|
||||
|
||||
实现后逐项检查:
|
||||
|
||||
1. 正确性:空值、边界、溢出、精度、时区、编码、异常路径和资源释放。
|
||||
2. 契约:参数、返回值、异常、幂等性、事务、序列化和向后兼容。
|
||||
3. 并发:共享可变状态、原子性、可见性、锁范围、线程池和 `ThreadLocal` 清理。
|
||||
4. 数据:参数绑定、查询规模、索引假设、批量操作、事务边界和 N+1 查询。
|
||||
5. 安全:认证与授权、对象级权限、注入、反序列化、路径/URL、敏感信息和重放。
|
||||
6. 可维护性:命名、职责、重复、嵌套、隐藏副作用和测试可读性。
|
||||
|
||||
发现问题时按严重性报告:`阻断`、`严重`、`一般`、`建议`。给出文件、位置、触发条件、影响和最小修复建议;不得只报风格偏好。
|
||||
|
||||
## 验证
|
||||
|
||||
优先使用项目已有命令和 CI 等价检查。按改动范围选择:
|
||||
|
||||
- 运行目标单元测试,再运行受影响模块测试。
|
||||
- 运行编译、格式、静态分析和集成测试中与风险相称的部分。
|
||||
- 项目已配置 Alibaba P3C/PMD 时运行其既有任务;未配置时不要擅自安装插件或新增构建依赖。
|
||||
- 对并发、事务、时区、序列化或安全变更补充针对性验证,不能只依赖 happy path。
|
||||
|
||||
报告每个实际命令、结果和未执行项。不得把“代码看起来正确”写成测试通过,不得用全量构建失败掩盖目标测试结果。
|
||||
|
||||
## 交付格式
|
||||
|
||||
最终说明至少包含:
|
||||
|
||||
- 完成的行为与主要代码位置;
|
||||
- 与需求直接相关的设计决定;
|
||||
- 实际执行的测试和静态检查;
|
||||
- 未验证内容、遗留风险和明确例外。
|
||||
|
||||
若仅做 Review,不修改代码;若用户要求实现,则完成实现、Review 和验证后再交付。
|
||||
|
||||
## 规范来源与适配
|
||||
|
||||
本 Skill 以阿里巴巴公开的 Java 开发规约及 P3C 工具规则为基线,并将其改写为 Agent 可执行指令:
|
||||
|
||||
- [Alibaba Java Coding Guidelines](https://alibaba.github.io/Alibaba-Java-Coding-Guidelines/)
|
||||
- [阿里巴巴 Java 开发手册中文目录](https://alibaba.github.io/p3c/)
|
||||
- [Alibaba P3C](https://github.com/alibaba/p3c)
|
||||
|
||||
阿里规约按“强制、推荐、参考”分级;本 Skill 对应为“必须、推荐、参考”。历史性规则不得脱离项目 JDK、框架、序列化协议和工具链机械套用。
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "Java 代码风格"
|
||||
short_description: "以阿里巴巴规约为基线编写、审查与验证现代 Java 代码"
|
||||
default_prompt: "Use $java-coding-style to implement and review this Java change according to the project rules and Alibaba Java Coding Guidelines."
|
||||
@@ -0,0 +1,62 @@
|
||||
# 命名、格式与注释
|
||||
|
||||
## 命名
|
||||
|
||||
- **必须**:类、接口和枚举使用 `UpperCamelCase`;方法、参数、字段和局部变量使用 `lowerCamelCase`;常量使用语义完整的 `UPPER_SNAKE_CASE`。
|
||||
- **必须**:包名全小写,以稳定的组织与业务域命名;遵循项目现有单复数约定。
|
||||
- **必须**:命名不得以 `_` 或 `$` 开头、结尾,不得使用中文、纯拼音或中英拼音混写。国际通用专名除外。
|
||||
- **必须**:抽象基类使用 `Abstract` 或项目约定前缀;异常以 `Exception` 结尾;测试类遵循项目测试框架的现有命名。
|
||||
- **必须**:避免无意义缩写、单字母业务变量和误导性名称。循环索引等极小作用域变量可以使用惯用短名。
|
||||
- **必须**:Bean/序列化对象的布尔属性命名必须验证框架映射;默认不以 `is` 命名字段,访问器可按 JavaBeans 约定使用 `isXxx()`。
|
||||
- **推荐**:DO、DTO、BO、VO、PO 等后缀只在项目已经定义其语义时使用,不自行发明相邻概念。
|
||||
- **推荐**:实现设计模式时让类名表达职责,如 `OrderFactory`;不要仅为套用模式而改名。
|
||||
|
||||
## 常量与字面量
|
||||
|
||||
- **必须**:禁止散落的业务魔法值;提取为有领域含义的常量、枚举或值对象。
|
||||
- **必须**:`long` 字面量使用大写 `L`。
|
||||
- **必须**:不得用一个“万能常量类”承载所有模块常量;按模块和职责控制可见性。
|
||||
- **推荐**:仅在真正固定且跨实例共享时声明 `static final`;不要把可变集合伪装成常量。
|
||||
- **推荐**:状态和类型码优先使用有行为约束的枚举或值对象,同时保持对外协议兼容。
|
||||
|
||||
## 格式
|
||||
|
||||
- **必须**:服从项目 formatter、Checkstyle 或编辑器配置;不得因本文件偏好覆盖自动化格式规则。
|
||||
- **必须**:控制语句始终使用大括号;关键字与左括号间保留空格;运算符两侧保留空格。
|
||||
- **必须**:默认使用 4 空格缩进且不使用 Tab;项目 formatter 另有规定时从项目。
|
||||
- **推荐**:单行不超过 120 字符;import 和自动生成代码按工具配置处理。
|
||||
- **推荐**:新增方法原则上不超过 80 行,新增类原则上不超过 500 行。生成代码、声明型配置或框架限制可例外,但应说明原因。
|
||||
- **推荐**:方法保持聚焦,避免超过三层嵌套;优先使用卫语句、提取方法或清晰的布尔变量。
|
||||
- **必须**:避免魔法值、重复代码、过深嵌套和无业务价值的抽象。
|
||||
- **必须**:不要提交仅由全局换行、import 重排或格式化导致的无关 diff。
|
||||
|
||||
## 导入
|
||||
|
||||
- **必须**:禁止通配符导入。
|
||||
- **推荐**:按静态导入、Java/Jakarta 标准库、第三方库、项目内部包分组,组间空一行。
|
||||
- **推荐**:同组内按字典序排列;若项目格式化器定义了不同顺序,以格式化器为准。
|
||||
- **必须**:删除未使用导入,不通过全限定类名规避正常导入。
|
||||
|
||||
## 注释与 Javadoc
|
||||
|
||||
- **必须**:公共 API、接口抽象方法和不显然的契约说明使用 Javadoc,包含参数约束、返回语义和可观察异常。
|
||||
- **必须**:修改逻辑时同步更新相关注释;陈旧注释视为缺陷。
|
||||
- **必须**:注释说明意图、业务原因、约束或权衡,不复述语句表面含义。
|
||||
- **必须**:枚举字段或代码值必须能看出业务含义,可通过 Javadoc、构造参数或明确命名表达。
|
||||
- **推荐**:TODO/FIXME 包含可追踪的任务标识和原因;若无跟踪机制则完成或删除。
|
||||
- **必须**:不要保留大段注释掉的代码,版本历史可承担恢复职责。
|
||||
- **必须**:所有新增类必须有 Javadoc,首句说明职责而非复述类名。
|
||||
- **必须**:类 Javadoc 使用作者 `xiang`,通过 `@since` 记录实际首次创建日期,日期格式固定为 `yyyy-MM-dd`;后续修改不得覆盖首次创建日期。
|
||||
- **推荐**:对复杂业务逻辑解释“为什么”和特殊规则,不逐行翻译代码;业务分支意图不明显时补充说明。
|
||||
- **必须**:禁止保留 `yourname`、`TODO author` 等占位内容。
|
||||
|
||||
Javadoc 采用以下格式;`yyyy-MM-dd` 必须替换为实际首次创建日期,不得原样保留:
|
||||
|
||||
```java
|
||||
/**
|
||||
* 类的职责说明
|
||||
*
|
||||
* @author xiang
|
||||
* @since yyyy-MM-dd
|
||||
*/
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
# 类型、OOP 与 API 设计
|
||||
|
||||
## 类型与相等性
|
||||
|
||||
- **必须**:包装类型使用 `equals` 或 `Objects.equals` 比较值,不使用 `==`;警惕缓存范围造成的偶然相等。
|
||||
- **必须**:`BigDecimal` 使用字符串或精确来源构造;数值大小用 `compareTo`,需要比较值与 scale 时才用 `equals`。
|
||||
- **必须**:货币、比例和计量值明确精度、舍入方式与单位;禁止用 `double` 承载精确金额。
|
||||
- **必须**:重写 `equals` 时同时重写 `hashCode`,并验证对称性、传递性和集合行为。
|
||||
- **推荐**:用领域类型、枚举和受约束构造器替代多个语义不明的 `String`、`int` 参数。
|
||||
- **必须**:类型转换前检查范围和语义;不得以强制转换静默截断数值。
|
||||
|
||||
## 空值与返回值
|
||||
|
||||
- **必须**:明确参数与返回值的 nullability;不得依靠调用方猜测。
|
||||
- **推荐**:返回空集合或空数组而非 `null`;不要为避免判断而创建语义虚假的空领域对象。
|
||||
- **推荐**:`Optional` 主要用于可能缺失的返回值;不要默认用于实体字段、DTO 字段、方法参数或集合元素。
|
||||
- **必须**:禁止无条件链式解引用可能为空的对象;在边界校验或使用清晰分支表达缺失语义。
|
||||
- **必须**:不要用断言校验外部输入,因为生产环境可能禁用断言。
|
||||
- **推荐**:在系统边界尽早校验参数;项目支持 Bean Validation 时优先使用 `@Valid`、`@NotNull`、`@NotBlank`、`@Size` 等声明式校验。
|
||||
- **推荐**:内部前置条件优先复用项目已有校验工具;只有需要定制业务错误码或分支处理时才手写空值判断。
|
||||
- **必须**:不得仅为判空新增依赖。
|
||||
- **推荐**:项目没有现成判空工具时,对象使用 `obj == null`,集合使用 `collection == null || collection.isEmpty()`,Map 使用 `map == null || map.isEmpty()`;只有项目已经依赖 Apache Commons Collections 时,才使用 `CollectionUtils.isEmpty()` 或 `MapUtils.isEmpty()`。
|
||||
|
||||
## OOP 与封装
|
||||
|
||||
- **必须**:遵循单一职责和最小可见性;字段默认 `private`,只暴露必要 API。
|
||||
- **必须**:构造完成后对象应满足不变量;不要暴露可变内部集合、数组或日期对象。
|
||||
- **推荐**:优先组合而非继承;继承只用于稳定的 is-a 关系和可替换契约。
|
||||
- **必须**:覆写方法使用 `@Override`;可变参数只用于同类型、同语义参数,不使用 `Object...` 逃避类型设计。
|
||||
- **必须**:构造器不得启动线程、访问远程资源或发布未完全构造的 `this`。
|
||||
- **推荐**:不可变对象优先;必要时使用 defensive copy,并确保集合元素也符合可变性预期。
|
||||
- **推荐**:接口保持内聚,不创建囊括无关操作的“大而全” Service 或 Util。
|
||||
|
||||
## API 与兼容性
|
||||
|
||||
- **必须**:公共 API 明确输入校验、返回语义、错误模型、幂等性和副作用。
|
||||
- **必须**:新增重载时检查 `null`、lambda、自动装箱和可变参数是否造成调用歧义。
|
||||
- **必须**:修改 DTO、枚举、JSON 字段、RPC 签名或异常类型前评估调用方兼容性。
|
||||
- **推荐**:返回接口类型而非具体集合实现;不要泄漏 ORM 实体、框架上下文或内部异常。
|
||||
- **推荐**:避免布尔参数控制多个行为,优先使用有语义的方法、枚举或选项对象。
|
||||
- **必须**:不得以反射、原始类型或未检查转换绕过编译器,除非边界隔离、理由明确并有测试。
|
||||
|
||||
## Lombok
|
||||
|
||||
- **必须**:仅在项目已采用 Lombok 时使用,不为风格统一单独引入依赖。
|
||||
- **参考**:DTO/VO 可使用 `@Data`;使用前检查可变性、相等性和敏感字段,存在特殊约束时改用明确的 `@Getter`、`@Setter`、`@EqualsAndHashCode` 或 `@ToString`。
|
||||
- **推荐**:实体类和值对象避免使用 `@Data`;按项目约定组合 `@Getter`、`@Setter`、`@Builder`、`@NoArgsConstructor` 和 `@AllArgsConstructor`,且不得绕过领域不变量或 ORM 构造约束。
|
||||
- **推荐**:除非继承关系确有需要,不设置 `@EqualsAndHashCode(callSuper = true)`。
|
||||
- **必须**:`toString` 不得暴露敏感字段,也不得触发懒加载或递归引用。
|
||||
@@ -0,0 +1,34 @@
|
||||
# 集合、并发与时间
|
||||
|
||||
## 集合
|
||||
|
||||
- **必须**:选择与语义相符的集合;需要唯一性用 `Set`,需要键查找用 `Map`,不要靠线性扫描模拟索引。
|
||||
- **推荐**:规模可预估时设置合理初始容量,但不得按不可信输入直接分配超大容器。
|
||||
- **必须**:`Arrays.asList` 不是可增删列表;数组元素变化会反映到视图。需要独立可变列表时显式复制。
|
||||
- **必须**:集合转数组使用类型安全的 `toArray` 形式,并遵循项目 JDK 的惯用写法。
|
||||
- **必须**:遍历时删除元素应使用迭代器、`removeIf` 或收集后处理,不在增强 `for` 中直接结构性修改。
|
||||
- **必须**:不要修改 `Map.keySet()`、`values()` 等视图后假设原映射不变。
|
||||
- **必须**:自定义对象作为 `Map` 键或 `Set` 元素时保证 `equals/hashCode` 稳定;插入后不得改变参与哈希的字段。
|
||||
- **推荐**:返回只读视图或副本时明确其快照/联动语义;`unmodifiable` 不等于深度不可变。
|
||||
- **推荐**:Stream 用于清晰的数据变换;有副作用、异常流程或复杂分支时使用普通循环。
|
||||
|
||||
## 并发
|
||||
|
||||
- **必须**:先识别共享可变状态,再选择不可变、线程封闭、并发容器、原子类或锁;`volatile` 不能保证复合操作原子性。
|
||||
- **必须**:线程池必须有清晰的线程数、队列、线程命名、拒绝策略和关闭策略。传统平台线程池不得直接使用默认无界的便捷工厂掩盖这些参数。
|
||||
- **参考**:Java 21+ 虚拟线程需确认项目支持、阻塞模型、限流方式与 `ThreadLocal` 成本;不要把虚拟线程当作无限资源。
|
||||
- **必须**:`ThreadLocal` 使用后在 `finally` 中清理,尤其在线程池和请求复用场景。
|
||||
- **必须**:锁范围尽可能小,不在持锁期间执行未知回调、远程调用或慢 I/O;多个锁必须有固定顺序。
|
||||
- **必须**:捕获 `InterruptedException` 后恢复中断标记或明确终止流程,不得吞掉中断。
|
||||
- **推荐**:高并发随机数使用 `ThreadLocalRandom`;共享计数根据竞争程度选择原子类或累加器。
|
||||
- **推荐**:并行 Stream 仅在数据量、无副作用、线程池影响和基准数据明确时使用。
|
||||
- **必须**:并发正确性不能只靠一次测试;检查竞态、可见性、重复执行、超时、取消与关闭路径。
|
||||
|
||||
## 日期与时间
|
||||
|
||||
- **必须**:优先使用 `java.time`;旧 `Date/Calendar` 仅用于兼容边界并尽快转换。
|
||||
- **必须**:业务时间明确时区。存储时间点优先用 `Instant`,面向地区规则时显式使用 `ZoneId`。
|
||||
- **必须**:不得共享非线程安全的旧式日期格式化器;优先使用不可变的 `DateTimeFormatter`。
|
||||
- **必须**:持续时间测量使用单调时钟语义,如 `System.nanoTime()`;不要用墙上时钟计算短耗时。
|
||||
- **必须**:时间测试固定 `Clock` 或等价抽象,避免依赖当前时间造成不稳定测试。
|
||||
- **推荐**:日期边界、夏令时、闰年和跨时区转换要有针对性用例。
|
||||
@@ -0,0 +1,46 @@
|
||||
# 异常、日志与安全
|
||||
|
||||
## 异常
|
||||
|
||||
- **必须**:异常表达失败语义,不用异常控制正常分支。
|
||||
- **必须**:不要直接抛出宽泛的 `Exception`、`RuntimeException` 或 `Throwable`;使用标准的精确异常或稳定的领域异常。
|
||||
- **必须**:不得空 `catch`、只打印堆栈或吞掉异常。转换异常时保留 cause,并补充不含敏感数据的上下文。
|
||||
- **必须**:同一层通常选择“处理并记录”或“向上抛出”,避免每层重复记录同一异常。
|
||||
- **必须**:可通过前置检查避免的错误应先校验;并发竞态场景仍以原子操作结果为准。
|
||||
- **必须**:资源使用 try-with-resources;`finally` 不得用 `return` 覆盖原返回值或异常。
|
||||
- **必须**:捕获范围保持最小,不用一个大 `try` 模糊具体失败点。
|
||||
- **推荐**:对外错误模型稳定、可追踪且不泄漏内部栈、SQL、文件路径或依赖细节。
|
||||
|
||||
## 日志
|
||||
|
||||
- **必须**:使用项目日志门面,不使用 `System.out`、`System.err` 或 `printStackTrace`。
|
||||
- **必须**:参数化记录日志,不做无必要的字符串拼接;异常对象作为日志框架支持的异常参数传入。
|
||||
- **必须**:日志级别符合可操作性:预期业务拒绝通常不是 error,系统不可恢复失败不能只写 debug。
|
||||
- **必须**:禁止记录密码、令牌、密钥、完整证件号、银行卡、Cookie、会话或未脱敏请求体。
|
||||
- **推荐**:记录稳定的事件、结果、耗时、非敏感标识和 trace/correlation id;避免在高频循环中刷屏。
|
||||
- **必须**:日志不得改变业务行为;日志表达式不得触发远程调用、延迟加载或明显昂贵计算。
|
||||
- **推荐**:项目同时使用 SLF4J 和 Lombok 时采用 `@Slf4j`,否则遵循项目统一的日志门面与声明方式。
|
||||
- **必须**:`error` 仅用于由当前层最终处理、需要人工介入的系统失败,并包含异常堆栈和已脱敏的定位上下文。
|
||||
- **推荐**:`warn` 用于异常但可恢复、仍需要关注的状态。
|
||||
- **推荐**:预期业务拒绝通常使用 `info` 或不记录,避免制造告警噪声。
|
||||
- **必须**:同一异常只在负责最终处理的层记录一次;转换异常时保留原始 cause,不在中间层重复打印堆栈。
|
||||
|
||||
## 输入与权限
|
||||
|
||||
- **必须**:所有外部输入在信任边界验证类型、长度、范围、格式、集合规模和允许值;前端校验不能替代服务端校验。
|
||||
- **必须**:认证后仍要做功能级和对象级授权,不能只检查“是否登录”。
|
||||
- **必须**:SQL 使用参数绑定;排序字段、表名、列名等不可绑定的元数据必须采用服务端白名单。
|
||||
- **必须**:输出到 HTML、脚本、URL、日志或命令时按目标上下文编码;不要自行拼接转义规则。
|
||||
- **必须**:状态变更接口按框架能力启用 CSRF、防重放、幂等或频控措施。
|
||||
- **必须**:文件路径规范化并限制在允许根目录;URL 请求限制协议、主机、重定向和内网地址以防 SSRF。
|
||||
- **必须**:禁止反序列化不可信 Java 原生对象流;JSON 多态、表达式、脚本和正则能力采用最小白名单。
|
||||
- **必须**:凭据来自受控配置或密钥服务,不写入源码、测试、日志和错误响应。
|
||||
- **推荐**:使用成熟安全库和框架默认防护,不自行实现密码学、会话、签名或随机令牌算法。
|
||||
|
||||
## 事务与一致性
|
||||
|
||||
- **必须**:事务边界与业务原子性一致,避免在长事务中执行远程调用或不可控 I/O。
|
||||
- **必须**:明确异常类型是否触发回滚;框架代理、自调用和异步边界可能使事务注解失效。
|
||||
- **必须**:事务方法捕获异常后必须重新抛出、显式标记回滚或完成可靠补偿。
|
||||
- **必须**:重试仅用于可重试失败,并要求操作幂等、退避、次数上限和可观测性。
|
||||
- **推荐**:跨系统一致性采用项目既有 outbox、事件或补偿机制,不临时发明“先写库再发消息”的脆弱流程。
|
||||
@@ -0,0 +1,38 @@
|
||||
# 工程分层与数据访问
|
||||
|
||||
## 分层与依赖
|
||||
|
||||
- **必须**:遵循项目既有模块边界和依赖方向;领域层不得反向依赖 Web、ORM 或具体基础设施实现。
|
||||
- **必须**:Controller/Endpoint 负责协议适配与边界校验,不承载核心业务编排。
|
||||
- **必须**:持久化对象、领域对象和 API DTO 的转换边界明确;不得把 ORM 实体直接作为外部契约。
|
||||
- **推荐**:使用构造器注入表达必需依赖并支持测试;字段注入仅在项目框架约束明确时使用。
|
||||
- **推荐**:工具类无状态、职责单一且构造器不可见;不要创建混杂业务逻辑的通用 `Utils`。
|
||||
- **必须**:循环依赖表示边界问题,不以延迟注入作为默认解决方案。
|
||||
|
||||
## 数据访问
|
||||
|
||||
- **必须**:禁止字符串拼接用户输入生成 SQL;MyBatis 默认使用 `#{}`,`${}` 只允许经过严格白名单的元数据。
|
||||
- **必须**:明确查询列,不使用 `SELECT *` 作为生产查询默认写法。
|
||||
- **必须**:分页总数为零时避免继续执行无意义的数据查询;限制最大页大小和排序字段。
|
||||
- **必须**:批量查询、写入和 `IN` 参数有明确上限并按数据库能力分批。
|
||||
- **必须**:避免循环中逐条远程或数据库调用;检查 N+1 查询和不受控懒加载。
|
||||
- **必须**:更新语句只更新预期字段;乐观锁、版本号或条件更新必须检查受影响行数。
|
||||
- **必须**:事务内查询和更新基于明确隔离假设;不能用应用层 `if` 代替数据库唯一约束或原子条件。
|
||||
- **推荐**:索引设计与真实查询条件、排序和基数一致;新增查询必须评估执行计划或沿用已验证索引。
|
||||
- **推荐**:数据库约束与应用校验共同保护核心不变量,不机械套用“禁止所有外键”;服从项目的数据治理策略。
|
||||
|
||||
## Spring、Jakarta 与 ORM
|
||||
|
||||
- **必须**:Bean Validation 放在真实入口并确保级联校验生效;内部调用仍需保护领域不变量。
|
||||
- **必须**:`@Transactional`、缓存、异步和权限注解必须考虑代理边界、自调用、方法可见性和异常回滚语义。
|
||||
- **必须**:JPA 实体的 `equals/hashCode` 不得依赖会变化的数据库生成标识造成集合异常。
|
||||
- **推荐**:默认避免 Open Session in View 带来的隐式查询;在服务边界显式获取所需数据。
|
||||
- **必须**:MyBatis/JPA 映射字段、枚举、时区和 null 语义必须有测试,不能仅凭同名假设自动映射正确。
|
||||
|
||||
## 构建与依赖
|
||||
|
||||
- **必须**:新增或升级依赖前确认项目 BOM、dependency management、版本锁定和许可证/安全要求。
|
||||
- **必须**:生产发布不依赖不可复现的 SNAPSHOT 或动态版本,除非项目流程明确批准。
|
||||
- **必须**:依赖变更检查传递依赖、冲突、打包体积和运行时兼容;不要只确认“能编译”。
|
||||
- **推荐**:优先使用 JDK 与项目已有库;为一个简单方法引入大型依赖通常不合理。
|
||||
- **必须**:生成代码和资源遵循构建目录约定,不手改会被生成器覆盖的文件。
|
||||
@@ -0,0 +1,67 @@
|
||||
# 测试、审查与验证
|
||||
|
||||
## 测试设计
|
||||
|
||||
- **必须**:测试代码放在项目约定的测试源集,通常为 `src/test/java`;不得把测试逻辑混入生产代码。
|
||||
- **必须**:每个测试具有清晰的 Arrange/Act/Assert 或 Given/When/Then 结构,一个失败能指出一个主要行为。
|
||||
- **必须**:测试独立、可重复、可并行时不互相污染;不得依赖执行顺序、真实当前时间、随机外网或共享生产数据。
|
||||
- **必须**:断言业务结果、状态变化和外部交互,不只断言“无异常”或覆盖实现细节。
|
||||
- **推荐**:遵循 AIR 原则:Automatic、Independent、Repeatable;覆盖 BCDE:Boundary、Correct、Design、Error。
|
||||
- **必须**:缺陷修复先加入能复现问题的测试;新行为先建立失败证据,再实现通过。
|
||||
- **推荐**:单元测试隔离自身职责,集成测试验证真实框架映射、事务、序列化和数据库行为。
|
||||
- **必须**:Mock 只隔离边界,不复刻被测实现;过多 Mock 通常提示职责或测试层级错误。
|
||||
- **推荐**:测试命名表达条件与预期,服从项目现有 JUnit/TestNG、Mockito、AssertJ 等风格。
|
||||
|
||||
## 风险用例
|
||||
|
||||
按任务选择至少检查:
|
||||
|
||||
- null、空值、最小/最大长度、零、负数、溢出、重复和非法枚举;
|
||||
- 精度、舍入、字符编码、Locale、时区和夏令时;
|
||||
- 超时、重试、重复请求、部分失败、事务回滚和幂等;
|
||||
- 并发更新、锁竞争、中断、资源关闭和线程池拒绝;
|
||||
- 未认证、未授权、越权、注入、恶意大输入和敏感信息泄漏;
|
||||
- 序列化前后兼容、数据库映射和旧调用方行为。
|
||||
|
||||
## Code Review 清单
|
||||
|
||||
1. 将每条需求映射到实现与至少一项验证证据。
|
||||
2. 阅读完整 diff 和必要上下文,不只看新增行。
|
||||
3. 检查是否覆盖用户已有改动或包含无关格式化。
|
||||
4. 检查空值、异常、资源、并发、事务、数据规模和安全边界。
|
||||
5. 检查 API、DTO、SQL、配置与依赖的兼容性。
|
||||
6. 检查测试能在错误实现下失败,避免只验证 Mock 自己的返回。
|
||||
7. 将发现按 `阻断/严重/一般/建议` 分级,并给出触发条件和影响。
|
||||
8. 修复后重新阅读 diff 并重跑受影响验证。
|
||||
|
||||
## 命令选择
|
||||
|
||||
先从仓库文档和 CI 获取标准命令,常见候选仅供识别:
|
||||
|
||||
```text
|
||||
Maven: ./mvnw test
|
||||
Gradle: ./gradlew test
|
||||
```
|
||||
|
||||
不要假定包装器、模块名或 profile 一定存在。优先运行:
|
||||
|
||||
1. 单个受影响测试;
|
||||
2. 受影响模块测试;
|
||||
3. 编译与项目配置的 formatter/Checkstyle/PMD/SpotBugs;
|
||||
4. 风险要求的集成测试或全量构建。
|
||||
|
||||
项目已配置 P3C 时使用既有入口。若未配置,进行人工规则 Review,并把“未运行 P3C”明确写为未验证项,而不是临时修改构建。
|
||||
|
||||
## 结果报告
|
||||
|
||||
每项验证记录:
|
||||
|
||||
```text
|
||||
命令或检查:
|
||||
范围:
|
||||
结果:通过 / 失败 / 未执行
|
||||
证据摘要:
|
||||
失败或未执行原因:
|
||||
```
|
||||
|
||||
只报告本次实际获得的证据。环境错误、既有失败和本次回归必须区分;无法确定归属时标记为待调查,不得猜测。
|
||||
Reference in New Issue
Block a user