name: 严谨编码 description: 在任何实现之前应用严谨的编码标准。适用于编写、实现或审查代码时。强制执行实现前的思考、错误处理、状态管理、命名和实现后验证。
严谨编码标准
实现前检查清单(强制)
在编写任何代码之前,请说明:
- 假设:要使此代码正常工作,哪些条件必须为真?
- 边界情况:哪些输入/状态可能导致此代码崩溃?
- 正确性标准:我们如何知道它是正确的?
- 故障模式:当出现问题时会发生什么?
在说明假设之前不要编写代码。 不要声称未经验证的正确性。 不要只处理正常路径。
错误处理
规则
- 永远不要使用空的 catch 块
- 显式处理异步拒绝(try/catch 或 .catch)
- 处理网络故障(超时、断开连接、DNS)
- 错误应附带上下文传播,而不是被吞没
- 区分可恢复错误和致命错误
模式
// 错误:吞没错误
try { riskyOp() } catch (e) {}
// 错误:丢失上下文
try { riskyOp() } catch (e) { throw new Error("failed") }
// 正确:保留上下文
try { riskyOp() } catch (e) { throw new Error(`riskyOp failed: ${e.message}`, { cause: e }) }
状态管理
- 最小化可变状态 — 优先使用派生值
- 明确所有权:谁创建、谁修改、谁读取?
- 记录状态转换(有效转换、无效转换)
- 对多步突变使用事务语义(全有或全无)
- 错误时永远不要留下部分更新的状态
输入验证
- 在系统边界处验证(用户输入、API 响应、外部数据)
- 信任内部代码 — 不要在自己的模块之间过度验证
- 在可能的情况下,优先使用类型收窄而不是运行时断言
- 在边界处快速失败并给出清晰的错误消息
命名
- 意图揭示:名称描述是什么,而不是如何做
- 布尔前缀:
is、has、can、should、did - 复数集合:
users而不是userList,items而不是itemArray - 函数的动作动词:
fetchUser、validateInput、calculateTotal - 除非普遍理解,否则不使用缩写(id、url、api)
代码结构
- 单一职责:一个函数只做一件事
- 最多 3 层嵌套:如果更深,提取辅助函数
- 保护子句:对无效状态提前返回
- 最大函数长度:约 30 行(指导原则,非教条)
- 参数数量:3 个或更少;超过则使用选项对象
实现后验证
编写代码后,验证:
- 你能解释每一行以及为什么需要它吗?
- 空输入、null、undefined 会发生什么?
- 并发访问时会发生什么?
- 网络断开时会发生什么?
- 边界值(0、MAX_INT、空字符串)会发生什么?
- 是否测试或至少考虑了所有错误路径?
- 这是否符合实现前陈述的假设?
在什么条件下这能工作?请明确说明。