37 听从蜥蜴脑
把迟疑、烦躁和阻塞当作潜意识发现不一致的信号,暂停并用小实验显化未知。
学习目标
- 能把迟疑、烦躁或绕路的感觉转成一个关于设计或环境的可检验假设
- 能用最小实验、边界样本和短暂休息区分结构阻力、知识缺口与疲劳
- 能保存预测、首个差异和回退动作,让别人可以在相同条件下复核结论
直觉是输入,不是判决
本页依据 David Thomas、Andrew Hunt《程序员修炼之道:通向务实的最高境界(第2版)》,云风译,电子工业出版社,2020 年 4 月,ISBN 9787121384356 的公开中文目录,独立重构 37 听从蜥蜴脑。正文、代码、图示、实验和练习都是本课程重新设计的教学材料,不复制原书正文、插图或答案。
“听从蜥蜴脑”不是把每次不舒服都当作真理,而是承认熟悉代码的人常常先感觉到不一致,再找到能说清它的词。一个函数让你不愿修改、一个接口需要绕路调用、一次简单需求却要触碰五个模块,这些都是值得记录的信号。信号出现后要暂停,把它转成假设,再用成本很小的实验验证;实验失败时,失败本身也要成为证据。
三个常见误区先停下来
五步反馈回路
<Term def="在编码过程中出现的迟疑、绕路、重复或无法解释的紧张感;它提示需要调查,不直接决定结论。">阻力信号</Term>要进入一个短回路,而不是停留在“我觉得不对”。回路的每个节点都要有输入、输出和拒绝条件:
- 感知:写下具体动作和感觉,不写人格判断。
- 暂停:停止扩大改动,保存当前状态和最近一次可运行结果。
- 假设:列出两个可能解释,以及能区分它们的最小观察。
- 实验:只改变一个条件,记录预测、实际结果和首个差异。
- 解释:选择修复、继续调查或休息,并把未覆盖范围写入记录。
这条回路把“听从”限制在可复核范围内。若一个实验没有改变任何可观察结果,不能据此宣布设计正确;它可能只是没有触达真正的阻力。若实验产生差异,先停在首个差异处,不要为了得到熟悉的最终结果继续修改后续节点。
识别蜥蜴脑在说什么
代码阻力
当你需要复制一段相同的转换、先调用一个看似无关的初始化函数,或必须打开多个文件才能确认一个字段含义,阻力可能指向责任边界或名称问题。记录“我做了什么、哪一步开始绕路、期待什么结果”,比写“代码很乱”更有用。
知识阻力
有些不安来自尚未理解的协议、数据格式或运行时规则。此时最小实验可以是读一条官方规范、构造一个三行输入,或让编译器暴露类型边界。知识缺口被补上后,若同一绕路仍存在,信号才更可能指向设计结构。
环境阻力
时间、内存、网络、权限和工具版本都可能使一个本来合理的方案看起来不可靠。把环境条件写进记录,避免把暂时的网络错误或过期依赖误判为业务设计缺陷。环境实验必须有超时和停止条件,不能无限重试。
37 与提示 61:倾听,但要能反驳
本单元对应中文目录的 37 听从蜥蜴脑 和 提示 61:倾听你内心的蜥蜴。提示的教学化解释是:直觉可以帮助选择调查入口,但不能替代输入、边界、反例和结果。一个合格的复核记录应回答:
- 具体是什么对象让你停顿?
- 你认为哪两个原因最可能?
- 哪个最小实验能区分它们?
- 结果在哪个节点与预测不同?
- 你选择修复、继续调查还是休息,为什么?
例如,支付接口的调用顺序让你不安。假设一是“接口依赖隐含初始化”,假设二是“测试夹具没有表达真实权限”。最小实验可以分别在干净进程中调用接口,并用普通用户身份跑一条端到端请求。实验只要能让两个解释产生不同结果,就比重写整个支付模块更有信息量。
认知卸载与休息窗口
<Term def="把当前假设、输入、观察点和工作区状态写到可回看的工件中,使离开一段时间后仍能准确恢复。">认知卸载</Term>不是写长日志,而是保存下一次行动所需的最小信息:当前提交、失败命令、假设、预测、实际首差和下一步。这样休息不会把问题重新变成记忆游戏。
<Term def="有明确开始和恢复动作的短暂离开,用于降低注意力噪声并验证问题是否依赖当前疲劳状态。">休息窗口</Term>也应有验收条件。回来后先重读记录,在不改变输入的情况下重跑失败实验;若结果消失,记录“疲劳可能参与”,但不要因此断言设计没有问题。若结果重现,继续调查结构或环境原因。
练习实验:最小反例比大改动更快
Interactive lab
选择样本,决定下一步
输入证据
空输入触发超时阈值,错误信息可被调用者理解。
实际首差
边界节点:结果应明确拒绝,而不是继续传播空状态。
恢复动作
把阈值写成测试,补一个能重现边界的输入。
先写预测再点击样本。如果结果与感觉不一致,保留差异并缩小假设,不要让最终结果替你解释过程。
1. 写下阻力对象与预测
选择一个真实函数或流程,写出“我在哪一步开始绕路”“我期待看到什么”“什么结果会推翻这个判断”。不要使用“质量差”“很复杂”这类无法观察的形容词。
正常、边界与单一故障证据
| 样本 | 唯一变化 | 预期判定 | 必存证据 |
|---|---|---|---|
| 正常 | 已知输入与稳定依赖 | 回路闭合,解释与结果一致 | 预测、输出和提交哈希 |
| 边界 | 恰好超时、空输入或权限阈值 | 明确接受或拒绝,不伪造成功 | 阈值来源与拒绝原因 |
| 单一故障 | 一个环境或知识条件失效 | 在首个差异处停下 | 失败输入、首差与回退 |
反例不是“我不同意”,而是在相同前提下产生相反结果,或证明前提不适用于目标环境。发现反例后缩小结论的适用范围,更新假设并重放旧样本;不能删除失败记录来保护原来的故事。
独立复核清单
复核者只接收输入身份、环境版本、验收问题和边界,不接收原作者期待的答案。复核前先预测五个节点,运行最小实验,再比较首个差异。证据包至少包含:
- 阻力对象与两个候选解释;
- 当前提交、工具版本和输入摘要;
- 预测、实际输出、首个差异与错误信息;
- 选择修复、继续调查或休息的理由;
- 回退动作、回归结果和未覆盖条件。
截图和覆盖率可以辅助定位,却不能代替可重放的输入。能说“我感觉好多了”不等于能证明设计问题已经消失;必须让复核者在相同条件下得到同一结论。
术语表
名词解释
本章出现的专业名词,用大白话再讲一遍。
- 阻力信号
编码时出现的迟疑、绕路、重复或无法解释的紧张感。
- 认知卸载
把假设、输入、观察点和工作区状态写成可回看的最小工件。
- 最小实验
只改变一个条件、能区分两个解释并具有停止条件的验证。
- 首个差异
预测和实际结果第一次不一致的可观察节点。
- 休息窗口
带有保存和恢复动作的短暂离开,用来降低注意力噪声并重放实验。
练习
练习
问题 1: 你发现一个函数必须先被另一个模块调用才不会报错。如何把直觉转成最小实验?
问题 2: 同一测试在连续工作数小时后失败,第二天却通过。你会如何避免把它误判成“只是累了”?
问题 3: 一个大原型同时改变了缓存、数据库和接口,你如何重新获得因果证据?
本单元回顾
听从蜥蜴脑不是服从每个情绪,而是把阻力当作调查入口:记录对象,暂停扩大改动,提出竞争假设,用最小实验找到首个差异,再选择修复、继续调查或休息。最终能否复核,取决于输入、预测、失败记录和回退动作是否仍在,而不是取决于这次编码是否感觉顺利。