代码命名指南
命名是编程中最被低估的工程问题:名字起得好,代码自己就是文档;起得差,每个读者都要付费重建一次理解。本文从”降低认知成本”出发,给出类、方法、变量的具体法则,讨论魔法值与领域语言,并赏析常见反例。
核心概念:命名的本质是降低认知成本
Martin Fowler 曾转述一个经典说法:计算机科学里只有两件难事——缓存失效和命名。命名难,因为它不是翻译问题而是抽象问题:一个名字背后是你对这段代码职责的理解,想不出好名字往往说明职责没切干净。读代码的时间远多于写代码,含糊的名字迫使读者反复跳转上下文、在心里维护一张临时映射表,认知成本就这样逐行累积。好名字的标准很朴素:读者不借助注释,就能说对这段代码”是什么、干什么”。
实践要点
类、方法、变量的基本法则
- 类用名词或名词短语,表达一个角色或职责:
OrderRepository、PricingPolicy。慎用Manager、Handler这类万能后缀,它们通常意味着职责还没想清楚。 - 方法用动词或动词短语:
calculateTax、sendInvoice。查询与命令要分清——getUserAndUpdateLastLogin把读和写揉在一起,调用方极易踩坑。 - 布尔量与布尔方法用
is/has/can/should前缀:isPaid、hasPermission,让if (order.isPaid())读起来像一句可验证的陈述。 - 集合用复数,时间金额带单位或币种:
timeoutSeconds、priceInCents,避免”这个值到底是秒还是毫秒”的悬案。 - 形态遵守语言惯例:Java 类名大驼峰,方法与变量小驼峰,常量大写蛇形,包名全小写且用单数名词。
消灭魔法值
散落在代码里的字面量是命名的重灾区:
// 反例:3 是什么?86400 又是什么? |
更进一步,状态码应收敛为枚举(如 UserStatus.DISABLED),既消灭魔法值,又能获得编译期检查,非法取值直接无法通过编译。
统一领域语言
同一个业务概念在代码里只能有一个名字。产品文档写”租户”,代码里却一会儿 tenant、一会儿 customer、一会儿 account,每个新人都要重建一次映射表,评审时间全花在猜词上。这正是领域驱动设计强调的通用语言(Ubiquitous Language):代码词汇表应与业务对话保持一致,发现不一致时优先改代码,而不是让团队背三套说法。内部改名交给 IDE 安全重构、随功能修改小步推进;对外接口的字段改名则要留兼容期,避免一次性巨型 diff 淹没评审。
常见误区
data、info、obj、temp:能编译,但信息量为零。- 无共识缩写:
CustomTF这类自创简写只有作者本人认识;HTTP、ID 这类通行缩写才安全。 - 类型冗余进名字:
nameString、userList里的类型信息,IDE 一眼可见。 - 用拼音命名如
dazhe:既难读又无法与领域术语对齐;alibaba、taobao 这类已国际化的专有名词除外。 - 名字靠注释解释:需要注释才能看懂的名字,该改的是名字本身。
- 反向布尔命名
isNotDeleted:双重否定逼读者做逻辑运算。 - 一词多义与多词一义并存:同一个
count在订单上下文指”条目数”、在库存上下文指”可用件数”,调用方极易张冠李戴;反过来,同一个”下单时间”被写成createTime、orderTime、submitTime三个字段,联调时只能靠猜。消除这类歧义,正是统一词汇表要解决的日常问题。
另外提醒一点:改名也要看收益。局部变量命名含糊但作用域只有三行,影响有限;公共 API、跨模块共享的枚举与消息字段,一旦起错名字,成本会随着调用方数量复利增长。把精力优先投向这些高杠杆位置,性价比最高。
小结
- 命名即抽象:起不出好名字,先回头检查职责划分。
- 立刻可落地的五条:类名词、方法动词、布尔 is/has、集合复数、量纲入名。
- 魔法值收敛为常量或枚举,业务术语全团队对齐,代码才会”自己会说话”。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Dai Wei!
评论

