


在分模块的Java项目中,保持兼容地做小范围修改
让AI修改分模块的Java项目时使用。先查清构建和CI的规则,保证旧的Java版本和模块依赖仍能正常工作,在合适的层级测试,并在大范围或破坏性操作前先询问。
要使用这个AI规则
## 编辑前先查清构建、格式和CI的规则
将仓库指南、构建配置、格式规则和持续集成检查视为可执行的契约。编辑前先阅读适用的说明,并确定哪些规则由工具强制执行。
- 找到规范的构建包装器、格式化工具、静态检查、测试命令和贡献政策。
- 更改代码前,追溯负责该代码的模块及其依赖关系。
- 优先采用项目中既有的工具和模式,而不是只图本地便利的替代方案。
- 区分源代码兼容性、构建工具要求、运行时支持和分发行为。
- 不要仅仅为了让变更通过而禁用质量关卡。
使用能够控制所请求行为的最小权威输入。
## 确保代码在声明的Java版本和依赖下正常工作
构建可能需要较新的工具链,而源代码仍须与较旧的运行时兼容。按照声明的源代码级别进行编译和测试;不要因为本地环境较新,就认为可以使用较新的语言功能或库 API。
- 将不受支持的便捷 API 替换为兼容的等效方案。
- 必要时使用仓库中经过重定位或着色处理的依赖项命名空间。
- 对于验证、序列化、集合、文件、Future 和时间处理,优先使用项目自有工具。
- 如果分发包隔离了这些库,就不要直接导入第三方库。
- 添加依赖项前,先讨论兼容性、许可、打包方式和传递影响。
通过仓库指定的构建目标验证兼容性,不要只依赖本地编译。
## 公开API使用工厂、构建器和不可变的结果对象
根据预期的稳定性标记 API:稳定的公开契约、演进中的公开契约和内部实现界面必须保持明确区分。
- 工厂应返回接口,并将构造过程隐藏在私有构造函数或静态创建方法之后。
- 多步骤配置应使用构建器,提供流式方法和一个经过验证的构造点。
- 结果对象应保持不可变:状态使用 final、不提供 setter,并完整实现相等性、哈希和字符串表示。
- 当调用方需要通用和类型化两种形式时,应同时提供对应接口,避免不安全的类型转换。
- 在公开类型上说明线程安全要求。
更改公开契约需要进行兼容性分析,并采用适当的版本演进路径。
## 让模块之间的依赖保持单一方向
实现前先绘制模块关系图。基础模块应拥有共享类型和接口;协议层或传输层构建在其上;同级的客户端模块与服务器模块不应相互依赖;集成功能应位于稳定的下层之上。
- 在适当的最底层模块中定义共享接口,并在其上层放置实现。
- 防止连接器和可选集成功能把依赖项泄漏到核心中。
- 防止循环依赖以及同级模块之间仅为方便而引入的导入。
- 测试应与生产代码的包结构保持一致。
- 将生成代码、分发资源、文档生成器和测试工具放入各自指定的模块。
功能跨越边界时,应明确修改每个负责的层级,而不是绕过架构。
## 区分错误类型,并用锁保护共享状态
在 API 边界使用项目标准的前置条件辅助工具和可指导行动的消息来验证输入。保留异常层次结构,使调用方能够区分用户错误、可重试故障和非受检的内部故障。
- 通过既有的 Future 工具和错误处理程序传播异步故障。
- 组合异步工作,不要在没有文档说明理由的情况下阻塞。
- 使用显式锁保护共享的可变状态,并记录受保护的字段。
- 只有在锁外访问确有需要时,才使用可见性原语。
- 通过结构化资源管理关闭资源。
- 如果清理操作可能重复执行,应使 close 操作保持幂等。
不要隐藏受检故障,也不要把可重试错误和永久性错误合并成一个无法区分的异常。
## 保持配置键和消息格式的兼容
在适用时,通过带有默认值、说明、可选值和弃用键处理机制的类型化构建器来定义配置。使用层次清晰且一致的键,并通过仓库的配置抽象访问值。
对于序列化和远程消息:
- 保持声明的模式和协议版本;
- 只使用该版本支持的字段形式;
- 模式变更后,使用规范生成器重新生成代码;
- 保持传输消息不可变,并相应标记内部传输类型;
- 明确表示可选字段;
- 当生成工作流负责文件时,绝不要直接编辑生成文件。
每当配置或传输契约发生变化时,都要更新兼容性测试和生成文档。
## 用项目的测试工具编写单元测试和集成测试
使用仓库选定的测试框架、断言库、命名约定、扩展和基础夹具。不要混入与全局测试工具冲突的其他断言或超时机制。
- 为局部行为编写范围集中的单元测试,为跨组件契约编写集成测试。
- 使用能够说明被测行为的描述性测试名称。
- 同时断言成功结果和预期失败。
- 复用受支持的集群、存储或服务夹具,不要创建平行基础设施。
- 先运行范围狭窄且受影响的测试,再运行直接受影响的测试套件。
- 在依赖测试证明修复有效之前,先确认它因预期原因而失败。
如果内部实现细节不属于契约的一部分,就通过公开行为进行测试。
## 通过项目的构建包装器完成构建和检查
使用仓库包装器执行构建、格式化、静态分析、许可证检查、代码生成和测试。规范命令可能会准备生成资源或强制执行兼容性,而直接调用工具会漏掉这些步骤。
- 使用文档规定的工具链构建,同时保持声明的源代码目标。
- 按文档规定的顺序启动本地服务依赖项和组件。
- 只编辑受支持的配置文件和值。
- 在静态检查前运行格式化。
- 在进行更广泛的验证前,先运行受影响的测试套件。
- 如果变更可能改变被测行为,就使用覆盖率配置。
在报告完成前,应了解持续集成的各个阶段,并在本地重现相关阶段。
## 遵循格式化工具,差异中不混入无关修改
遵循强制规定的导入顺序、修饰符顺序、数组语法、花括号规则、空白政策和命名约定。让规范格式化工具处理机械性的样式问题。
- 避免通配符导入,以及仓库禁止的注释标记或署名标签。
- 如果项目要求,应为 public 和 protected API 保留文档。
- 通过提取职责明确的部分来遵守文件大小限制,而不是压缩代码、牺牲可读性。
- 当命令、配置、兼容性或公开行为发生变化时更新文档。
- 审查最终差异,检查是否存在无关重写、意外编辑生成文件、机密信息或未完成的清理。
不要把范围集中的行为变更与无关的重构混在一起。
## 通过审查分支提交修改,不使用force-push
在获准的分支上工作,并在推送前验证每一个远程仓库。保护上游分支或共享分支;通过项目的审查流程提交变更,不要直接写入受保护目标。
- 按照文档规定的流程,从规范的基础分支进行 rebase 或更新。
- 编写简洁且限定组件范围的提交主题,并在必要时于正文中说明动机。
- 发布前审查完整的分支差异。
- 运行格式化、静态检查、许可证检查和受影响的测试。
- 在审查请求中加入简明摘要和测试计划。
- 如果贡献政策要求,应标明借助工具完成的变更,以供人工审查。
未经明确授权,绝不要对共享分支执行 force-push,也不要使用破坏性的历史记录操作。
## 添加新依赖或重置等大范围、破坏性操作前先询问
对于遵循现有规则且范围明确的读取、本地构建、测试、格式化、诊断和修复,可以自主进行。对于跨模块重构、新依赖项、模式迁移、构建系统变更、持续集成变更或破坏性操作等范围广泛或后果重大的工作,应先征得同意。
未经明确许可,绝不要:
- 提交凭据或敏感值;
- 直接推送到受保护的上游目标;
- 对共享历史记录执行 force-push 或删除分支;
- 执行 hard reset 或破坏性清理;
- 绕过 hook、静态检查或格式规则;
- 修改生成的产物而不是其源文件;
- 为获得通过结果而削弱质量关卡。
完成前,应验证测试、格式化、静态检查、必需的文件头以及完整的预期差异。如果范围或可逆性不明确,应停止并说明需要作出的决定。
