Skip to content

Latest commit

 

History

History
208 lines (157 loc) · 12.9 KB

File metadata and controls

208 lines (157 loc) · 12.9 KB

开发规范

修订记录

修订时间(CST) 修订人 修订说明
2026-08-31 whisper 明确通用规范适用于全部维护者
2026-08-28 whisper 规范临时 Markdown 工作文档
2026-08-28 whisper 接入开源仓库文本与许可基线
2026-08-28 whisper 明确版本控制排除项和中文提交信息
2026-08-27 whisper 建立 Starter 通用开发规范

本文规定 Android Starter 中代码书写之外的工程实践, 包括变更决策, 任务拆分, 兼容性, 验证, 文档同步和 Git 提交. 具体代码的命名, 格式和编码规则见 代码规范; 模块设计, 维护和接入契约见对应模块的 design.md, development.mdusage.md.

本文适用于所有参与项目维护的人员, 自动化工具和智能体. 根目录 AGENTS.md 只补充智能体特有的执行, 授权和指令解释规则, 不替代本文.

Starter 是面向不同应用的公共模板. 本文不固化具体应用的业务流程, 域名, 环境, 错误码, 鉴权方式或发布渠道.

1. 变更合理性

开始修改前先回答以下问题:

  1. 当前真实问题是什么, 期望改变的行为是什么.
  2. 该职责属于哪个模块, 是否符合现有依赖方向和公开边界.
  3. 现有能力能否满足需求, 是否确有必要增加抽象, 依赖或配置.
  4. 哪些调用方, 变体, 生成链路, 数据或公开契约会受到影响.
  5. 如何验证变更有效, 失败时如何回退或迁移.

合理性判断遵循以下原则:

  • 先读取真实代码, 构建配置和相关模块文档, 不仅依据名称或预期推断现状.
  • 新增抽象必须减少已经存在的复杂度, 消除真实重复或建立清晰边界, 不为假设需求提前设计框架.
  • 优先复用项目已有的模块边界, 约定插件和公共 API, 不建立语义相同的第二套机制.
  • 公共模板只提供通用能力和可替换契约, 应用差异由 app 组合根或应用实现层注入.
  • 方案显著扩大需求范围, 改变公开契约或产生不可逆影响时, 先说明收益, 代价和迁移方案, 再实施.
  • 发现与当前目标无关的问题时单独记录, 不以"顺手修复"为由扩大当前变更.

2. 任务与变更拆分

任务按可独立理解, 审查和验证的能力拆分, 不按文件数量机械拆分.

  • 一个变更单元只表达一个明确意图, 例如修复一个缺陷, 增加一项能力或完成一次契约迁移.
  • 功能实现, 无关重构, 依赖升级, 批量格式化和目录整理不得混入同一变更单元.
  • 为当前功能必需的局部重构可以同行, 但应能说明其必要性和影响范围.
  • 跨模块契约及其实现不可为了按模块拆分而制造不可编译或语义不完整的中间状态.
  • 大任务先列出预期变更单元, 依赖顺序, 验证方式和提交边界, 实施中发现事实变化时及时调整.
  • 每个阶段尽量保持项目可编译, 使问题能够定位到最小变更范围.

以下内容通常应拆开处理:

内容组合 处理方式
新功能与无关代码清理 分开, 避免扩大评审范围
依赖升级与业务行为修改 分开, 避免无法判断回归来源
批量格式化与逻辑修改 分开, 保留可读 diff
多个互不依赖的插件或公共能力 按能力分别处理和提交
公开契约与对应实现, 测试和文档 保持同一原子变更, 避免仓库出现不完整契约

