文章目录
Clean Code: The Art of Naming
“There are only two hard things in Computer Science: cache invalidation and naming things.”
“计算机科学中只有两件难事:缓存失效和命名。”
— Phil Karlton
在软件开发的世界里,我们往往花费大量时间在算法优化和架构设计上,却容易忽视最基础的环节——命名。实际上,代码被阅读的次数远多于被编写的次数。一个好的名字能让代码像散文一样流畅,而糟糕的命名则是逻辑混乱和Bug滋生的温床。
本文将深入探讨为什么命名如此重要,并提供一套切实可行的命名指南。
1. 为什么要好好命名 (Why Good Name Matters)
名字是代码的第一张名片。
当开发者接手一个遗留项目时,如果看到的是 var d、function proc(),他的认知负荷会瞬间飙升;反之,如果看到的是 daysSinceCreation、calculateRevenue(),逻辑便不言自明。
核心价值 (Core Values)
- 意图传达 (Intent): 名字应该告诉读者它是什么,为什么存在,以及如何使用。
- 沟通成本 (Communication): 代码是写给人看的,顺便给机器执行。好的命名减少了团队间的沟通障碍。
- 维护性 (Maintainability): 语义清晰的代码更容易重构和扩展。
💡 影响分析思维导图
2. 选择好名字的基石 (Choosing Good Names)
2.1 意义明确 (Meaningful)
名副其实是首要规则。如果一个名称需要注释来补充说明,那它就不合格。
-
❌ Bad:
int d; // 经过的时间(天数) -
✅ Good:
int elapsedDays;或int daysSinceCreation; -
❌ Bad:
List<int> list; // 存储标记过的单元格 -
✅ Good:
List<int> flaggedCells;
2.2 命名风格与大小写 (Name Casing)
统一的风格是团队协作的基础。不同的语言有不同的惯例,但在同一项目中必须保持一致。
| 风格名称 | 示例 | 适用场景 (常见约定) |
|---|---|---|
| camelCase (小驼峰) | userName, isValid | 变量, 函数, 方法, 属性 (Java, JS, Swift) |
| PascalCase (大驼峰) | UserService, HttpClient | 类, 接口, 构造函数 (C#, Java, TS) |
| SNAKE_CASE (蛇形) | MAX_RETRY_COUNT, API_KEY | 常量, 环境变量 |
| kebab-case (烤串形) | user-profile.css, main-header | 文件名, URL, CSS类名 |
3. 变量与属性的命名 (Naming Variables & Properties)
3.1 理论基础 (Theory)
- 使用名词 (Nouns): 变量代表的是“数据”或“状态”,应使用名词或名词短语。
- 具体胜于抽象 (Specificity): 避免使用
data,info,value这样宽泛的词,除非是在非常局部的循环中。 - 布尔值 (Booleans): 应加上
is,has,can,should前缀,使其读起来像一个问句。
3.2 决策流程图
在定义变量时,可以遵循以下心智模型:
3.3 源码示例 (Examples)
场景:购物车结算
❌ 糟糕的代码:
// 即使写了注释,阅读也很累
let l = []; // 商品列表
let p = 0; // 总价
let f = false; // 是否包含折扣
l.forEach(x => {
p += x.pri; // pri 是什么?price? priority?
if (x.t === 1) f = true;
});
✅ 优雅的代码:
const cartItems = [];
let totalPrice = 0;
let hasDiscountItem = false;
cartItems.forEach(item => {
totalPrice += item.price;
if (item.type === ItemType.DISCOUNTABLE) {
hasDiscountItem = true;
}
});
解析:
l→ \to →cartItems:表明它是集合,且存放的是商品。f→ \to →hasDiscountItem:布尔值前缀,含义一目了然。
4. 函数与方法的命名 (Naming Functions & Methods)
4.1 理论基础 (Theory)
- 使用动词 (Verbs): 函数执行动作,必须以动词开头。
- 动词+名词结构:
verbObject(例如getUser,postPayment)。 - 单一职责暗示: 如果函数名包含
And(例如validateAndSave),通常意味着该函数做的事情太多了,应该拆分。 - 一致性: 动作词汇要统一。
- 不要混用
fetch,retrieve,get来表示同一个动作。 - 不要混用
delete,remove,destroy。
- 不要混用
4.2 常用动词对照表
| 动作类型 | 推荐动词 | 示例 |
|---|---|---|
| 获取数据 | get, fetch | getUserById |
| 查询判断 | is, has, can | isValid |
| 数据转换 | to, parse, format | toString, parseJson |
| 执行操作 | create, update, delete | createAccount |
| 计算逻辑 | calculate, compute | calculateTax |
4.3 序列图示例 (Sequence Diagram)
好的方法命名能让调用流程像讲故事一样清晰。
4.4 源码示例 (Examples)
❌ 模棱两可:
public void handle(User user) {
// 到底是保存用户、删除用户还是发送邮件?
// 这个名字没有任何信息量
}
✅ 意图清晰:
public void registerUser(User user) {
validateUserInfo(user);
userRepository.save(user);
sendWelcomeEmail(user);
}
5. 类的命名 (Naming Classes)
5.1 理论基础 (Theory)
- 名词或名词短语: 类是对象的模板,应该是一个名词。
- 避免通用后缀: 尽量避免
Manager,Processor,Data,Info这种“万金油”后缀,因为它们往往暗示类承担了过多责任(上帝类)。 - 设计模式体现: 如果使用了特定模式,可以在名字中体现,如
UserFactory,OrderBuilder,PaymentStrategy。
5.2 类的层级与命名
通过类图展示命名如何体现架构分层。
5.3 源码示例 (Examples)
❌ 糟糕的命名:
class Program:
# 这是一个具体的业务类,却叫 Program?
def execute(self):
pass
class Info:
# 什么信息?
pass
✅ 优雅的命名:
class ReportGenerator:
# 明确:它是生成报告的
def generate_pdf(self, data):
pass
class CustomerProfile:
# 明确:它是客户资料实体
def __init__(self, name, address):
self.name = name
self.address = address
总结 (Conclusion)
好的命名不仅仅是代码风格的问题,它是一种以读者为中心的编程思维。
- Variables 就像故事中的角色,要有清晰的身份(名词)。
- Functions 就像角色的动作,要有明确的行为(动词)。
- Classes 就像故事的场景或归类,要有具体的定义(具体名词)。
当你为了给一个变量起名而停顿思考时,不要感到浪费时间。你在为未来阅读这段代码的所有人(包括两周后的你自己)节省数小时的调试时间。
Action Item: 在今天的 Code Review 中,试着挑出一个命名不清晰的变量,并重构它。
706



被折叠的 条评论
为什么被折叠?



