用途
cc-defensive-programming 是一个防御性编程技能,用于在代码中应用《Code Complete》的防御性编程规则。其目标是防止小故障累积成静默的、难以诊断的错误。技能围绕四项几乎总是必需的检查展开,例外情况需要明确说明理由:
- 断言中不含可执行代码:断言在生产构建中会被编译移除,其中的代码也随之消失。
- 禁止空 catch 块:空 catch 会静默吞掉缺陷,使其级联成更严重的故障。
- 外部输入在入口处验证:未验证的输入是安全漏洞和数据损坏的来源。
- 断言仅用于程序缺陷:可预期的运行时错误需要错误处理,而非断言(断言在生产中被禁用)。
主要能力
技能提供两种模式:
- CHECKER:针对代码执行防御性编程、断言和异常检查清单,逐项输出结果,格式为 | Item | Status | Evidence | Location |,状态取值为 VIOLATION(缺少验证、空 catch、有副作用的断言)、WARNING(处理不一致、缺少文档)或 PASS。
- APPLIER:生成断言放置、错误处理策略、隔离墙架构和验证实现。它会搜索代码库中现有的错误处理模式(异常、返回码或 Result 类型、自定义异常类、日志约定)并遵循该模式,因为错误处理的一致性正是使故障可调试的关键。
使用方式
技能通过读取检查清单和参考文件来执行。CHECKER 模式读取 checklists.md 并逐项审查代码;APPLIER 模式读取 pattern-reuse-gate.md 并生成实现。技能还引用共享阈值和信息隐藏理由,位于 cc-foundations.md。
关键规则
两条规则覆盖教科书式做法:
- “内部团队 API”仍属外部:任何跨越网络或进程边界的数据都是外部输入,即使来自本团队拥有的服务,也必须验证。
- 隔离墙减少冗余验证,但不替代纵深防御:在隔离墙内部可以假定数据已验证,但安全关键路径(认证、加密、PII)除外,这些路径需要再次验证,因为隔离墙验证本身也可能有缺陷。
外部输入的定义:任何无法证明由当前代码路径控制的数据,包括用户输入、文件、网络/API/数据库响应、环境变量以及来自任何其他服务的数据。
适用场景
技能适用于代码审查、错误处理架构设计和输入验证策略制定。它区分正确性与健壮性:正确性要求绝不返回不准确结果,宁可关闭也不产生错误答案(安全关键、金融、数据管道);健壮性要求即使结果有时不准确也继续运行(消费级应用、内部工具)。技能还提供隔离墙设计步骤、错误处理策略选项(返回中性值、替换下一个有效数据、返回先前答案、替换最接近的合法值、记录警告并继续、返回错误码、集中式错误处理器、显示错误消息、优雅关闭)以及现代错误传播模式(async/await、回调、Promise.all、事件处理器/React)的处理建议。
限制
技能明确列出不适用的情况:无副作用的纯函数(但仍需在系统边界验证输入);原型/探索代码,在确定错误策略前有时间限制;测试代码,测试替身有意违反生产模式;性能关键的内层循环,其中断言开销经分析超过 5%。安全关键代码(认证、授权、加密操作、PII 处理)无论上述情况如何都永不豁免。当条件确实不明确(“这是缺陷还是预期?”)时,应与领域专家澄清需求,而非猜测。