跳到主要内容

五种编程活动与被打断的代价 — 你的时间去了哪

这一章讲三件事: 「写代码」这个词掩盖了五种认知上完全不同的活;打断为什么值一刻钟; 以及三种把伤害压到最低的自救办法。 它把全书的方法按「活动」重新装箱:方法没错,但要看你此刻在干哪种活。

1. 全景:五种活动,三种记忆

来自一套研究「符号系统」(编程语言这类表达思想的体系)的框架,它把语言对大脑的影响拆成一个个评估侧面,每个侧面叫维度(dimension,可以理解成体检项);这套框架通称符号认知维度,提出者是 Green、Blackwell 与 Petre,第 13 章还会遇到它。它把程序设计分成五种活动1。每种活动压的记忆不同,所以对症的辅助手段也不同:

活动在干什么压哪套记忆对症的辅助
搜索找特定信息:改哪、调用在哪短时记忆——要记着「我在找什么、找过哪了」笔记:把搜索状态写下来
理解弄懂不熟悉的代码工作记忆——全程靠推理建模型、重构(第 04~06 章全套)
转写方案已定,照方写码长时记忆——语法要信手拈来抽认卡、自动化(第 03、11 章)
递增加新功能:搜索+理解+转写三种全压注释和重构
探索用代码试想法,边写边想三种全压,工作记忆最重随手记设计方向

2

两个实务推论。**其一:**递增任务(最常见的「加个功能」)对新手最难,因为五种里它一下压三种记忆——给新人分任务时尽量拆开:先纯搜索、再纯理解、最后才转写3。**其二:**调试不在五单里,因为它是五种活动的叠加——先搜索、再理解、再探索、最后转写修复4

2. 打断的价目表

打断贵,但贵多少,有数5:

  • 20 世纪 90 年代 van Solingen 的观察:程序员经常被打断,每次持续 15~20 分钟;大约两成工作时间用于应付干扰;
  • 帕宁(Parnin)的 85 人、10000 次会话记录:程序员平均每天只有两小时不被打扰;微软的调查里,62% 的程序员认为被打断后找回状态「相当不易」;
  • 找回状态的代价:约一刻钟;如果打断发生在改方法改到一半,只有 10% 的人能一分钟内回来。

脑成像补了个细节:中川团队测出程序理解的认知负荷峰值出现在任务中段——理解活动存在预热(先热身、搭模型的阶段)期和冷却期,最难的部分在两者之间6。这意味着打断落在任务中段时,拆掉的是最贵的部分。

3. 主走查:一次五分钟的打断,大脑里丢了什么

场景:你在修一个 bug,改到第三版,手机进来一个五分钟的电话(人物与代码为演示场景,认知机制全部有出处)7。逐层盘点丢掉了什么:

打断前你手里有什么:
短时记忆:「变量 retryCount 现在是 3,下一版要验证边界」 ← 30 秒内蒸发
工作记忆:这个 bug 的心智模型——「应该是超时后没重置
计数器,所以第二次请求带上了旧票据」(搭了半小时)
前瞻记忆:「改完这里,还要把单元测试里的假数据删掉」

电话 5 分钟(聊的是晚饭):

打断后盘点:
① 短时记忆:已清空。「retryCount 是几?」——没了,
只能重读代码。这一项丢得最少。
② 心智模型:还在,但开始渗漏。你隐约记得「和重置有关」,
却想不起「为什么怀疑重置」——模型没有错,是支撑它的
证据链断了,你得回去重看两处代码重建证据。
③ 前瞻记忆:全灭。「删假数据」这件事连「存在过」都不记得了。

那一刻钟(第 2 节的实测数)花在哪:不是反应慢,
是 ①重读代码恢复中间值 + ②重看证据链焊接模型 + ③查 diff
找回「本来还要干嘛」——三件事各自都要几分钟。(diff,
即版本工具里「改动前后对照」的视图。)

