跳到主要内容

命名的认知学 — 好名字是写给大脑的路标

这一章讲三件事: 取名为什么这么难(有数据);什么样的名字读起来省脑子(有一串实验); 以及一套现场可用的取名流程。 它是第 02 章「信标」的施工规范:信标主要就是名字,这一章讲怎么把名字造成好信标。

1. 全景:命名难的认知根源

计算机科学有两桩公认的老大难,其中一桩就是取名,另一桩是缓存——缓存,即把常用数据先抄在近处省时间的那一小块存储;「缓存失效」就是近处没抄到、只好回原处重取1

取名难在哪?费特尔森(Feitelson)做了个干脆的测量:334 位被试(有学生也有平均 6 年工龄的职业程序员)给 47 个对象命名——两位被试选中同一个名字的比例,中位数只有 6.9%2。也就是说,程序员对「同一个东西」几乎不存在心照不宣的名字。

但名字偏偏又极其重要,因为它就是代码的组成成分本身: Eclipse 的源码约 200 万行,其中 33% 的标记(即代码里最小单位的词,一个函数名、一个括号都算)和 72% 的字符属于标识符(代码里所有由程序员起名的东西:变量、函数、类、模块的总称)3。名字还是读得最多的文档——代码审查的评论里,25% 在谈命名;而读代码时大家最常看的「文档」正是注释和标识符,因为跳出代码库查文档额外烧工作记忆4

取名难的机制
取名时:工作记忆正被解题占满 → 匀不出来琢磨名字
读名时:名字分头喂两套装置 →
├─ 短时记忆:靠「写法规范」分块(nmcntravg 切不动,name_counter_average 一眼三块)
└─ 长时记忆:靠「领域词」检索(customer 能勾出一串存货,xyz 不能)
图说:好名字=对短时记忆好切+对长时记忆好查。下面三节全在展开这张图。

2. 两派标准:规则派与一致派

学界对「什么叫好名字」有两派,认知上都有道理5:

  • 规则派(巴特勒 Butler):名字该守语法清单——别用下划线开头结尾、别用系统型匈牙利前缀(第 05 章考古过的那个)、统一首字母大小写。道理:每次都以相同样子出现,大脑分块不用重新猜;
  • 一致派(阿拉马尼斯 Allamanis):一致性高于一切——糟糕但一致的命名,好过优雅但混乱的命名。道理:同一个概念全库一个叫法,长时记忆检索只对一次答案。

一个现实佐证:法律里(Lawrie)分析了 78 个代码库、186 个版本、超 4800 万行、跨 30 年的代码,发现两件事——如今的代码命名比过去规范;但同一个代码库内部,命名质量从不随时间改善:开头什么样,后来还什么样。她的结论是「标识符质量在项目早期就已定型」,且和代码库大小无关6命名是开局定终局的少数几件事之一。

工具也证明「一致」可以自动化:Naturalize 用机器学习(让程序从数据里自己找规律的技术)从代码库里学「本地好名字」,给出改名建议——它提的 18 个拉取请求(向代码库提交改动的申请)有 14 个被接受;它给 JUnit 提建议时审阅者一度拒绝,理由是「和我们库里的风格不符」——而它改的正是违反了该库自己成文规范的地方。程序员违反自己定的规矩太久,错的版本反而成了标准7

3. 主走查:给「每月最大收益」起名

把三步模型(费特尔森提出,见第 5 节)直接走一遍。任务:给「每个月能够获得的最大收益」这个量起名。

第 1 步:选定要体现的概念
→ 「最大」「按月」「收益」三个概念。
自检:「要不要注明单位?」要——是美元还是人民币,读的人不知道。
(概念选错是命名最大的失败,这一步领域性最强。)

第 2 步:给每个概念挑单词
→ 最大 = max / maximum;月 = monthly / month;收益 = benefit / benefits
→ 团队有两个同义词在竞争?记进项目词库(全项目统一用词的对照表),
从此只许用一个。max 更短,但 maximum 无歧义——选哪个都行,选定就不换。

第 3 步:按代码库的「模具」拼装
→ 同一个概念,五种拼法(这五种拼法为演示而列,书中原图为表格):
max_monthly_benefit (前缀式:修饰词在前)
monthly_max_benefit (逐层收窄式)
benefit_max_month (名词堆叠式)
maximumMonthBenefit (驼峰拼写的前缀式)
maxBenAmt (缩写式——待会儿你会看到它的代价)
→ 查一下库里已有的 max_interest_amount(最高利息金额):前缀式。
收益和利息计算逻辑相近,用 max_monthly_benefit,
长时记忆检索「max_」就能把旧的利息代码一起勾出来;
用 benefit_max_month 则勾不出——概念相邻,模具不同,检索就断线。

