# 架构与设计原则 本规则用于指导架构决策、接口设计、数据库变更和技术选型。 ## 核心原则 - 职责分明的模块架构优先于优雅代码,优雅代码优先于功能堆砌。 - 优先评估模块边界、数据流向、状态机、权限边界、错误边界和扩展点。 - 出现复杂度扩散、参数爆炸、数据流回溯、状态同步困难时,应优先建议调整模块关系或架构,而不是继续局部补丁。 - 默认偏好 Functional Programming 和可读的 DSL 化组织方式;除非项目已明确是面向对象架构。 - 新技术、新依赖、新服务引入前,说明理由、收益、成本、风险和替代方案,并等待确认。 - 接口设计优先明确契约:输入、输出、错误结构、状态码、幂等性、权限、兼容性。 ## ADR 架构决策记录 - 重大技术决策必须写入 ADR,避免决策只存在于聊天或临时说明中。 - ADR 路径:`pmdocs/adr/YYYY-MM-DD-序号-主题.md`。 - ADR 触发条件: - 前端技术栈、后端技术栈、数据库或运行时选择。 - 认证授权、权限模型、状态管理、路由结构或部署方式选择。 - 重大模块边界调整、数据流调整、状态机调整。 - 引入会影响长期维护成本的新依赖、新服务或基础设施。 - 关键性能、安全、可扩展性方案选择。 - ADR 必须包含:背景、决策选项、最终选择、选择理由、影响后果、风险和回滚思路。 - ADR 只记录重要决策;普通实现细节不要过度记录。 ### ADR 模板示例 ```markdown # ADR-001:选择 xxx ## 背景 为什么需要决策 ## 选项 - A:优点 / 缺点 - B:优点 / 缺点 ## 决策 选择哪个方案 ## 后果 带来的收益、成本、风险 ``` ## API 变更约束 - API 变更必须明确:请求结构、响应结构、错误码、权限要求、幂等性、兼容性和废弃策略。 - API 变更必须同步到 `pmdocs/1-prd-XXX.md`、`pmdocs/2-task-XXX.md` 或对应变更文档;如果项目已有 OpenAPI / GraphQL Schema / RPC IDL,也必须同步。 - 涉及权限码的 API 变更,必须同步权限码表、后端校验、前端权限门禁和测试用例。 - 破坏性 API 变更必须进入需求变更流程,并在 7 维度影响评估表中明确处理动作和状态。 ### API 变更检查清单 - [ ] 请求结构(字段、类型、必填、默认值) - [ ] 响应结构(字段、类型、状态码、错误码) - [ ] 权限要求(角色、权限码、访问边界) - [ ] 幂等性(POST / PUT / DELETE 是否幂等) - [ ] 兼容性(新增字段 / 废弃字段 / 破坏性变更) - [ ] 文档同步(PRD / 任务 / OpenAPI / GraphQL Schema) - [ ] 测试覆盖(单元测试 / 集成测试 / 权限测试) ## 数据库变更约束 - 数据库变更必须明确:表、字段、索引、约束、迁移脚本、回滚脚本、seed 是否调整、历史数据兼容策略。 - 数据库变更必须评估查询性能、索引影响、默认值、空值、唯一约束和线上数据迁移风险。 - 涉及权限码的 DB 变更,必须同步权限码表、后端校验、前端权限门禁和测试用例。 - 破坏性 DB 变更必须进入需求变更流程,并在 7 维度影响评估表中明确处理动作和状态。 ### 实体唯一代码规范 - 业务主体实体(用户、组织、部门、商品、订单、项目)和配置数据(角色、字典项、模板)必须有唯一业务代码。 - 唯一代码格式:`{前缀}_{业务含义}` 或 `{模块}_{编号}`,例如: - 用户:`USER_admin001`、`USER_john_doe` - 商品:`PROD_SKU12345` - 订单:`ORDER_20260705001` - 权限:`PERM_USER_CREATE` - 唯一代码约束: - 必须有唯一索引 - 一旦创建不可修改 - 优先可读性,而非简洁性 - 其他表引用时,优先使用唯一业务代码作为外键,而不是自增 ID。 - 好处:数据可读、跨系统可追溯、数据库导入导出友好、便于调试。 - 权衡:查询性能可能略低于整数 ID,必须在唯一代码字段上建立索引。 - 不需要唯一代码的场景:纯关联表、日志、审计、历史记录、一次性临时数据、只在父实体内部使用的子表。 ### 数据库变更检查清单 - [ ] 表、字段、索引、约束变化 - [ ] 迁移脚本(migration) - [ ] 回滚脚本(rollback) - [ ] seed 数据是否调整 - [ ] 历史数据兼容策略(默认值 / 数据填充 / 迁移脚本) - [ ] 查询性能影响(索引 / 全表扫描 / 锁表风险) - [ ] 空值、唯一约束、外键约束影响 - [ ] 线上数据迁移风险(停机 / 灰度 / 双写) - [ ] 测试覆盖(单元测试 / 集成测试 / 迁移测试) ## 代码质量 - 遵循项目既有代码风格。 - 保持单一职责、高内聚、低耦合。 - 避免重复代码,避免过度抽象。 - 命名必须语义清晰。 - 注释只解释代码无法自解释的意图、约束和权衡,不写表面行为注释。 ## 错误处理 - 不忽略错误。 - 用户可见错误要友好,内部错误要可诊断。 - 对关键边界做输入校验、权限校验和异常处理。 - 错误处理路径应有测试覆盖。 ## 测试与验证 - 功能代码和测试代码尽量同步完成。 - 公共函数、核心业务规则、权限判断、错误处理和边界条件应有测试。 - 测试优先使用 Arrange-Act-Assert 或 Given-When-Then。 - 使用 Mock / Stub 隔离外部依赖。 - 测试应快速稳定,避免不必要的 sleep 或长等待。 - 完成实质性编辑后,检查 linter 或诊断;若引入错误,应修复。 ## 安全 - 不在代码、规则、提交信息或文档中硬编码密钥、令牌、密码。 - 敏感信息应使用环境变量、密钥管理器或用户指定的安全存储方式。 - 验证所有用户输入,防止注入、XSS、越权访问等常见问题。 - 遵循最小权限原则。