程序员们其实早就自发发明了对策,帕宁记录了其中一种:路障提醒——打断前故意在代码里塞几个随机字符,让编译必然报错;回来时错误消息像路障一样把你拦在原地,想忘都忘不了8。下面这节把这类土办法升级成三件正经工具。

4. 三件自救工具

工具一:把心智模型存出去。理解活动靠心智模型(第 07 章),那就在模型最新鲜的时刻把它写进注释——不只是「这段干什么」,更包括为什么这么做、排除了哪些方案。书里引了奥斯特霍特(Ousterhout)的话:注释的意义就是「获取存在于编写者脑海里但没有体现在代码中的信息」9。自己的注释首先是给「被打断后的自己」看的——代码即文档派常反驳说注释没用,但代码恰恰写不出「我为什么放弃了方案 B」这部分。若打断可以推迟,优先推迟:Slack 消息可以晾着,响铃的电话晾不了10

工具二:喂饱前瞻性记忆。除了程序性和陈述性记忆,还有第三种——前瞻性记忆:记住「将来要做某事」的记忆,计划全靠它。「改完记得删假数据」就存在这里。它的常见容器是 TODO 注释——容器有多不可靠?GitHub 上含「TODO」的代码超过 1.36 亿条,大多「待而不办」11。改进方向:要么给提醒挂上触发点(有研究者做过给 TODO 设有效期的插件),要么退回路障提醒这类「物理外挂」12

**工具三:子目标标记。**动手前把任务拆成显式的几步,写下来。书里用文本拆解任务演示——作者自己的写法是把每步写成注释,逐个补齐:

# parse text ← 第 1 步:拆开文本
# receive parse tree ← 第 2 步:拿到分析树
# filter the parse tree ← 第 3 步:筛选
# flatten tree back into text format

13

有研究(马古利厄克斯)证实:提供子目标时,程序员真的会用它们规划解法14。子目标的三重用途:规划时是路线图;被打断时是「我做到第几步了」的定位器;做完后注释就地转正成文档。

5. 干扰本身能不能治

三件工具都是「被打断之后」,但打断的时机可以管理。贝利(Bailey)的对照实验:50 位被试做主要任务,一组的无关信息(突发新闻、股价)在任务中途插入,另一组在任务完成后才给——中途组花时更久、感受更难更烦更焦虑;2006 年的后续研究里,被打断者的错误率是两倍15

结论:同样的干扰,挪到任务间隙发生,伤害大幅下降。于是有了 FlowLight:一盏按打字速度、鼠标活动判断「你是否在状态」的桌灯,专注时亮红(别来烦我),闲时变绿。449 位程序员、12 个国家的现场研究:干扰减少 46%,不少人实验结束后继续用16——成本一盏灯,收益半个下午。

顺带回答一个常见反驳:「我不是被打断,我是主动多任务。」研究不站这边:一心多用只在各任务都自动化后成立(第 11 章),读难文章时想把音乐调小、停车入位前想关收音机,都是大脑在报「坑位不足」17。数字上:边读边聊天的学生多花约 50% 时间;重度社交网络用户学习时长不短、成绩更低,而且自我感觉效率很高;2008 年的对照实验里,一边干活一边在线聊天的人自我评价良好,同伴给他们的评分却低得多18。多任务最危险的部位是「自我感觉」。

6. 作者的判断与证据

**有实验撑着的:**打断频率与代价(van Solingen;帕宁 85 人记录;微软调查);预热期(中川,fNIRS);错误率翻倍(贝利 2001/2006);FlowLight 46%(祖格尔,449 人现场研究);多任务三连(Fox;克尔希纳;2008 对照)。

作者的发挥,要分开看:「把设计方向写进注释」是作者的一贯主张,她自己的步骤注释实例是自我报告;主走查的盘点是把书里分散的机制(30 秒蒸发、模型、前瞻记忆)拼到一个场景上——场景是编的,机制各有出处。

**书的坦白:**FlowLight 靠交互数据推测专注度,只是「通俗地讲」在判断状态;子目标研究的结论也只到「会使用」为止,收益没有测过数。