走查里每一件事都对应本章一个实验结论:第 1 步对应「概念最重要」,第 2 步对应项目词库,第 3 步对应「模具一致性助检索」——这就是三步模型的整体:先想清楚概念,再统一单词,最后按库里通行的模具拼装

4. 证据层:单词、缩写与大小写的实测

完整单词 vs 缩写。霍夫迈斯特(Hofmeister)让 72 位职业 C# 程序员找代码里的错误,材料分别用完整单词、缩写、单字母起名:读完整单词版时,每分钟多查出 19% 的错误8。法律里的另一项实验(128 位平均 7 年半工龄的程序员)补上了反面:完整单词最好理解没错,但长名字更难记——罪魁是音节数;而且前缀、后缀这类「额外信息」会加长名字、加重记忆,她建议这类命名约定要三思9

**单字母的江湖。**贝尼亚米尼(Beniamini)扒了 5 门语言在 GitHub 上最受欢迎的 200 个项目(超 16 GB 源码):i/j/k/n 大体公认是整数计数器,s 是字符串、c 是字符——仅此而已;d/e/f/r/t 被不少人猜成浮点数(出乎意料),x/y/z 则整数浮点五五开10。结论:单字母的「自明性」靠不住,除了那几个公认钉子,别人的脑补你管不着。

驼峰还是蛇形。宾克利(Binkley)找了 135 人(程序员和非程序员都有)做「读句子选标识符」测试:驼峰命名法(customerPrice,单词靠大写分界)比蛇形命名法(customer_price,单词靠下划线分界)正确率高 51.5%,但定位慢 0.5 秒——分界醒目就得逐词看清,快和准不可兼得11。更有趣的是培训的副作用:受驼峰命名法培训多年的人识别驼峰更快,但识别蛇形比没受过这种培训的人还慢——第 08 章的负迁移,在命名上也有份12

5. 代价层:坏名字和 bug 同框

巴特勒还做了一层更狠的验证:拿 8 个开源(源代码公开、谁都能查看使用的)Java 代码库——包括 Tomcat 和 Hibernate 这样的名项目——用工具提取全部标识符、检查命名违规,再和静态分析工具 FindBugs 报出的问题位置对照:命名缺陷和代码问题在统计上显著同框13

注意口径:同框不等于因果——可能是新手既写不好命名也写不好逻辑,也可能是难题本身让命名和代码一起失守14。正确的用法是把命名质量当烟感报警器:一片区域命名开始烂,就值得去看一眼那片代码,至少修名字能让它更好懂、更快修。

6. 施工规范:三步模型与项目词库

第 3 节走查用的三步模型,补齐细节15:

  1. 选概念:问「这个名字要不要注明单位、类型、安全性?」——如果需要写注释解释某个标识符,把注释内容并进名字;
  2. 挑单词:同义词竞争就建项目词库——全项目的重要定义和「同义词裁判决」记录在案;Feitelson 还发现三步不必严格按序,先想到词再回头补概念也行,但概念这一步不能省;
  3. 拼模具:模具=单词的组合模板(前缀式、逐层收窄式……),选库里通行的;再让语序贴自然语言——英语说「maximum number of points」不说「point maximum」,所以 max_points 优于 points_max;介词也是合法零件(indexOfelementAt)。

这套流程有效吗?Feitelson 让 100 名新被试用三步模型重做命名实验,请两位不知情的评委盲评前后质量:好评与差评之比为 2:116。不是惊天动地,但便宜、可复制、当场可用。

时机上还有一条反向纪律:别在开发时命名。解题时工作记忆正满载,硬挤名字只会产出 foo;名字的质量评估放到代码审查时做,那时概念已经稳定、脑子也是空的17

7. 作者的判断与证据

**有实验撑着的:**重名率 6.9%(Feitelson,334 人);完整单词多查 19% 错误(Hofmeister,72 人);长名字难记、音节是主因(Lawrie,128 人);驼峰准 51.5%、慢 0.5 秒(Binkley,135 人);单字母联想图谱(Beniamini,5 语言 200 项目);命名缺陷与 bug 同框(Butler,8 库);三步模型盲评 2:1(Feitelson,100 人)。命名是本书实验密度第二高的章节。

作者的发挥,要分开看:「烟感报警器」的用法是作者对同框数据的谨慎引申;模具一致性的检索收益有推理成分——书里自己承认「学界尚未开展有关名称模具的研究」18

**书的坦白:**两派标准(规则/一致)学界没有共识;「标识符质量好坏是个见仁见智的问题」是原话。

