Files
a-share-analysis/docs/governance/code-development-standards.md
T

199 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 代码开发规范
## 1. 目标
本规范保证代码对普通开发者可连续阅读、对关键业务可解释、对历史版本可维护。规范适用于 Vue 3 前端、NestJS 后端、调度器、RocketMQ Worker、数据适配器、规则引擎和 AI 分析模块。
## 2. 技术基线
- 前端:Vue 3、Vite、TypeScript、Dart Sass、Naive UI;浏览器 HTTP 请求统一使用 Axios,接口类型由 OpenAPI 生成。
- 后端:NestJS、TypeScript。
- 数据库:MySQL 5.7.x,字符集 `utf8mb4`,排序规则 `utf8mb4_general_ci`;缓存:Redis;消息队列:RocketMQ 5.x。
- 图表:Lightweight Charts负责K线和分时,ECharts负责热力图、分布和资金趋势。
- AI:由服务端调用兼容 OpenAI 格式的付费 API,密钥不得下发浏览器。
依赖版本必须由锁文件固定。引入新依赖前必须在功能设计中说明用途、现有替代方案、维护状态、许可证、安全风险、前端体积或服务端运行成本以及退出方案,验证通过后才能安装。
## 3. 文件组织与拆分尺度
代码按业务能力组织,而不是把每个函数、类型和常量拆成独立文件。
### 应当拆分
- 文件同时承担两个可独立变化的业务职责。
- 模块形成稳定复用边界,且确实被多个调用方使用。
- 单个文件已经难以在一次正常阅读中理解完整流程。
- 外部系统适配、持久化、消息传输与纯业务计算需要隔离测试。
### 不应拆分
- 只为减少行数创建单函数文件。
- 将同一业务流程拆成大量需要来回跳转的薄包装。
- 为尚未出现的复用场景提前抽象。
- 为形式上的“分层”添加不产生业务价值的转发层。
复用代码、工具类、Composable 或组件只有在真实重复已经出现、职责边界稳定且抽取确实能降低维护成本时才建立。名称相似、预计以后会用或单纯减少文件行数不构成抽取依据;Review 必须能说明抽取的现有调用方和所有权。
Vue 页面可以包含与页面强绑定的小型展示逻辑;当子区域拥有独立状态、独立测试价值或被复用时再提取组件。NestJS 模块应让入口、服务和领域计算的调用关系容易跟读。
## 4. 命名与语言
- 文件、变量、函数、类型和数据库字段使用清晰英文命名。
- 产品文案、业务日志、错误说明、代码注释和提交摘要优先使用中文。
- 禁止 `data1`、`temp2`、`handleThing` 等缺乏语义的命名。
- A 股领域词汇使用统一词典,例如 `limitUpCount`、`brokenBoardRate`、`marketBreadth`。
- 时间字段必须体现语义,例如 `tradeDate`、`snapshotAt`、`sourceUpdatedAt`,不得统称 `time`。
## 5. 注释规范
代码必须写详细但有信息价值的中文注释。注释解释“为什么、口径、限制和风险”,不复述语法。
### 必须注释
- 对外导出的公共接口、类型和关键函数。
- 涨跌停、复权、停牌、午间休市等 A 股特殊规则。
- 指标公式、阈值来源、单位、数据日期和缺失值处理。
- RocketMQ 的 Topic、Tag、Group、幂等、重试、死信和消息顺序假设。
- Redis 与 MySQL 一致性边界和缓存失效策略。
- AI 输入裁剪、事实约束、降级和成本控制逻辑。
- 看似可以简化但因兼容性或历史原因必须保留的实现。
- 异常恢复、降级策略和安全边界。
### 禁止注释
```ts
// 将 count 加一
count += 1;
```
此类注释没有提供代码之外的信息。代码变更时,注释必须同步更新;失真的注释视为缺陷。
## 6. 类型与数据契约
- 禁止无理由使用 `any`;外部输入先以 `unknown` 接收并校验。
- HTTP API 使用版本化 OpenAPI 契约。
- RocketMQ 事件包含 `eventId`、`eventType`、`schemaVersion`、`occurredAt`、`tradeDate`、`traceId` 和 `idempotencyKey`。
- Topic 使用稳定的业务域命名,环境隔离由部署配置的前缀完成;Tag 表达同一 Topic 内的事件类型,Consumer Group 表达独立消费进度,禁止把临时实例名作为 Group。RocketMQ 5.x Proxy Producer 不配置旧 Remoting Producer Group。
- 需要顺序处理的消息必须明确消息组键,例如证券代码或交易日;未声明顺序键时不得依赖全局到达顺序。
- 金额、成交额和比率必须明确单位,避免同一字段混用元、万元、亿元或百分比小数。
- 数据来源、采集时间、交易日期、完整性和口径版本必须可追溯。
## 7. 错误处理与日志
- 不吞异常,不使用空 `catch`。
- 对外错误不泄露密钥、内部地址和原始上游响应。
- 日志使用结构化字段,至少包含 `traceId`、任务类型、交易日期和数据源。
- 免费数据源失败时保留最后有效快照,并明确标记陈旧,禁止伪装实时数据。
- AI 失败不得影响规则分析和基础行情展示。
## 8. 环境配置规范
- 应用只接受 `development` 与 `production`,环境必须显式设置。生产启动不得回退到开发默认值、模拟数据、热更新或调试模式。
- API、Scheduler、Worker 必须使用各自的配置 Schema,在进程启动时验证类型、格式、范围和条件必填项;配置错误立即退出。
- 同一进程的开发与生产模板必须保持相同变量名。环境差异通过配置值、依赖注入和 Adapter 收敛,禁止在业务代码中散落 `APP_ENV` 分支。
- 只有 `*.env.example` 可以提交;真实 `.env`、`*.env.local`、密码、Token 和 API Key 必须被 Git 忽略并由运行环境注入。
- Web 只能使用公开的 `VITE_*` 变量。数据库、Redis、RocketMQ、数据源和 AI 凭据禁止进入前端变量或构建产物。
- MySQL、RocketMQ、正式数据源与 AI 使用显式功能开关;关闭时连接变量可为空,开启后缺少任何必填值都必须拒绝启动。
- 开发源码进程与 Ubuntu 生产源码部署复用同一变量契约;项目脚本不得安装、启动、停止或删除 Redis、MySQL、RocketMQ 等外部基础设施。
- 生产配置必须位于发布目录之外,切换应用版本不得覆盖配置;日志和诊断输出必须对配置值脱敏。
## 9. 前端规范
- 页面不得直接访问第三方行情源、Redis、RocketMQ 或 AI 服务。
- `web/src/utils/request.ts` 是唯一 Axios 实例、拦截器、超时、取消和通用错误处理入口;其他文件不得创建 Axios 实例。
- 所有业务接口按后端业务域放在 `web/src/api/<业务域>/index.ts`,API 文件统一调用 `@/utils/request`,不得绕过封装。
- 页面、组件、Store 和 Composable 不得直接导入 Axios、调用浏览器 `fetch`、拼接业务 URL 或依赖 `AxiosResponse`。
- 后端 OpenAPI 文档是本项目 HTTP 契约的机器可读描述,与兼容 OpenAI API 的 AI Provider 协议无关。前端保留 `openapi-typescript` 生成类型,实际请求由 Axios 发出。
- API 函数优先使用生成的请求和响应类型,返回 DTO 或明确的业务结果;禁止用 `any` 取代已有契约,也不得把 Axios 类型扩散到功能层。
- DTO 到 ViewModel 的转换放在对应功能的 adapter 中;页面不得直接绑定后端 DTO,以免传输字段变化扩散到展示层。
- 全局服务器状态使用 TanStack Vue Query,本地界面偏好使用 Pinia或轻量组合式函数。
- Sass token集中管理颜色、间距、圆角、字号和断点。
- A 股默认红涨绿跌,但状态必须同时提供文字或形状,不能只依赖颜色。
- 图表必须标注单位、时间范围、数据日期和更新时间。
- 所有核心交互覆盖加载、空、部分数据、错误和过期状态。
## 10. 后端与任务规范
- 后端以业务模块为一级目录,模块内部按实际职责建立 `controllers`、`services`、`dto`、`domain`、`repositories`、`adapters`、`types`、`utils`;小模块不强制凑齐全部目录。
- Controller 只处理协议、边界参数和响应映射;Service 编排用例、事务与降级;Domain 保存纯业务规则和模型;Repository 描述持久化端口;Adapter 实现 MySQL、Redis、RocketMQ、外部数据源和 AI Provider 边界。
- DTO、领域模型与数据库实体必须分离。领域层不得依赖 NestJS、TypeORM、Redis 或 RocketMQ SDK;基础设施实现依赖领域端口。
- 禁止在应用级全局目录堆放所有 Controller 或 Service,禁止为目录外观创建空层或只做无意义转发的包装。跨模块代码只有在真实复用且所有者明确后才上移到 `server/libs`。
- 分层参考 RuoYi 的职责清晰性和成熟 NestJS 模块实践,不照搬 Java 目录,也不以分层数量衡量架构质量。
- API、Scheduler和Worker作为独立进程维护,不在请求期间临时抓取全市场数据。
- Scheduler 只决定何时投递;MessageBusAdapter 负责隔离客户端;RocketMQ 负责任务传输;Worker 负责执行;MySQL 负责事实记录;Redis 负责当前快照和短期状态。
- 消费者必须幂等,消息确认只能发生在持久化或可验证处理完成后。
- RocketMQ 可能重复投递;消费者不得把“收到一次”当作“只执行一次”,必须以 `idempotencyKey` 和业务唯一约束防重。
- 普通重试使用 RocketMQ 消费重试;延迟任务使用受版本支持的定时/延迟消息;超过服务端 Consumer Group 最大投递次数后进入死信,必须可查询、告警和人工重放。
- 业务代码只依赖项目定义的 `MessageBusAdapter` 和版本化事件契约,禁止直接依赖 RocketMQ SDK 类型;客户端、NameServer 或 Proxy 接入方式由基础设施适配层决定。
- 免费数据源通过 Adapter 统一为内部模型,上层不得依赖供应商原始字段。
## 11. MySQL 5.7.x 兼容规范
- 开发、测试和生产环境统一使用 MySQL 5.7.x,不设置最低补丁版本;禁止使用 `latest`、MySQL 5.6.x、8.x、MariaDB 或其他数据库代替兼容性验证。
- 创建数据库必须显式声明 `DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci`;建表与迁移脚本必须显式保持 `DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci`。
- ORM 和数据库驱动必须声明 `utf8mb4`,连接建立后验证会话、数据库和表的排序规则为 `utf8mb4_general_ci`,不得依赖服务器默认值。
- 文本列默认继承表级规则。列级改变字符集或排序规则必须由具体功能设计解释,并通过 ADR 审批。
- 禁止使用 MySQL 8.x 专属或在 5.7 行为不同的公用表表达式、递归 CTE、窗口函数、函数索引、不可见索引、`utf8mb4_0900_*` 排序规则和 JSON 增强能力。
- 不得依赖 `CHECK` 约束在 MySQL 8.x 的强制执行语义;MySQL 5.7.x 下的业务约束必须由边界校验、普通索引或可测试的写入逻辑保证。
- `utf8mb4_general_ci` 不区分大小写。证券代码、外部事件 ID、幂等键等身份字段必须规范化输入,或显式采用经设计批准的二进制比较与唯一键,不能误把默认比较当成大小写敏感。
- 索引长度按 MySQL 5.7.x 和 `utf8mb4` 最多四字节字符预算;超长标识使用受控长度、前缀索引或稳定摘要时,必须说明唯一性和碰撞处理。
- JSON 字段只能使用 MySQL 5.7.x 已支持并经过真实环境验证的能力,查询和索引不得建立在 8.x 特性上。
- 每份迁移脚本必须能够从上一版本基线在 MySQL 5.7.x 正向执行;禁止用直接修改共享数据库表代替迁移脚本。
- 代码 Review 必须检查服务端版本、字符集、排序规则、SQL/迁移兼容性、索引长度和字符串比较语义;任一不符合项按 Important 处理并阻断发布。
### Schema 基线规范
- 每个新应用版本开发前必须封存上一已发布版本的开发库 Schema;只能读取 `APP_ENV=development`、`a_share_analysis_dev` 和 MySQL 5.7.x,主机仅允许回环地址或固定开发白名单 `112.192.20.11`,禁止连接、探测或读取生产数据库。配置优先读取 Git 忽略的 `deploy/env/development/api.env.local`。
- 导出使用 Node.js 22.x 与 `mysql2` 连接 MySQL 5.7.x,读取固定 `information_schema` 元数据并执行 `SHOW CREATE`,完整保留表、索引、外键、视图、触发器、存储过程、函数和事件,不得包含任何表数据;本机不要求安装 MySQL Server、`mysql` 或 `mysqldump`。
- 规范化必须确定性删除导出时间、环境 `DEFINER` 和表选项中的当前 `AUTO_INCREMENT=<值>`,同时保留列定义的 `AUTO_INCREMENT` 属性和业务 SQL。
- 账号密码只存在于内存连接配置,不得进入命令参数、日志、异常、SQL、清单或 checksum 文件。
- `manifest.yaml`、`checksum.sha256` 和 `schema.sql` 的 SHA-256 必须一致;既有版本目录只允许内容完全一致的幂等验证,不允许覆盖。
- 导出前后必须复核对象目录和定义摘要,发现并发 DDL 或定义变化立即失败;MySQL 5.7.x 不提供 `VIEW_TABLE_USAGE` 时,只能回退读取 `information_schema.VIEWS.VIEW_DEFINITION` 解析视图依赖。
- MySQL 未启用时只创建状态为 `not_applicable` 的清单,不得创建空 `schema.sql`;启用但无对象时创建 format v3 的 `captured_empty` 清单和零对象计数,不伪造空 SQL;启用后的缺失基线必须阻断下一版本开发。既有 format v1/v2 基线必须继续只读验证,不得静默升级或重写。
- format v3 清单记录 Node exporter 和数据库驱动版本,不复用 v1/v2 的 `mysql_client_version` 与 `mysqldump_client_version` 字段。
## 12. 测试要求
- 功能和缺陷修复遵循测试先行:先看到测试因缺少行为而失败,再实现最小代码。
- 纯规则和指标计算使用单元测试,期望值必须手工推导。
- 数据源 Adapter 使用契约测试和固定样本。
- HTTP 与 RocketMQ 使用契约测试;消息测试必须覆盖 Topic、Tag、Group、序列化、重复投递、重试和死信边界。
- 关键页面使用 Playwright流程测试和视觉截图对比。
- 合并前必须通过类型检查、测试、构建和适用的视觉验证。
## 13. 安全要求
- 禁止提交 `.env`、API Key、密码、真实账号和生产数据。
- AI 密钥、数据源凭证和支付凭证仅存在服务端密钥管理中。
- SQL必须参数化;外部输入必须在边界处校验。
- 日志和异常报告必须脱敏。
- 每个功能和缺陷修复必须在设计中识别资产、数据、信任边界、攻击面、缓解措施和残余风险,在测试计划和 Review 中保存验证证据。
- 按适用性检查认证与授权、输入校验、SQL/命令/模板注入、XSS、CSRF、CORS、SSRF、限流、凭据、敏感数据、日志、错误、依赖供应链、数据保留和滥用场景。
- 外部数据源和 AI 还必须检查密钥隔离、上游不可信内容、提示词与事实边界、超时重试、成本控制和不可用降级。
- 不适用项必须说明不适用于什么、为什么以及适用边界;空白、`无`、`不适用` 或 `N/A` 不能作为安全评估证据。
## 14. 性能要求
- 每个功能必须说明延迟、吞吐、数据新鲜度或资源预算中适用的目标,并按风险选择验证强度。
- 后端评估数据量与算法复杂度、MySQL 查询/索引/N+1、Redis 用途/TTL/一致性/击穿、API 载荷与分页、Scheduler/Worker 并发/幂等/背压,以及外部数据源和 AI 的超时/重试/批处理/成本。
- 前端评估依赖与构建体积、渲染次数、长列表、图表数据量、交互响应和内存占用;不能只以开发环境主观感觉作为证据。
- 高风险路径必须提供 benchmark、profile 或负载测试;低频治理逻辑等不适用场景必须写明无需负载测试的原因和边界。
- 性能优化不得牺牲数据口径、安全、可观察性、异常恢复或 MySQL 5.7.x 兼容性;禁止无证据的预优化。
## 15. 代码 Review 要求
开发者完成自测不等于 Review 完成。审查者必须从功能 PRD、设计和 Git diff 出发,检查:
- 业务行为是否真正满足验收标准,是否存在遗漏分支。
- 类型、数据口径、缓存、消息、事务和异常恢复是否正确。
- 是否引入安全、性能、并发、幂等或数据一致性风险。
- 安全策略、性能目标和残余风险是否与实际实现一致,是否提供了风险相称的验证证据。
- GitNexus 开发前影响是否覆盖其他功能、模块和同步修改,开发后实际影响是否与计划一致。
- 前端是否遵守 Axios 单一封装和 API 分域,后端是否按业务模块内实际职责分层。
- 复用抽取是否基于已出现的重复,新增依赖是否完成用途、安全、许可证、体积/成本和退出评估。
- 测试是否能捕获真实回归,而非只验证 Mock 或实现细节。
- 中文注释是否解释关键原因、口径和限制,是否存在失真注释。
- 文件拆分是否便于常规阅读,是否出现过度抽象或巨型多职责文件。
Critical 和 Important 问题必须修复并复审。Minor 问题可以延期,但必须写明理由和后续功能编号。