# 编码规范 创建人员:Codex 文件职责:定义通用编码注意事项、编码流程、验收方式、问题修复原则,适用于管理体系下的多个项目。 管理规范/模板:../../管理系统说明.md;../../全局规范.md;开发环境创建指南.md;开发审计规范.md;非临时文件应能追溯到事项、需求、方案、验收结果。 引用文件:../../管理系统说明.md;../../全局规范.md;开发环境创建指南.md;开发审计规范.md;编码方案范本.md;AI管理体系建议.md;旧项目开发规范已去项目化抽象。 记录方式:全局编码规范文档;编码流程、方案要求、测试验收或问题修复口径变化时更新。 统一依赖:本规范必须同时遵守 `../../全局规范.md` 和 `../project-doc/项目规范.md`;项目本地编码规范可补充流程,但不得违反全局规范、全局项目规范和本体系硬约束。 ## 1. 目标 本规范用于约束 AI 或人工在项目中编写、修改、验收代码的全过程。 核心目标: 1. 先明确目标和接口,再写代码。 2. 代码变更必须可追踪、可复现、可验收。 3. 多模块流程要避免散修、重复逻辑、隐式依赖和难以重跑。 4. 数据校验要保护主流程,但不能层层加码到拖垮主流程。 5. 发现问题时必须区分需求问题、代码问题、数据问题、流程问题。 ## 2. 适用范围 适用于管理体系下所有项目的: 1. 新模块开发。 2. 多模块流程开发。 3. 旧代码重构。 4. Bug 修复。 5. 数据处理脚本。 6. 实验、回测、校验、审计辅助工具。 小脚本可以简化流程,但不能跳过输入输出说明、基本自检和结果记录。 ### 2.1 开发体系绑定口径 开发体系默认随项目创建,但不单独承载业务目标,必须绑定目标体系或目标事项。 开发产物按目标体系分账: 1. 代码放在 `dev/-dev/`。 2. 测试放在 `dev/-dev/test/`。 3. 目标相关代码文档、测试说明和重型编码方案附件放在 `dev-doc/-doc/`。 4. 开发事项总纲、计划、执行日志和问题记录默认放在 `dev-doc/` 根级账本,不在目标目录复制第二套。 5. 审计报告入口按目标体系分账:需求开发、项目工具开发等独立开发事项写 `dev-doc/开发审计报告.md`;实验开发写 `exp-doc/实验审计报告.md`;案例分析开发写 `ana-doc/案例审计报告.md`。 常见映射: 1. 需求 / 需求开发:`dev/pro-dev/`、`dev/pro-dev/test/`、`dev-doc/pro-doc/`。 2. 实验开发:`dev/exp-dev/`、`dev/exp-dev/test/`、`dev-doc/exp-doc/`。 3. 案例分析开发:`dev/ana-dev/`、`dev/ana-dev/test/`、`dev-doc/ana-doc/`。 不得把所有代码、测试或开发文档直接堆到 `dev/` 或 `dev-doc/` 根目录。 ### 2.2 本地编码规范最低内容 每个项目的根级 `dev-doc/编码规范.md` 不能只写“引用 common 规范”。目标开发工作区 `dev-doc/-doc/` 不再创建第二份编码规范,只放目标代码文档和方案附件。 本地编码规范至少要包含: 1. common 编码规范路径。 2. 本地编码规范适用范围。 3. 本地开发目录口径。 4. 核心开发文档作用说明。 5. 如有本地补充规则,说明不得削弱 common 硬约束。 核心开发文档作用说明至少覆盖: | 文档 | 作用 | |---|---| | `目录导读.md` | 说明开发目录结构、代码入口、测试入口、当前事项和审计入口 | | `编码规范.md` | 记录本地编码规范和 common 规范引用 | | `开发审计规范.md` | 记录本地开发审计规范和 common 审计规范引用 | | `开发事项总纲.md` | 记录开发事项背景、目标、边界、状态和结论 | | `开发事项计划.md` | 记录开发计划、步骤、输入输出、验收方式和审计入口 | | `开发方案/` | 重型开发时按事项创建具体编码方案文件,例如 `开发方案/.md`;轻量开发不创建 | | `开发执行日志.md` | 记录编码、测试、自检、中间结果、异常和偏离 | | `开发审计报告.md` | 记录方案审核、实现审核、测试验收和复审结论 | | `开发问题记录.md` | 记录非审计来源开发问题;审计问题只做跨轮索引 | ## 3. 总原则 ### 3.1 需求先行 编码前必须先明确: 1. 要解决什么问题。 2. 输入是什么。 3. 输出是什么。 4. 成功标准是什么。 5. 哪些行为不允许发生。 如果需求中的字段、接口、边界、验收标准不清楚,不应靠代码猜。应先记录为需求问题,再修需求或补说明。 ### 3.2 编码方案先行 以下情况必须先写代码编写方案,再写代码: 1. 新增整体系统模块。 2. 改动超过一个模块。 3. 涉及长流程、批处理、回测、发布、归档、审计。 4. 涉及公共字段、公共表、公共工具函数。 5. 涉及重跑、缓存、并发、断点续跑。 6. 存在明确性能瓶颈或性能风险。 ### 3.3 真问题优先 审查代码时要优先找会影响结果、阻断流程、污染数据、造成不可追踪的问题。 不应把命名小差异、文档措辞不优雅、非关键诊断项缺失,升级成主流程阻断问题。 ### 3.4 公共能力复用 多个模块都需要的能力,应抽成公共函数、公共类或公共 helper。 典型公共能力包括: 1. 路径解析。 2. manifest 读写。 3. receipt 读写。 4. fingerprint 计算。 5. schema 校验。 6. gate 汇总。 7. CSV/Parquet 分块读写。 8. 错误码和状态码归一。 禁止在多个模块里复制粘贴同一套核心判断逻辑。 ### 3.5 可追溯和可复现 重要运行必须能回答: 1. 用了哪些输入。 2. 用了哪个配置。 3. 运行了哪个代码版本。 4. 产出了哪些文件。 5. 哪些检查通过,哪些检查失败。 6. 如果失败,停在哪一步,为什么失败。 ## 4. 编码前流程 编码前按以下顺序执行: 1. 确认事项编号、任务目标、责任模块。 2. 阅读相关需求文档、需求方案、架构文档、模块说明文档、核心流程文档、流程图、接口文档;没有的上游文档要说明“不适用”。 3. 判断本次是需求问题、代码问题、数据问题,还是流程问题。 4. 明确改动范围,列出会被影响的模块和产物。 5. 如属于多模块或长流程改动,先写代码编写方案。 6. 明确验收方式,包括最小样本、边界样本、失败样本、全量样本。 7. 再开始编码。 如果本次是需求体系交付到开发的事项,还必须先读项目本地 `pro-doc/需求规范.md`、`pro-doc/需求规范.md`,以及需求文档引用的需求方案、架构文档、模块说明文档、核心流程文档。若这些上游需求文档缺失或互相冲突,应按需求问题退回,不得靠代码补口径。 如果本次是实验开发、案例分析开发或项目工具开发,也必须读取对应目标体系规范和事项账本;开发规范只约束怎么写代码,不替代目标体系的业务流程。 ## 5. 三类编码流程 不同规模的代码任务按三类处理,不要把所有任务都套进重流程。 ### 5.1 无需求文档的轻量实现 适用范围: 1. 一次性辅助脚本。 2. 小型数据检查脚本。 3. 简单文件整理、格式转换、压缩、检索、统计。 4. 不改核心业务流程、不产生正式主表、不影响长期接口的小改动。 这类任务通常不需要先写需求文档,也不需要写代码编写方案。 需求体系正式交付到开发的事项,默认不适用“无需求文档的轻量实现”。如果需求侧只给了口头要求或草案,应先回到需求流程形成可审计需求,再进入开发。 执行流程: 1. 明确用户要的结果、输入路径、输出路径。 2. 说明关键假设,例如编码、文件格式、输出位置。 3. 直接实现,代码保持小而清晰。 4. 自测能运行,检查输出是否存在、行数或文件数是否合理。 5. 如果脚本会复用,补最小使用说明。 6. 如果执行中发现任务影响核心流程、正式产物、公共字段或多个模块,立即升级为“有需求文档的轻量实现”或“重型实现”。 最低交付: 1. 代码文件。 2. 运行方式。 3. 输出位置。 4. 简短自测结果。 ### 5.2 有需求文档的轻量实现 适用范围: 1. 已有需求文档。 2. 改动边界清楚。 3. 单模块或少量局部改动。 4. 不涉及长链路调度。 5. 不新增公共核心字段或公共基础设施。 6. 不涉及复杂重跑、缓存、并发、发布流程。 这类任务可以不写代码编写方案。 执行流程: 1. 先检查需求文档是否足够清楚,重点看目标、输入、输出、字段、边界、验收标准。 2. 如果需求不清,先记录需求问题,不要靠代码猜。 3. 需求没问题后再写代码。 4. 写完后先做基础自测,例如语法、导入、最小样本、关键输出。 5. 自检:逐条对比需求文档和代码实现,确认是否有字段缺失、口径偏差、流程绕过、产物不一致。 6. 修掉自检发现的问题。 7. 输出验收结论,说明跑了什么测试、结果是什么、还有什么限制。 最低交付: 1. 代码变更说明。 2. 对应需求文档。 3. 自测命令和结果。 4. 需求-代码自检结论。 5. 未解决问题或限制。 ### 5.3 有需求文档的重型实现 适用范围: 1. 新增整体系统模块。 2. 改动多个模块或多个阶段。 3. 涉及核心主流程、正式数据链路、长流程调度。 4. 涉及公共模块、公共字段、公共表、公共 gate、公共 helper。 5. 涉及断点续跑、缓存、并发、子进程、全量批处理。 6. 存在明确性能瓶颈或失败后代价较高。 这类任务必须在需求文档没有明显问题之后,先写代码编写方案,再写代码。 执行流程: 1. 先审需求文档,确认目标、主链、接口、字段、产物、验收标准没有明显冲突。 2. 写代码编写方案,说明模块边界、公共能力、验收、重跑、风险和协作方式。 3. 代码编写方案必须交给审核员审核。 4. 审核员确认方案没有明显流程、接口、职责、验收、重跑、公共模块问题后,才允许进入代码编写阶段。 5. 如果审核员发现方案问题,必须先修方案,不能边写代码边补方案。 6. 按审核通过的方案拆分实现,优先实现公共入口和关键主路径。 7. 每个模块完成后做模块自测。 8. 多模块串联后做链路 smoke。 9. 自检:按需求文档和编码方案逐项对照代码、产物、日志、测试。 10. 修复自检发现的真实问题。 11. 生成最终验收结论,说明是否可以进入全量、发布或下一阶段。 最低交付: 1. 需求文档。 2. 代码编写方案。 3. 代码变更说明。 4. 模块自测结果。 5. 链路自测结果。 6. 需求-代码-方案一致性自检结论。 7. 重跑或恢复说明。 ## 6. 代码编写方案必须包含的内容 本节只适用于“有需求文档的重型实现”。轻量任务不强制写完整代码编写方案。 默认开发体系不创建空的 `编码方案.md`。重型开发发生时,按开发事项创建具体编码方案文件,例如 `dev-doc/开发方案/.md` 或 `dev-doc/-doc/开发方案/.md`。写方案时必须满足本节要求;如需要参考写法,可以看 `编码方案范本.md`,但不得把范本机械复制成无实际内容的方案。 代码编写方案至少包含以下内容。 代码编写方案必须经过审核员审核通过后,才能进入代码编写阶段。未审核、审核不通过、或审核意见未处理完成时,不得开始实现。 ### 6.1 模块和接口 必须说明: 1. 本次涉及哪些模块。 2. 每个模块的职责是什么。 3. 模块之间如何交互。 4. 每个模块的输入表、输出表、关键字段、主键、枚举、错误码。 5. 哪些字段是正式字段,哪些字段只是兼容 alias 或诊断字段。 ### 6.2 公共模块和公共功能 必须识别多个模块共用的逻辑,并说明: 1. 是否需要抽公共函数或公共类。 2. 公共模块放在哪里。 3. 哪些调用方必须使用这个公共入口。 4. 哪些旧逻辑需要迁移或废弃。 5. 如何防止调用方绕过公共入口。 ### 6.3 性能风险和优化方案 性能优化不是代码编写方案的必选项。 如果本次改动存在明显性能风险,应提前识别: 1. 大文件读写。 2. 大表 join。 3. 全量排序。 4. 大 JSON 字段展开。 5. 多进程或子进程。 6. 重复计算。 7. 可能长时间无日志的步骤。 如果存在明显性能风险,方案中要写明优化策略,例如分块、索引、缓存、流式写出、原子落盘、进度日志、断点续跑。 如果没有明显性能风险,可以只写“本次无明确性能瓶颈,暂不设计专项优化”,不要为了形式强行增加性能优化章节。 ### 6.4 验收方案 必须写清: 1. 单模块怎么验收。 2. 多模块链路怎么验收。 3. 需要哪些正例。 4. 需要哪些反例。 5. 哪些 gate 是主流程必过。 6. 哪些检查只是外部诊断,不得阻断主流程。 ### 6.5 扩展性设计 对可能频繁变化的部分,要明确扩展点: 1. 规则配置。 2. 枚举扩展。 3. 字段扩展。 4. 数据源扩展。 5. 策略参数扩展。 6. 输出格式扩展。 不得把频繁变化的业务规则散落在多个硬编码 if-else 中。 ### 6.6 统一数据结构 贯穿全流程的字段、ID、状态、枚举应尽量统一。 如果必须保留旧字段 alias,必须明确: 1. canonical 字段是什么。 2. legacy alias 是什么。 3. 二者是否必须逐行一致。 4. 下游应读取哪个字段。 5. 什么时候可以移除 alias。 ### 6.7 重跑和恢复 长流程必须写清重跑原则: 1. 什么时候从原始数据重跑。 2. 什么时候可以从中间快照重跑。 3. 哪些产物可以复用。 4. 复用前必须校验哪些 fingerprint、schema、row_count、config。 5. 失败产物如何标记,避免被误用。 不能只靠“文件存在”判断可复用。 ### 6.8 高风险点 必须列出容易出错的关键点,例如: 1. 未来函数。 2. 主键不唯一。 3. 多模块字段名不一致。 4. 分组键和最终实体键不一致。 5. 中间产物被误当正式产物。 6. 诊断模块反向覆盖主流程结果。 7. 半成品文件被当作完成文件。 8. 同一逻辑在多个模块散修。 ## 7. 编码规则 ### 7.1 路径和配置 1. 不得硬编码个人机器绝对路径。 2. 路径应来自配置、参数或统一路径工具。 3. 输出目录必须可配置。 4. 重要运行要保存配置快照。 5. 临时文件、正式文件、失败文件要有清晰命名。 ### 7.2 输入处理 1. 必需输入不存在时必须 fail-fast。 2. 输入 schema 不匹配时必须报清楚缺失字段。 3. 可选字段缺失时可以置空,但必须记录。 4. 不得伪造缺失输入。 5. 不得用测试数据冒充正式输入。 ### 7.3 输出处理 1. 重要输出必须写 manifest。 2. 大文件或关键文件应先写临时文件,完成后原子 rename。 3. 中途失败不得留下看似完成的正式文件。 4. 输出 row_count、key_count、schema 应可审计。 5. 输出应尽量可重复生成。 ### 7.4 数据安全和时间安全 1. 涉及时间序列、时序决策、预测、回测时,必须明确 as-of 时间。 2. 不能用未来数据生成过去时点的信号。 3. 若实验阶段刻意允许使用未来信息,必须在实验说明中明确标注,不能和实盘口径混用。 4. 买卖、判断、持仓、退出等操作必须能追溯到当时可见的信息。 ### 7.5 错误处理 1. 合同错误必须显式失败。 2. 不得 silent pass。 3. 不得用 fallback 掩盖主路径错误。 4. 自动重试只能用于明确的临时 I/O 或网络问题。 5. 失败原因要能定位到模块、输入、字段、规则。 ### 7.6 代码组织 1. 函数应短小,职责单一。 2. 复杂规则应抽成命名函数。 3. 公共判断应集中到公共模块。 4. 魔法数字必须有常量名或配置名。 5. 代码命名遵循项目语言惯例。 6. Python 默认使用 snake_case 函数和变量、PascalCase 类名、UPPER_SNAKE_CASE 常量。 ## 8. 日志和证据链 重要流程建议输出: 1. `run_meta.yaml` 或 `run_meta.json` 2. `config_snapshot.yaml` 或 `config_snapshot.json` 3. `runtime.log` 4. `output_manifest.csv` 5. `selfcheck.md` 6. `evidence_chain.md` 7. 关键中间产物 日志至少包含: 1. run_id 2. matter_id 3. step_id 4. module 5. stage 6. input_path 7. output_path 8. input_row_count 9. output_row_count 10. elapsed_seconds 11. status 12. error_code 13. error_message 长流程必须有进度日志,不得长时间无输出导致无法判断是正常运行还是卡死。 ## 9. 数据校验原则 ### 9.1 主流程只保留轻量核心校验 主流程中的校验只应覆盖核心合同: 1. 必需输入存在。 2. 必需字段存在。 3. 主键或关键键合法。 4. 行数明显合理。 5. 上下游 handoff 可读。 6. 核心状态不违反硬合同。 主流程不应被过重的外围诊断项卡死。 ### 9.2 重型数据校验放到只读 helper 复杂数据校验应做成外部只读 helper,而不是塞进主流程。 helper 只允许: 1. 读取已落盘产物。 2. 输出 summary/report/readout。 3. 标记诊断问题。 4. 给人工或后续修复提供证据。 helper 不允许: 1. 改写业务主表。 2. 改写 stage output。 3. 改写 root manifest。 4. 改写 final manifest。 5. 改写 fingerprint receipt。 6. 反向覆盖主流程成功或失败状态。 ### 9.3 不做一堆 gate 压垮模块 不要为了“看起来严谨”无限增加 gate。 只有会影响主流程正确性、数据安全、结果可信度的检查,才应成为主流程硬 gate。 发布级、审计级、归档级、诊断级检查,应放在对应层级,不得混进样本、smoke、10k、50k 的核心执行链。 ## 10. 测试和验收 ### 10.1 分层测试 推荐分层: 1. L0:语法、导入、静态检查。 2. L1:单模块最小样本。 3. L2:多模块 smoke 链路。 4. L3:边界样本和回归样本。 5. L4:全量或准全量验收。 不得直接用全量跑批替代前置验证。 ### 10.2 验收样本 验收至少考虑: 1. 正常样本。 2. 边界样本。 3. 缺字段样本。 4. 空结果样本。 5. 多候选或多状态样本。 6. 历史上出过 bug 的回归样本。 ### 10.3 通过标准 通过标准必须明确: 1. 哪些文件必须存在。 2. 哪些行数必须一致。 3. 哪些 key 必须唯一。 4. 哪些字段允许为空。 5. 哪些状态允许出现。 6. 哪些错误必须 fail-fast。 ## 11. Bug 修复规则 ### 11.1 先分类 发现问题后先分类: 1. 需求问题:需求模糊、冲突、缺字段、边界不清。 2. 代码问题:实现与需求不符。 3. 数据问题:输入数据缺失、错乱、污染。 4. 流程问题:顺序、重跑、验收、归档不合理。 5. 性能问题:结果正确但运行不可接受。 需求问题不能只改代码绕过去,必须先修需求或补合同。 ### 11.2 修主路径 反复出现的问题,优先修公共入口和主路径,不要只修报错点。 如果多个模块都有同类问题,应: 1. 抽公共函数。 2. 统一调用方。 3. 补公共测试。 4. 删除或废弃散落逻辑。 5. 用回归样本验证全链路。 ### 11.3 关闭问题标准 问题关闭前必须满足: 1. 能复现原问题,或能解释为什么无法复现。 2. 有对应修复。 3. 有最小验证。 4. 有回归验证。 5. 相关问题文档已更新。 6. 若是需求问题,已标注为需求问题并同步给需求负责人。 ## 12. 多 AI 协作规则 多 AI 并行时必须遵守: 1. 先冻结接口,再并行实现。 2. 每个 AI 明确负责文件和模块。 3. 不同 AI 不应同时修改同一核心文件,除非有明确合并人。 4. 公共字段和公共工具只能由一个 owner 统一修改。 5. 每个 AI 都要记录修改内容、验证结果、未解决问题。 6. 审核 AI 只记录真问题,不把边角料升级成阻断。 ## 13. 性能规范 性能优化要遵循: 1. 先定位瓶颈,再优化。 2. 优先减少重复 I/O、重复解析、重复 join、重复全量排序。 3. 大表优先考虑分块、索引、缓存、投影列、sidecar 分账。 4. 长流程必须可观察进度。 5. 不为了性能破坏数据合同。 6. 性能优化必须证明结果不漂移,或明确说明允许漂移的范围和原因。 ## 14. 重跑和断点续跑 长流程必须设计重跑策略: 1. 原始数据重跑。 2. 中间快照重跑。 3. 指定阶段续跑。 4. 失败阶段重跑。 5. 只读审计重跑。 复用中间产物时必须校验: 1. 输入 fingerprint。 2. 配置 fingerprint。 3. 代码版本或规则版本。 4. schema。 5. row_count。 6. key_count。 7. completion marker。 半成品、失败包、空壳文件不得被当作可复用产物。 ## 15. 禁止事项 禁止: 1. 没有需求或目标就直接写代码。 2. 需求不清时用代码猜。 3. 用假数据、默认值、空字符串掩盖缺失输入。 4. 用未来数据生成历史信号。 5. 把诊断 helper 变成主流程阻断器。 6. 重复复制公共逻辑到多个模块。 7. 只修局部报错,不修公共入口。 8. 只看父进程不看子进程就判断卡死。 9. 只靠文件存在判断流程完成。 10. 不记录验证结果就关闭问题。 ## 16. 最低交付清单 正式交付代码至少应包含: 1. 代码变更说明。 2. 影响范围说明。 3. 运行命令或入口。 4. 输入输出说明。 5. 验证命令和结果。 6. 已知限制。 7. 是否涉及需求问题。 8. 是否涉及性能风险。 9. 是否需要后续重跑。 一句话原则:先把目标、接口、数据、验收、重跑讲清楚,再写代码;代码要解决真问题,不要用过重校验拖垮主流程。