8. 边界与局限

  • 全部实验都在英文命名语境下做的;中文团队的拼音命名、中英混拼,这些数字一个都不能直接搬;
  • 「驼峰准但慢」的 51.5% 是特定任务(读句子选标识符)的结果,真实代码阅读里两种风格的差距没人量过;
  • 法律里的「早期定型」是观察性结论——它说明现状,不证明「开局没做好就没救」;只是返工成本极高,值得当真;
  • 三步模型的 2:1 是盲评的主观质量,不是「读懂速度」之类的硬指标。

9. 可带走的

  1. 命名质量的黄金窗口是项目开局,「先跑起来再统一改名」基本不会发生;
  2. 一致 > 优雅:糟糕但统一的名字好过精致但混乱的名字;
  3. 变量名用完整单词,除非缩写是全行业公认的钉子(isc 这类);
  4. 同义词竞争开项目词库裁决,一个概念一个词,全库通用;
  5. 新名字尽量套库里已有的模具,让相关概念的检索能连上线;
  6. 需要写注释解释的标识符,先把注释内容并进名字;
  7. 别在解题时硬起名——先占位,代码审查时再正名;
  8. 命名变烂的区域,bug 密度大概率也高——拿它当巡检信号。

10. 原文地图

主题原书章原文位置
Karlton 名言8.1 命名为什么重要text/48-ch08-01-8-1.txt:5(搜「缓存失效」)
重名率 6.9%8.1 命名为什么重要text/48-ch08-01-8-1.txt:7(搜「6.9%」)
Eclipse 占比、审查数据8.1 命名为什么重要text/48-ch08-01-8-1.txt:17(搜「33%的标记」) · text/48-ch08-01-8-1.txt:21(搜「25%的代码审查」) · text/48-ch08-01-8-1.txt:25(搜「文档类型」)
两派标准8.1 命名为什么重要text/48-ch08-01-8-1.txt:45(搜「问题清单」) · text/48-ch08-01-8-1.txt:57(搜「一致的命名实践」) · text/48-ch08-01-8-1.txt:59(搜「符合我们对认知科学的了解」)
Lawrie 三十年数据8.1 命名为什么重要text/48-ch08-01-8-1.txt:71(搜「4800万行」) · text/48-ch08-01-8-1.txt:75(搜「日趋成熟」) · text/48-ch08-01-8-1.txt:77(搜「早期阶段就已定型」)
Naturalize 与 JUnit 故事8.2 从认知的角度剖析命名text/49-ch08-02-8-2.txt:19(搜「Naturalize」) · text/49-ch08-02-8-2.txt:21(搜「违反命名约定」)
nmcntravg 对照8.2 从认知的角度剖析命名text/49-ch08-02-8-2.txt:27(搜「name_counter_average」)
三类信息8.2 从认知的角度剖析命名text/49-ch08-02-8-2.txt:37(搜「领域知识」) · text/49-ch08-02-8-2.txt:41(搜「嵌套循环」)
评估时机8.2 从认知的角度剖析命名text/49-ch08-02-8-2.txt:63(搜「foo」) · text/49-ch08-02-8-2.txt:65(搜「良机」)
Hofmeister 19%8.3 哪些类型的标识符更容易理解text/50-ch08-03-8-3.txt:11(搜「72位」) · text/50-ch08-03-8-3.txt:13(搜「19%」)
Lawrie 音节数8.3 哪些类型的标识符更容易理解text/50-ch08-03-8-3.txt:19(搜「1分」) · text/50-ch08-03-8-3.txt:21(搜「音节数量」) · text/50-ch08-03-8-3.txt:23(搜「三思而行」)
Beniamini 单字母8.3 哪些类型的标识符更容易理解text/50-ch08-03-8-3.txt:31(搜「16 GB」) · text/50-ch08-03-8-3.txt:37(搜「循环计数器」) · text/50-ch08-03-8-3.txt:43(搜「浮点数」)
Binkley 驼峰蛇形8.3 哪些类型的标识符更容易理解text/50-ch08-03-8-3.txt:55(搜「驼峰命名法」) · text/50-ch08-03-8-3.txt:59(搜「51.5%」) · text/50-ch08-03-8-3.txt:63(搜「负面影响」)
Butler 同框研究8.4 标识符与代码错误之间的关系text/51-ch08-04-8-4.txt:9(搜「Tomcat」) · text/51-ch08-04-8-4.txt:13(搜「统计学意义上的关联性」) · text/51-ch08-04-8-4.txt:15(搜「因果关系」)
名称模具8.5 如何设计质量更高的标识符text/52-ch08-05-8-5.txt:9(搜「名称模具(name mold)」) · text/52-ch08-05-8-5.txt:21(搜「max_interest_amount」) · text/52-ch08-05-8-5.txt:23(搜「达成一致」)
三步模型与词库8.5 如何设计质量更高的标识符text/52-ch08-05-8-5.txt:33(搜「三步模型」) · text/52-ch08-05-8-5.txt:45(搜「领域特定性」) · text/52-ch08-05-8-5.txt:47(搜「项目词库」) · text/52-ch08-05-8-5.txt:51(搜「indexOf」)
盲评 2:18.5 如何设计质量更高的标识符text/52-ch08-05-8-5.txt:55(搜「100名」) · text/52-ch08-05-8-5.txt:59(搜「2:1」)