7. 边界与局限

  • 五种活动的边界在真实工作里是糊的:一次提交常常五种活动揉在一起,分类是分析工具,不是时刻表;
  • 一刻钟、46%、两倍这些数字各有各的样本(85人会话、449人、50被试),相互间不能换算,引用时要带各自的口径;
  • FlowLight 的 46% 来自自愿参加的现场研究——愿意挂灯的人本身就可能更在意专注,效果有自我选择的水分;
  • 「打断后一刻钟」测的是恢复到能写代码,不是恢复到打断前的思路质量——深处的模型缺口可能几天后才暴露。

8. 可带走的

  1. 干活前先自报家门:这会儿是搜索、理解还是转写?——活动不同,该请的工具不同;
  2. 给新人拆任务按活动切:先纯搜索、再纯理解,最后才递增;
  3. 离开工位前 30 秒,把心智模型和「下一步」写进注释或便签——这是给自己买的保险;
  4. 「下一步要做的琐事」别信脑子,TODO 要么带触发点,要么用路障提醒;
  5. 大任务开工前先把子目标写成注释,打断回来靠它定位;
  6. 能推迟的干扰就推迟:把「马上回」改成「攒到任务间隙一起回」;
  7. 团队装一盏 FlowLight(或任何状态灯),一盏灯顶半条制度;
  8. 别信自己「可以一心多用」的感觉——那个感觉恰恰是被研究证伪的部分。

9. 原文地图

主题原书章原文位置
五种活动框架11.1 程序设计包括不同的编程活动text/65-ch11-01-11-1.txt:5(搜「5种编程活动」)
各活动压的记忆11.1 程序设计包括不同的编程活动text/65-ch11-01-11-1.txt:15(搜「搜索活动会影响短时记忆」) · text/65-ch11-01-11-1.txt:27(搜「显著影响工作记忆」) · text/65-ch11-01-11-1.txt:33(搜「转写活动主要影响长时记忆」)
递增与探索11.1 程序设计包括不同的编程活动text/65-ch11-01-11-1.txt:39(搜「混合性」) · text/65-ch11-01-11-1.txt:53(搜「尤其明显」)
调试=五种结合11.1 程序设计包括不同的编程活动text/65-ch11-01-11-1.txt:59(搜「5种编程活动的结合」)
打断频率11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:7(搜「15~20分钟」) · text/66-ch11-02-11-2.txt:9(搜「62%」)
预热期11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:17(搜「认知负荷最高」) · text/66-ch11-02-11-2.txt:19(搜「预热期」)
一刻钟与路障提醒11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:23(搜「一刻钟」) · text/66-ch11-02-11-2.txt:25(搜「路障提醒」)
保存心智模型11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:39(搜「没有体现在代码中」) · text/66-ch11-02-11-2.txt:41(搜「重中之重」) · text/66-ch11-02-11-2.txt:43(搜「推迟法」)
前瞻性记忆与 TODO11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:49(搜「前瞻性记忆」) · text/66-ch11-02-11-2.txt:51(搜「1.36亿」) · text/66-ch11-02-11-2.txt:57(搜「attachables」)
子目标标记11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:61(搜「子目标标记法」) · text/66-ch11-02-11-2.txt:71(搜「parse text」) · text/66-ch11-02-11-2.txt:76(搜「Margulieux」)
Bailey 实验11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:88(搜「50位被试者」) · text/66-ch11-02-11-2.txt:92(搜「两倍」)
FlowLight11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:98(搜「449位程序员」)
多任务研究11.2 受到干扰的程序员text/66-ch11-02-11-2.txt:108(搜「自主阶段」) · text/66-ch11-02-11-2.txt:114(搜「50%」) · text/66-ch11-02-11-2.txt:116(搜「Facebook」) · text/66-ch11-02-11-2.txt:88(搜「对照实验」)

