44 事物命名
用名称传达领域意图和作用域,并在意图变化时及时重命名,避免陈旧名称传播错误模型。
学习目标
- 能从调用者、领域和作用域判断名称是否表达真实对象与当前意图
- 能区分名称歧义、陈旧名称和跨边界词汇冲突,并用反例验证理解
- 能以安全重命名、引用检查和回归证据更新名称,让代码与模型同步
名称是给下一位读者的接口
本页依据 David Thomas、Andrew Hunt《程序员修炼之道:通向务实的最高境界(第2版)》,云风译,电子工业出版社,2020 年 4 月,ISBN 9787121384356 的公开中文目录,独立重构 44 事物命名。正文、代码、图示、实验和练习都是本课程重新设计的教学材料,不复制原书正文、插图或答案。
名称不仅用于编译器查找。它告诉读者一个值代表什么、在哪个边界有效、可以做什么、不能做什么,以及意图变化后是否需要更新。data、info、handle 或 tmp 可能在很小的作用域里足够,但一旦跨越模块、领域或权限边界,含糊名称会把错误模型传播到更多代码。
三个会让名称制造风险的陷阱
从对象到可验证的更名回路
<Term def="代码、数据或业务规则正在描述的具体事物及其集合边界。">领域对象</Term>先于名称。问“这个值到底代表什么”,再问“调用者在当前作用域需要知道什么”。一个订单 ID、付款事实和购物车快照不能因为都能放进字符串就共享一个含糊名字。
名称回路包含五步:
- 对象:列出真实集合、单位、生命周期和敏感性;
- 语境:确认领域词汇、调用者和边界;
- 意图:说明它允许的动作与拒绝条件;
- 命名:选择能表达范围和作用域的词;
- 更名:意图变化时同步引用、文档、测试和事件。
44 与提示 74:好好取名;需要时更名
本单元对应中文目录的 44 事物命名 和 提示 74:好好取名;需要时更名。好名称不是最长或最聪明的名称,而是让调用者少猜一个关键前提。它应能和领域词汇、作用域、单位、权限以及生命周期对齐。
<Term def="团队和领域对对象、动作、状态有稳定含义的词汇集合;跨边界使用时要检查语义是否仍相同。">领域词汇</Term>可以减少翻译和猜测,但同一个词在不同边界可能有不同定义。account 在计费服务、身份服务和财务服务中可能分别代表不同对象,接口应通过更具体的名称或类型表达边界。
<Term def="名称有效、可见且不会与其他对象混淆的代码与业务边界。">作用域</Term>决定所需精度。局部循环变量可以短,公共函数、审计事件和安全令牌必须更精确。名称越靠近跨团队或跨系统边界,越需要表达单位、状态和权限。
type SessionRefreshToken = {
value: string;
expiresAt: string;
};
function isRefreshTokenExpired(
token: SessionRefreshToken,
now: string,
): boolean {
return token.expiresAt <= now;
}token 被改成 SessionRefreshToken 后,调用者更容易意识到它的生命周期和敏感性;名称不能替代安全存储和验证,但能减少把长期凭据当作普通字符串传递的机会。
一致性与安全表达
<Term def="同一概念在代码、接口、测试、文档和事件中的名称及含义保持一致的程度。">命名一致性</Term>不是要求所有词都相同,而是要求同一语义不要在相邻边界悄悄变形。若 API 叫 expiresAt,日志和数据库字段不应又叫 createdUntil 来表达同一时刻。
名称还承担安全提示:untrustedHtml、hashedPassword、expiresAt、adminOnly 都在提醒调用者检查边界。它们不是防护本身,但能帮助审查者发现危险组合。名称与行为冲突时,应把冲突当作缺陷,而不是继续添加注释来掩盖。
练习实验:让名称与意图同步
Interactive lab
选择命名样本,定位第一个语义差异
输入证据
同一个词同时指向缓存条目和用户会话,调用路径跨过了职责边界。
实际首差
语义节点:先拆开领域词,再决定是否需要两个明确名称。
恢复动作
补一个边界样本,确认两种对象的生命周期和失败行为分开。
先确认对象和意图,再选择名称;重命名不是机械替换,而是一次可验证的设计迁移。
1. 列出对象集合与反例
选择一组含糊变量,写出它实际包含和不应包含的对象、单位、生命周期和权限。若集合同时包含两个领域概念,考虑拆类型。
正常、边界与单一故障证据
| 样本 | 唯一变化 | 预期判定 | 必存证据 |
|---|---|---|---|
| 正常 | 对象、语境和意图一致 | 名称表达范围,引用行为不变 | 候选词、引用检查和测试 |
| 边界 | 跨领域、单位或权限边界 | 名称或类型明确拒绝歧义 | 反例、作用域和兼容规则 |
| 单一故障 | 一个引用、事件或迁移未更新 | 在编译或回归处暴露首差 | 首差、修复和回退 |
独立复核者应能只看对象集合、调用者需求和引用结果判断名称是否合理。名称评审不是投票喜欢哪个词,而是验证词汇能否减少错误假设,并能随意图变化及时更新。
术语表
名词解释
本章出现的专业名词,用大白话再讲一遍。
- 领域对象
代码、数据或业务规则正在描述的具体事物及集合边界。
- 领域词汇
团队和领域对对象、动作、状态有稳定含义的词汇集合。
- 作用域
名称有效、可见且不会与其他对象混淆的代码或业务边界。
- 命名一致性
同一概念在代码、接口、测试、文档和事件中保持同一语义。
- 重命名
意图变化后同步更新引用、文档、测试和事件名称的受控变更。
练习
练习
问题 1: 一个公共函数参数叫 time,调用者有的传创建时间,有的传过期时间。你如何处理?
问题 2: user 变量同时包含客户、员工和服务账号。只把名称改成 principal 就够了吗?
问题 3: 更名后代码通过,但旧事件消费者仍读取旧字段。你会怎样安全迁移?
本单元回顾
命名不是装饰,而是对象、语境、意图和作用域之间的接口。好名称减少调用者的猜测;更名让代码模型跟上业务变化。用对象集合、反例、引用检查和行为回归验证名称,再处理兼容和回退,才能避免陈旧词汇把错误理解传播到下一层。