3. 工作区与产物

  • 开始和交付前检查 git status, 区分当前任务修改, 用户已有修改和生成产物.
  • 保留与当前任务无关的已有修改, 不擅自恢复, 删除, 覆盖, 取消暂存或纳入提交.
  • 修改重叠文件时先理解已有 diff, 在其基础上完成变更, 不用整文件覆盖消除他人内容.
  • 根目录 .gitattributes 统一仓库文本换行并声明二进制格式; .editorconfig 统一编辑器基础格式. 不使用个人 Git 或 IDE 配置生成与仓库基线冲突的大范围格式变化.
  • 公共模板默认完整忽略 .idea/*.iml, 不提交依赖个人 IDE、插件、JDK 路径或运行目标的项目元数据. 确有跨团队共享价值的 IDE 配置需要单独评审, 不能通过 git add -f 绕过当前规则.
  • 默认不提交 build/, .gradle/, .kotlin/, local.properties, APK / AAB, 签名文件、应用服务配置、缓存、日志、 临时文件和本机路径配置. 根目录 .gitignore 负责给出仓库统一基线, 模块不得用更宽松的局部规则重新纳入这些内容.
  • .gitignore 只影响尚未被追踪的文件. 发现排除项已经进入版本控制时, 需要同时处理当前索引; 如果要求历史中从未出现, 还必须在确认分支、远程和协作者影响后重写相关历史, 不能只追加一个删除提交.
  • 生成文件只有在仓库明确将其作为源码或发布产物版本化时才提交; 否则只提交生成源和生成规则.
  • 临时诊断代码, 测试开关, 示例凭据和占位文件必须在交付前清理.
  • 批量格式化或自动生成前先确认目标范围, 避免改写无关模块.

4. 契约与兼容性

修改公共能力时分别检查源码兼容, 二进制兼容和行为兼容, 不能只以编译通过判断安全.

重点关注:

  • public / protected 类型, 包名, 方法, 参数, 默认值, 泛型边界, 注解和资源名称.
  • Kotlin 公开参数重命名对命名实参调用方的影响.
  • Flow 的冷 / 热流语义, replay, buffer, 取消, 并发和生命周期行为.
  • 网络请求和响应, 序列化模型, 路由, Manifest 组件与 Intent 参数.
  • 数据库 schema, 迁移路径, 持久化 key 和已经落盘的数据.
  • BuildConfig, flavor, Gradle 插件, 生成代码及其产物位置.
  • R8 / ProGuard, 反射, ServiceLoader, JNI 和注解处理发现规则.

兼容性无法保持时必须提供明确迁移方案, 标注破坏范围, 并扩大调用方验证.

5. 依赖与构建

  • 不在无关任务中顺便升级 AGP, Kotlin, Gradle, 插件或业务依赖.
  • 新增依赖前确认现有依赖不能满足需求, 并评估体积, 许可证, 维护状态, Android 兼容性和传递依赖.
  • 版本和插件坐标优先由 gradle/libs.versions.toml 统一管理.
  • api(...) 只用于调用方源码或 ABI 确实需要看到的依赖, 其它依赖使用最小暴露范围.
  • build-logic 中的公共约定应保持职责单一; 可选插件不能成为所有项目或模块的隐式前提.
  • 构建逻辑变更需要覆盖受影响的插件组合, 模块类型和变体; 可选能力同时验证接入和未接入路径.
  • 不把本机 SDK 路径, 私服凭据, 签名信息或应用真实环境值写入公共模板.

6. 测试与验证

验证范围随风险和影响面扩大:

变更类型 最低验证要求
文档或注释 链接, 示例, 修订记录和 git diff --check
局部纯逻辑 相关单元测试和受影响模块编译
公共 API 或公共模块 模块测试, 直接调用方编译和必要的兼容性检查
协程, Flow, 缓存或并发 边界, 取消, 重放, 顺序和并发行为测试
Android 生命周期或资源 相关集成测试或可复现的设备 / 模拟器验证
构建逻辑或生成代码 相关插件测试, 生成任务, 受影响变体和消费方编译
数据库或持久化格式 schema, 升级 / 降级策略和真实迁移路径验证
  • 修复缺陷时补充能够复现问题并防止回归的测试.
  • 不为测试放宽生产 API, 改变生产行为或暴露无业务价值的内部状态.
  • 测试不能覆盖的风险需要通过集成验证, 示例工程或明确的人工步骤补足.
  • 执行验证后记录具体命令和结果; 无法执行的验证项必须说明原因和剩余风险.
  • 构建或测试失败时先区分当前修改, 工作区已有修改和外部环境问题, 不静默忽略失败.

7. 文档同步

代码和文档共同构成项目契约. 行为或接入方式改变时, 在同一变更中更新对应文档:

内容 文档位置
设计目标, 职责边界和取舍 模块 design.md
维护规则, 扩展点和实现约束 模块 development.md
接入步骤, 配置和公开示例 模块 usage.md
代码命名, 格式和书写方式 application/code-style.md
通用开发与交付流程 application/development.md
智能体执行和授权限制 根目录 AGENTS.md
  • 实质修改 Markdown 时同步更新其修订记录, 不改写历史记录.
  • 示例代码必须使用当前真实 API, 占位值不得伪装成生产配置.
  • 临时评审, 诊断或迁移跟踪文档使用 *.tmp.md 后缀, 例如 architecture-review.tmp.md. 根目录 .gitignore 统一忽略此类文件, 不使用 git add -f 将其作为长期文档提交.
  • 临时文档需要标明状态, 负责人和清理条件. 任务结束前将仍有价值的结论迁入对应的 design.md, development.md, usage.md 或正式 Issue, 随后删除临时文件; 过程记录和已经关闭的问题列表不进入长期文档.
  • 实现与文档冲突时应确认当前事实和设计意图, 同步修复一方, 不长期保留矛盾描述.

8. Git 提交

8.1 提交规划

提交前先判断本次工作应拆成哪些提交, 并能说明每个提交的独立意图和边界.

  • 每个提交代表一个可独立审查, 验证和回滚的能力或修复.
  • 不把多个无关模块, 插件或问题压入一个"大提交". Prism, Aster, Habitat, Quill 等独立能力默认分别提交.
  • 不按文件数量或目录机械拆分. 同一公开契约的实现, 测试, 文档和必要迁移应进入同一原子提交.
  • 一个提交需要依赖前置提交时保持清晰顺序; 每个中间提交尽量能够独立构建.
  • 纯格式化, 依赖升级, 重命名和功能修改只在彼此不可分割时合并, 否则分别提交.

8.2 暂存与检查

工作区存在其它修改时, 使用明确路径或交互式 patch 暂存当前提交内容, 不直接执行 git add .git add -A.

每个提交前至少检查:

git status --short
git diff --cached --stat
git diff --cached
git diff --check
git diff --cached --check

确认以下事项:

  • 暂存区只包含当前提交需要的文件和变更片段.
  • 实现, 测试, 文档和迁移内容完整, 没有只提交一半的重命名或契约.
  • 未纳入 IDE 配置, 本地产物, 密钥或其它任务的修改.
  • diff 中没有调试代码, 无意义格式变化, 冲突标记和空白错误.
  • 已执行与本次提交风险相匹配的验证.

8.3 提交信息与历史

提交信息使用 Conventional Commits 结构, 类型和 scope 使用英文小写关键字, 摘要和正文使用中文:

feat(network): 增加通用请求路由能力

type 使用 feat, fix, refactor, test, docs, build, chore 等明确类别; scope 表示主要能力或模块. 中文摘要直接说明 提交结果, 不添加句号; 必要的背景、兼容性和验证信息写入中文正文. 代码标识符、文件名、插件 ID 和命令保持原始英文.

  • 不使用 update, changes, misc 等无法表达意图的摘要.
  • 提交后检查提交内容和顺序, 确认没有遗漏或误纳文件.
  • 未经明确授权不修改已经共享的提交历史, 不随意 amend, rebase 或 force-push 共享分支.
  • 尚未共享且需要清除误提交文件或统一提交信息时, 可以在明确授权后重写历史. 重写前必须确认所有受影响分支、创建仓库外备份并验证新历史; 已经共享时还需要协调所有协作者重新同步, 不能把强制推送视为普通提交操作.
  • 修正尚未共享的本地提交时仍应保持原子性, 不用 amend 掩盖本应独立审查的新能力.

9. 完成与交付

交付结果至少说明:

  • 完成了哪些行为或契约变更.
  • 执行了哪些测试, 构建或静态检查及其结果.
  • 哪些内容未验证, 原因和剩余风险是什么.
  • 是否存在兼容性, 迁移, 配置或后续清理事项.
  • 用户要求提交时, 列出提交及其独立职责.

只有代码, 测试, 文档和必要迁移保持一致, 且已完成与风险匹配的验证后, 任务才算完成.