Footnotes

  1. 出处:「11.1 程序设计包括不同的编程活动」第 5 段(text/65-ch11-01-11-1.txt:5,搜「5种编程活动」)。框架提出者为 Green、Blackwell 与 Petre。

  2. 出处:「11.1 程序设计包括不同的编程活动」第 15、27、33、39、53 段(text/65-ch11-01-11-1.txt:15,搜「搜索活动会影响短时记忆」)。各活动对应的记忆与辅助手段为对原文的归纳。

  3. 出处:「11.1 程序设计包括不同的编程活动」第 43 段(text/65-ch11-01-11-1.txt:43,搜「分解为若干个独立的子任务」)。

  4. 出处:「11.1 程序设计包括不同的编程活动」第 57–59 段(text/65-ch11-01-11-1.txt:59,搜「5种编程活动的结合」)。

  5. 出处:「11.2 受到干扰的程序员」第 7、9、23 段(text/66-ch11-02-11-2.txt:7,搜「15~20分钟」;text/66-ch11-02-11-2.txt:9,搜「62%」;text/66-ch11-02-11-2.txt:23,搜「一刻钟」)。van Solingen 的研究在两家组织进行;帕宁的 85 人、10000 次会话见第 9 段。

  6. 出处:「11.2 受到干扰的程序员」第 17、19 段(text/66-ch11-02-11-2.txt:17,搜「认知负荷最高」)。

  7. 主走查场景为本拆解虚构;所引机制分别见:30 秒蒸发(text/14-ch02-01-2-1.txt:91,搜「不超过30秒」)、心智模型与中断(「11.2 受到干扰的程序员」第 25 段,text/66-ch11-02-11-2.txt:25,搜「重建上下文」)、前瞻性记忆(text/66-ch11-02-11-2.txt:49,搜「前瞻性记忆」)。

  8. 出处:「11.2 受到干扰的程序员」第 25 段(text/66-ch11-02-11-2.txt:25,搜「路障提醒」)。

  9. 出处:「11.2 受到干扰的程序员」第 39 段(text/66-ch11-02-11-2.txt:39,搜「没有体现在代码中」)。出自 Ousterhout《The Philosophy of Software Design》;布鲁克斯《人月神话》对注释的强调见第 41 段。

  10. 出处:「11.2 受到干扰的程序员」第 43 段(text/66-ch11-02-11-2.txt:43,搜「推迟法」)。

  11. 出处:「11.2 受到干扰的程序员」第 49、51 段(text/66-ch11-02-11-2.txt:49,搜「前瞻性记忆」;text/66-ch11-02-11-2.txt:51,搜「1.36亿」)。

  12. 出处:「11.2 受到干扰的程序员」第 57 段(text/66-ch11-02-11-2.txt:57,搜「attachables」)。帕宁开发的 Visual Studio 插件,可给待办事项设有效期。

  13. 出处:「11.2 受到干扰的程序员」第 61–74 段(text/66-ch11-02-11-2.txt:71,搜「parse text」)。作者本人的步骤注释实例。

  14. 出处:「11.2 受到干扰的程序员」第 76 段(text/66-ch11-02-11-2.txt:76,搜「Margulieux」)。

  15. 出处:「11.2 受到干扰的程序员」第 88–92 段(text/66-ch11-02-11-2.txt:88,搜「50位被试者」;text/66-ch11-02-11-2.txt:92,搜「两倍」)。

  16. 出处:「11.2 受到干扰的程序员」第 95–98 段(text/66-ch11-02-11-2.txt:98,搜「449位程序员」)。

  17. 出处:「11.2 受到干扰的程序员」第 108 段(text/66-ch11-02-11-2.txt:108,搜「自主阶段」)。

  18. 出处:「11.2 受到干扰的程序员」第 114–117 段(text/66-ch11-02-11-2.txt:114,搜「50%」;text/66-ch11-02-11-2.txt:116,搜「Facebook」;text/66-ch11-02-11-2.txt:88,搜「对照实验」)。