Footnotes

  1. 出处:「8.1 命名为什么重要」第 5 段(text/48-ch08-01-8-1.txt:5,搜「缓存失效」)。原话出自前网景程序员 Phil Karlton。

  2. 出处:「8.1 命名为什么重要」第 7 段(text/48-ch08-01-8-1.txt:7,搜「6.9%」)。被试 334 位,含学生与平均 6 年经验的专业程序员,共 47 个命名对象。

  3. 出处:「8.1 命名为什么重要」第 17 段(text/48-ch08-01-8-1.txt:17,搜「33%的标记」)。

  4. 出处:「8.1 命名为什么重要」第 21 段(text/48-ch08-01-8-1.txt:21,搜「25%的代码审查」)与第 25 段(text/48-ch08-01-8-1.txt:25,搜「文档类型」)。

  5. 出处:「8.1 命名为什么重要」第 45 段(text/48-ch08-01-8-1.txt:45,搜「问题清单」)与第 57 段(text/48-ch08-01-8-1.txt:57,搜「一致的命名实践」)。

  6. 出处:「8.1 命名为什么重要」第 71、75、77 段(text/48-ch08-01-8-1.txt:71,搜「4800万行」;text/48-ch08-01-8-1.txt:77,搜「早期阶段就已定型」)。C++、C、Fortran、Java 四种语言,时间跨度 30 年。

  7. 出处:「8.2 从认知的角度剖析命名」第 19、21 段(text/49-ch08-02-8-2.txt:19,搜「Naturalize」;text/49-ch08-02-8-2.txt:21,搜「违反命名约定」)。

  8. 出处:「8.3 哪些类型的标识符更容易理解」第 11、13 段(text/50-ch08-03-8-3.txt:13,搜「19%」)。

  9. 出处:「8.3 哪些类型的标识符更容易理解」第 15–23 段(text/50-ch08-03-8-3.txt:21,搜「音节数量」)。128 位被试平均经验 7 年半;前缀后缀建议见第 23 段。

  10. 出处:「8.3 哪些类型的标识符更容易理解」第 31–43 段(text/50-ch08-03-8-3.txt:31,搜「16 GB」)。d/e/f/r/t 被联想为浮点数见第 43 段。

  11. 出处:「8.3 哪些类型的标识符更容易理解」第 59 段(text/50-ch08-03-8-3.txt:59,搜「51.5%」)。被试 135 位,含程序员与非程序员;多花 0.5 秒同段。

  12. 出处:「8.3 哪些类型的标识符更容易理解」第 63 段(text/50-ch08-03-8-3.txt:63,搜「负面影响」)。

  13. 出处:「8.4 标识符与代码错误之间的关系」第 9、13 段(text/51-ch08-04-8-4.txt:9,搜「Tomcat」;text/51-ch08-04-8-4.txt:13,搜「统计学意义上的关联性」)。研究完成于 2009 年,评估 8 个代码库。

  14. 出处:「8.4 标识符与代码错误之间的关系」第 15 段(text/51-ch08-04-8-4.txt:15,搜「因果关系」)。

  15. 出处:「8.5 如何设计质量更高的标识符」第 37–51 段(text/52-ch08-05-8-5.txt:33,搜「三步模型」)。项目词库见第 47 段,模具与介词建议见第 51 段。

  16. 出处:「8.5 如何设计质量更高的标识符」第 55–59 段(text/52-ch08-05-8-5.txt:59,搜「2:1」)。两位评委事先不知道变量名来自哪次实验。

  17. 出处:「8.2 从认知的角度剖析命名」第 63、65 段(text/49-ch08-02-8-2.txt:63,搜「foo」;text/49-ch08-02-8-2.txt:65,搜「良机」)。

  18. 出处:「8.5 如何设计质量更高的标识符」第 19 段(text/52-ch08-05-8-5.txt:19,搜「尚未开展有关名称模具的研究」)。