笔记 04|注重实效的偏执:防御式编程与契约

一、核心观点

这一章的立场常被误解为"多写检查",其实它主张的是把不信任精确地放在正确的地方。

  1. 按合约设计(DBC)。每个例程都有前置条件、后置条件和不变式。合约明确了"谁负责什么":调用方负责满足前置条件,实现方负责兑现后置条件。这样责任可以划清,也便于生成测试用例。
  2. 死程序不会说谎。当检测到不可恢复的错误时,尽早崩溃比带着坏状态继续运行更安全。作者形象地说,让程序在错误状态下继续跑,等于让飞行员带着冒烟的发动机飞。断言正是用来"把不可能变成不可能"的工具。
  3. 用异常处理例外情况。异常是解决"意外"的,不是替代流程控制的分支。是否使用异常取决于错误能否被本地处理;能处理就处理,不能处理就传播。
  4. 资源配平。凡是"分配"就必须有对称的"释放",代码结构应让这一对称关系肉眼可见(RAII、using、try-with-resources、defer)。这是防止泄漏与死锁的根本方法。
  5. 不要赶时髦,要解耦。作者提醒警惕为技术而技术;同时指出解耦是防御的核心:最小化耦合、全局状态和通信渠道,让爆炸半径变小。
  6. 重构是日常,不是专项。先让它能跑,再让它跑对,最后让它跑快;重构的时机就藏在"需要修改"这个动作里。

二、原文摘录

"死程序不会说谎。"

"让调用者承担前置条件,让例程兑现后置条件。"

"如果你不能修复它,那就让它崩溃。"

三、个人思考

"早崩溃"在实践中常遭遇阻力:产品经理希望"别让用户看到错误页"。折中方案是在边界崩溃、在内部不猜测:内部接口快失败,用户侧用统一的兜底与监控承接。真正有害的是"吞掉异常然后返回 null",因为那会把错误变成难以追踪的空指针。

资源配平给我的启发更偏架构层面:检查两个服务之间的调用是否成对——请求有没有对应的超时、重试有没有上限、缓存有没有失效路径。凡是"配对缺失"的地方,迟早会以线上事故的形式付费。

四、行动清单

为关键公共方法补充前置/后置条件说明,并在实现里用断言表达。
全仓库搜索吞异常的写法,逐个改为记录日志并向上传播。
审计一处资源使用链(连接/文件/锁),确认每处分配都有对称释放。
把"先可用、再正确、再快速"写成提交评审清单。

posted @ 2026-11-04 23:01  CCidy  阅读(3)  评论(0)    收藏  举报