一个团队建了 60 条术语的"统一语言表",放在 Wiki 首页。三个月后它停止了更新,而代码里"同一个概念"仍有三个名字:Order、Trade、Deal——因为"表在 Wiki,而命名在代码里",两者从未被同一个动作同时修改。
术语表的价值不在"文档",而在"同一个概念只有一个名字,且这个名字在代码里可见"。这个"分离"的具体形态是:"写术语"的人与"用术语"的人不在同一时刻——于是"写的人有一份心智模型,用的人各自带一份",而两份从不校验。
而它失效的原因很机械:维护动作与使用场景分离。
1. 术语表的三种"存放位置"
| 位置 | 维护成本 | 是否被使用 |
|---|---|---|
| Wiki/文档 | 中 | 低(很少人查) |
| 代码(类名/枚举/常量) | 随代码 | 高(写代码必然用到) |
| 两者同步 | 高 | 中(易漂移) |
第二项是"唯一被强制执行"的:你写代码时必须选一个名字第二项的"强制"来自"编译器与评审":两个类都叫 Order 会撞包,而"两个概念都叫订单"不会编译报错——于是"代码里的术语"仍有"同名不同义"的空间。
——于是"术语表的约束"在这里才真正生效。
2. "同一概念三个名字"的三种后果
| 后果 | 表现 |
|---|---|
| 沟通歧义 | "订单"指的是两个对象 |
| 代码重复 | 三套模型/三套接口 |
| 数据不一致 | 同一实体三张表 |
第三项的"成本"可算:每多一个名字,就多"一套模型 + 一套接口 + 一次对账"——而"对账"是"每天都要做"的重复成本。
第三项最贵:"三张表"意味着"三个真相",而对账时要"人工比三份"。
"术语表"应当只写"会混的词",而"会不会混"可以用一个测试发现:
// 一个五分钟的"歧义测试"
让 3 个人分别用"一句话"解释这 10 个词(不看文档)
收集答案 → 出现"两种以上解释"的词,就是该进表的
// 例:"账户"→ 有人答"登录账号",有人答"资金账户"→ 进表
// 收益:表里的每一条都对应"真实的歧义",而不是"作者的兴趣"
3. 术语表的"最小可持续"形态
| 做法 | 效果 |
|---|---|
| 60 条全量(大而全) | 维护不动 |
| 10–15 条"核心概念" | 可维护 |
| 只登记"曾经混乱"的概念 | 最有效 |
第三项是"最实用"的:"我们曾经叫它 X、Y、Z,现在统一叫 W"——一句"变更记录"比"定义"更有价值,因为它"阻止了回退"。
// 一条"够用"的术语记录(四项,比"定义"更有用)
术语:订单(Order)
曾用名:Trade / Deal(2025-06 前,已废弃)
边界:订单≠购物车;订单≠履约单(履约是下游)
权威字段:order_id / status / amount(以代码为准,链接到类)
// 关键:第三、四项回答"它不是什么",而这才是歧义的来源
4. "术语与代码对齐"的三种机制
| 机制 | 效果 |
|---|---|
| 类名/枚举名即术语 | 强(编译期约束) |
术语表链接到代码(@see) |
中(可跳转) |
| 定期"命名审计" | 弱(靠人) |
第一项的"落地顺序"是"先给"最容易混的三个"建类型":订单/购物车、用户/账户、商品/SKU ——这三组是"跨系统歧义"的高发区。
第一项是最有效的:"术语表"的核心条目应当"在代码里有唯一对应"——于是"改名"与"改术语"是同一个动作。
// 术语在代码里"落地"的三种形式
public enum OrderStatus { CREATED, PAID, SHIPPED, CLOSED } // 枚举:取值即术语
public record OrderId(String value) { } // 值对象:概念有类型
// 反例:String status = "paid"(无类型、无约束、拼错不报错)
"改名"的迁移要能"机械执行",否则"统一术语"会变成"半途而废":
// 三步迁移(每步可验证)
1 代码:新类型 + 旧类型标记 @Deprecated(并存)
2 数据:新列/新表双写,逐步切读
3 删除:确认"旧名调用量 0"后删
// 判据:每一步都能"单独回滚",而不是"一次切换"
5. "术语评审"的三种时机
| 时机 | 效果 |
|---|---|
| 设计阶段(新概念) | 最好(一次定名) |
| 代码评审(发现新词) | 好(成本低) |
| 事后统一(已三套) | 最贵(要迁移) |
第二项是"最划算"的:评审时问一句"这个词和我们术语表里的 X 是同一个吗"第二项的"问法"要具体:"这里的 Trade 和 Order 是同一个对象吗" 比"术语用对了吗"更能得到答案——因为它指向"两个具体的词"。
——成本一句话,收益是"阻止第四个名字出现"。
6. 排错:五种"术语表失效"
| 现象 | 成因 | 处理方向 |
|---|---|---|
| 表没人更新 | 与使用场景分离 | 术语进代码 |
| 新人不知道有表 | 无入口 | 放在"新人必读" |
| 同一概念多名字 | 无评审 | 评审时问一句 |
| 表太大没人看 | 全量登记 | 只留核心 10–15 条 |
| 定义模糊无法判定 | 只写"是什么" | 补"不是什么" |
第五项的"修法"是"三条边界 + 一个反例":它是/不是/是否与谁同义,加一个"看起来像但不是"的例子——于是"判定"有了依据。
第五项是"质量"问题:"订单:用户提交的购买请求" 这种定义无法判定边界——而"订单≠购物车、≠履约单"能。
"术语"与"命名规范"是两回事,别混在同一个文档里:
// 两种文档的分工
命名规范:怎么拼(驼峰、前缀、缩写表)→ 靠 linter 执行
术语表:叫什么(订单叫 Order 还是 Trade)→ 靠评审执行
// 反例:把"驼峰规则"写进术语表 → 术语表变成"风格手册",没人看
7. 边界:什么情况不必建术语表
| 场景 | 为什么 | 做法 |
|---|---|---|
| 单人项目 | 无沟通成本 | 不建 |
| 概念极少(< 5) | 不会混 | 不建 |
| 领域标准化(如会计) | 已有公认术语 | 沿用 |
| 短期项目 | 不长期 | 不建 |
判断口径一句话:"同一个词,两个人会不会理解成两个东西"。最后一条与"规模"有关的边界:术语表的"维护成本"随"概念数"线性增长,而"收益"集中在"前 15 条"——于是"想建全量表"通常是最快死掉的做法。
会(跨团队、跨系统、老系统遗留),就必须有"最小术语表 + 代码落地";不会(同团队共识清晰),建表只是增加维护负担。
最后一个"组织"现实:术语表往往由"最没权力改代码的人"维护(架构师、文档同学),而"改名"必须由"写代码的人"执行。所以"术语表"的落地前提不是"文档写得好",而是"改名的成本被降到可接受"——于是"并存 + 双写 + 确认后删"这套机械流程,比"一份更详细的定义"更重要。
再补一条"度量":"新增代码里出现"术语表之外的新词"的频率"。这个数不需要工具——每次评审记一行"出现了新词 X",一个月后就能看出"术语是否在漂"。频率高说明"领域在变"(该更新表),频率低说明"约束生效"。
还有一条"最便宜"的做法:在仓库根放一个 GLOSSARY.md,只写 10–15 条,且每条指向一个代码位置。它不需要 Wiki、不需要审批、不需要"全量",而它正好覆盖"最容易混的那几个词"——这也是"能活过三个月"的形态。
8. 自测
- 术语表的三种存放位置里,哪一种"真正被强制执行"?为什么?
- "三张表"为什么最贵?它让"对账"变成什么?
- 一条"够用"的术语记录有哪四项?为什么"它不是什么"比"它是什么"更有用?
- "术语与代码对齐"的三种机制里,哪一种最强?"枚举即术语"为什么能约束取值?
- 为什么"评审时问一句"是最划算的时机?
- 判断"是否需要术语表"的那个问题是什么?