写了几年代码,我总结了 7 条变量命名经验

3 阅读4分钟

在阅读《重构:改善既有代码的设计》时,第一条坏味道就是 Mysterious Name(神秘命名)

很多代码的问题,其实不是逻辑复杂,而是名字太差

好的命名应该清晰表达变量的用途和业务含义。

在所有重构手法中,改名(Rename)是最常用、也最值得投入时间的操作

如果你发现自己想不出一个好名字,往往说明:
代码背后可能存在设计问题。


一、为什么命名这么重要

代码阅读的成本,大部分来自 理解变量含义

例如:

let data = {}
let obj = {}
let temp = []

这些名字几乎没有提供任何信息。

而如果写成:

let customer = {}
let orderList = []
let totalPrice = 0

读者几乎不用思考就能理解代码。

所以命名的本质是:

降低理解成本。


二、如何命名(实践经验)

结合书中的建议和自己的实践,我总结了几个常用原则。

1. 表达业务含义,而不是技术细节

不要写:

data
obj
tmp

而是:

customer
orderList
totalPrice

命名应该反映业务语义。


2. 避免无意义缩写

例如:

usr
cfg
msgLst

可读性很差。

更好的写法:

user
config
messageList

除非是非常通用的缩写

  • id
  • url
  • api
  • db

否则尽量避免。


3. 命名体现数据结构

名字最好能反映数据结构。

例如:

customer        // 单个对象
customers       // 数组
customerList    // 列表

对于 Map / Dictionary:

customerById
userById
productIndex

这种命名在大型代码库中非常常见。


4. 在 JS/TS 中补充类型信息

《重构》里提到一句话:

在 JavaScript 这样的动态类型语言中,我喜欢把类型信息也放进名字里。

例如:

aCustomer

我觉得这个实践在 JS / TS 中仍然有价值。

常见命名模式:

单个对象

customer
aCustomer

集合

customers
customerList

Map / 字典

customerMap
customerById
productIndex

布尔值

isActive
hasPermission
canEdit

即使在 TypeScript 时代,命名依然重要。

因为很多代码库虽然用了 TS,但实际写法仍然接近 JS。
而好的命名可以显著降低阅读成本。

事实上,很多源码(如 Vue / React)也大量采用这种实践。


5. 根据作用域控制命名长度

命名不是越长越好,而是与作用域匹配

局部表达式

例如:

array.map(x => x.id)

一个字母完全没问题。


短函数参数

function sum(a, b) {
  return a + b
}

简短即可。


跨函数或复杂业务变量

如果变量在多个函数中使用,就需要更明确的命名:

currentLoginUser
selectedCustomerList
pendingPaymentOrders

三、封装变量(Encapsulate Variable)

书中的另一个建议是:

如果变量被广泛使用,可以考虑 封装变量

核心思想是:

不要让变量被随意修改。

例如:

let price = 100

改为:

function getPrice() {
  return price
}

function setPrice(value) {
  price = value
}

这样可以:

  • 控制修改入口
  • 降低耦合
  • 更容易维护

本质上就是:

将数据访问收敛到函数中。


四、注意“已发布变量”

书中还有一个非常重要的概念:

Published Variable(已发布变量)

如果变量已经被外部代码使用,就不能随便重构。

例如:

  • npm 包 API
  • SDK 导出变量
  • 服务接口字段
  • window/global 全局配置

示例:

window.APP_CONFIG

如果你直接重命名,很可能会导致外部系统崩溃。

正确做法应该是 兼容迁移

旧变量 -> 标记废弃 -> 用户迁移 -> 大版本删除

例如:

// deprecated
window.APP_CONFIG = config

window.appConfig = config

等用户迁移完成后,在下一次 major version 删除旧变量。


五、引申:代码所有权边界

这背后其实是一个更大的设计理念:

代码所有权边界(Ownership Boundary)

一个真实系统往往包含:

  • library
  • SDK
  • API
  • 服务
  • 数据库

如果没有明确的边界,就无法判断:

哪些代码可以安全重构,哪些不可以。

所以:

重构的前提是清楚代码的边界。


六、安全重命名的一种技巧

如果变量是 不可变的,可以采用一种更安全的方式重命名。

例如:

const oldVar = "PUBLIC_KEY_STRING"

步骤:

1️⃣ 新建变量

const newVar = "PUBLIC_KEY_STRING"
const oldVar = newVar

2️⃣ 逐步替换使用代码

3️⃣ 每次修改后运行测试

4️⃣ 最终删除旧变量

这样做的原因是:

JavaScript 可能存在动态访问:

obj['oldVar']

如果直接替换,很容易漏掉。

因此:

重命名之后一定要跑测试。


七、IDE 的重命名重构

很多人会用 全局搜索替换

但这其实不是重构功能,很容易改错。

现代 IDE 都支持 语义级 Rename

常见快捷键:

IntelliJ IDEA

Shift + F6

VSCode

F2

VSCode 依赖:

Language Server Protocol (LSP)

才能正确识别符号引用。


总结

好的命名,本质是让代码 更容易理解

核心原则:

1️⃣ 表达业务语义,而不是技术细节
2️⃣ 避免无意义缩写
3️⃣ 命名体现数据结构
4️⃣ 在 JS/TS 中适当补充类型信息
5️⃣ 根据作用域控制命名长度

另外要注意:

  • 已发布变量不要随便重构
  • 理解代码所有权边界
  • 使用 IDE 的 Rename 功能