有意义的命名
命名三要素——名副其实、避免误导、有意义的区分,以及变量、函数、类的命名规范。
为什么只记结论不足以掌握有意义的命名
学习“有意义的命名”时,第一步不是记住结论,而是冻结输入、上下文、版本和成功标准。只有这些条件明确,有意义的命名的含义才不会随着样例变化。正文已有的概念说明要与结构图、运行轨迹和失败样本互相印证,不能只凭最终输出看似正确就宣布完成。
结构分析从痛点场景:名字是最大的谎言开始:列出参与者、职责、连接方向、生命周期和所有权,再沿正常路径追踪数据或控制流。每一条边都要说明为什么存在、谁创建、谁消费、谁负责清理;如果边界被跨越,必须能在证据中找到第一处异常。
机制验证要把解决方案:命名三要素写成可以执行的条件。正常样本证明主路径,恰好边界样本验证等号和空值,单故障样本只破坏一个假设。三类样本使用同一份观察指标,避免因为测试口径变化而把偶然结果误认成规律。
成本分析同时记录时间、空间、延迟、耦合、可维护性和不可逆操作。1. 名副其实不是一句“可能失败”,而是可复现输入、预期停点、实际轨迹、错误分类与清理步骤。任何自动重试都要有次数、预算和幂等边界。
方案比较不能只列优点。需要给出直接实现、当前方案和至少一个替代方案,逐项比较复杂度、扩展点、故障隔离和团队认知成本。当问题规模很小或变化轴稳定时,更简单的实现往往更好;模式与框架必须由真实变化压力证明。
实现阶段把大结论拆成可检查的中间产物:配置快照、结构清单、状态转移、输入输出样本、日志摘要和测试结果。每个产物带来源与生成命令,下一阶段只消费已通过门禁的版本,避免旧缓存或隐式默认值污染结论。
解释结果时必须区分相关性与因果性、接口承诺与实现细节、设计意图与运行事实。对“2. 避免误导”的判断要由独立证据支持,并明确适用范围;一旦输入分布、版本、硬件或组织边界改变,就重新运行最小实验。
复盘从首个分叉开始,而不是从最后一个报错倒推。先比较冻结输入,再比较第一份结构化中间产物,随后检查状态、约束和副作用。这样可以把复杂系统的排错范围收缩到一个阶段,避免在多个层次同时修改造成新的不确定性。
迁移到真实项目时,先选择一个最小但有代表性的切片,保存改造前基线,再逐步引入“有意义的命名”中的机制。每一步只改变一个变量并保留回滚点;性能、正确性、安全性和可理解性至少各有一项可量化指标。
最终验收要求读者能脱离页面重新画出结构、口述关键链路、实现最小版本、构造一个反例并解释失败位置。若只能复述名词而不能预测中间状态,说明知识仍停留在识记层,需要回到图示和实验重新验证。
本页用、
、、、建立统一坐标。先预测这些概念在结构图和运行轨迹中的位置,再操作实验控件;如果结果与预测不一致,停止在首个分叉,不要用后续补丁掩盖早期错误。
权威目录与核心概念逐项对照
- 有意义的命名
- 痛点场景:名字是最大的谎言
- 解决方案:命名三要素
-
- 名副其实
-
- 避免误导
-
- 有意义的区分
- 常见误区
- 误区 1:用缩写省字符
可复现的最小实现
先把决策记录写成机器可读结构:
{
"unit": "有意义的命名",
"inputFrozen": true,
"scenario": "normal | boundary | single-fault",
"firstDivergence": null,
"cleanupRequired": true
}再用同一条执行链处理三类样本:
type Evidence = { stage: string; expected: string; actual: string };
function verify(sample: unknown, expected: readonly Evidence[]) {
const trace = runFromCleanState(sample);
return expected.find((item, index) => trace[index]?.actual !== item.expected);
}最后保存回归门禁,禁止失败样本静默通过:
normal -> complete, invariant preserved
boundary -> complete or explicit rejection
singleFault -> stop at first divergence, no stale output用统一评分解释实验结果:
本章回顾
- 有意义的命名必须绑定冻结输入和明确成功标准。
- 痛点场景:名字是最大的谎言必须能画成结构并沿边追踪责任。
- 解决方案:命名三要素要由正常、边界和单故障样本共同验证。
-
- 名副其实必须保存第一处偏离和清理重建步骤。
-
- 避免误导决定方案是否可以进入下一阶段。
术语表
痛点场景:名字是最大的谎言
你看不懂一段代码,多半不是逻辑难,而是名字烂。下面这两行,哪行你一眼能懂?
const d = r * t; // 距离?天数?什么跟什么?
const distance = speed * time; // 一眼就懂烂名字的代价:每一个读这段代码的人都要重新猜一遍你当年什么意思。猜错就引入 bug。命名是代码里成本最低、收益最高的改善——改个名字就能让代码可读性翻倍。
解决方案:命名三要素
1. 名副其实
名字要能回答「它是什么」「它做什么」,而不是需要注释补充。d 不如 daysSinceCreation;getList() 不如 getActiveUsers()。判断标准:删掉名字看注释才能懂,就是坏名字。
2. 避免误导
别用有特殊含义的词指代别的东西。accountList 如果实际是数组而不是 List 类型,就是误导——用 accounts 更安全。别用 0(零)和 O、l 和 1 这种容易混淆的字符。
3. 有意义的区分
name1 和 name2、aUser 和 theUser 都是噪音词——它们区分了,但没传达任何信息。真正的区分要靠语义:sourceUser 和 targetUser。
常见误区
误区 1:用缩写省字符
现象:把 userAccountNumber 写成 usrAccNum。原因:以为短名字更省事,其实省的是打字时间,浪费的是所有人的阅读时间。修法:除非是领域通用缩写(如 URL、ID),否则别缩写。现代编辑器有补全,长名字不增加打字成本。
误区 2:名字带实现细节
现象:把方法命名为 getUserFromMySQL。原因:把「怎么做」写进了名字。修法:名字反映意图而非实现——叫 getUser。哪天换成 Redis,名字不用改。实现细节是实现的事,不该泄漏到名字里。
误区 3:一个名字在不同地方含义不同
现象:account 在这个文件指账户实体,在另一个文件指账户 ID。原因:图省事复用词。修法:一词一义,全局一致。同义词也要小心——fetch 和 get 别混用,否则读者要猜它们到底差在哪。
小结
- 命名三要素:名副其实、避免误导、有意义的区分
- 变量名词、函数动词、布尔 is/has/can、类名词
- 别缩写、别带实现细节、一词一义全局一致
- 命名是性价比最高的改善:改个名,可读性翻倍
下一步:进入「函数」,看一个好函数该长什么样。