命名的认知学 — 好名字是写给大脑的路标
这一章讲三件事: 取名为什么这么难(有数据);什么样的名字读起来省脑子(有一串实验); 以及一套现场可用的取名流程。 它是第 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:
- 选概念:问「这个名字要不要注明单位、类型、安全性?」——如果需要写注释解释某个标识符,把注释内容并进名字;
- 挑单词:同义词竞争就建项目词库——全项目的重要定义和「同义词裁判决」记录在案;Feitelson 还发现三步不必严格按序,先想到词再回头补概念也行,但概念这一步不能省;
- 拼模具:模具=单词的组合模板(前缀式、逐层收窄式……),选库里通行的;再让语序贴自然语言——英语说「maximum number of points」不说「point maximum」,所以
max_points优于points_max;介词也是合法零件(indexOf、elementAt)。
这套流程有效吗?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. 可带走的
- 命名质量的黄金窗口是项目开局,「先跑起来再统一改名」基本不会发生;
- 一致 > 优雅:糟糕但统一的名字好过精致但混乱的名字;
- 变量名用完整单词,除非缩写是全行业公认的钉子(
i、s、c这类); - 同义词竞争开项目词库裁决,一个概念一个词,全库通用;
- 新名字尽量套库里已有的模具,让相关概念的检索能连上线;
- 需要写注释解释的标识符,先把注释内容并进名字;
- 别在解题时硬起名——先占位,代码审查时再正名;
- 命名变烂的区域,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:1 | 8.5 如何设计质量更高的标识符 | text/52-ch08-05-8-5.txt:55(搜「100名」) · text/52-ch08-05-8-5.txt:59(搜「2:1」) |