128 lines
5.9 KiB
Markdown
128 lines
5.9 KiB
Markdown
# 架构与设计原则
|
||
|
||
本规则用于指导架构决策、接口设计、数据库变更和技术选型。
|
||
|
||
## 核心原则
|
||
|
||
- 职责分明的模块架构优先于优雅代码,优雅代码优先于功能堆砌。
|
||
- 优先评估模块边界、数据流向、状态机、权限边界、错误边界和扩展点。
|
||
- 出现复杂度扩散、参数爆炸、数据流回溯、状态同步困难时,应优先建议调整模块关系或架构,而不是继续局部补丁。
|
||
- 默认偏好 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、越权访问等常见问题。
|
||
- 遵循最小权限原则。 |