重构与可读性:重构代码命名与结构,提升可读性
说实话,我见过太多代码了。有些代码像散文,读起来行云流水;有些代码像天书,看三行就想摔键盘。你猜哪种代码更容易出 Bug?
今天咱们聊聊可读性。这不是什么高大上的概念,说白了就是——别人(包括三个月后的你自己)能不能一眼看懂这段代码在干嘛。
我个人习惯把可读性重构分成两个维度:命名和结构。命名是微观层面的,结构是宏观层面的。两者缺一不可。
1. 命名:代码的「自我介绍」
先问个问题:你见过这样的变量名吗?
let a = 10;
let b = '张三';
let c = true;
嗯,我猜你见过。甚至可能写过。我在项目中遇到过最夸张的一次,有个同事用 a1、a2、a3 命名了十几个变量,最后他自己都分不清哪个是哪个了。
好的命名应该做到:看到名字就知道用途。
核心原则:
- 变量名用名词,函数名用动词
- 避免缩写,除非是行业通用缩写(如 HTML、API)
- 长度适中:太短含义不清,太长影响阅读
举个例子,这是重构前的代码:
function calc(a, b) {
return a * b + a * 0.1;
}
你能看出这个函数在算什么吗?反正我看不出来。重构一下:
function calculateTotalPrice(basePrice, quantity) {
const taxRate = 0.1;
return basePrice * quantity + basePrice * taxRate;
}
现在是不是清晰多了?calculateTotalPrice 告诉你这是算总价的,basePrice 是单价,quantity 是数量,taxRate 是税率。一目了然。
小技巧:命名时试着用英文完整描述变量的含义。比如 userList 比 list 好,activeUserList 比 userList 更好。但别走极端,listOfAllActiveUsersInTheCurrentSession 就太长了。
2. 结构:代码的「骨架」
命名搞定了,接下来看结构。结构问题往往比命名问题更隐蔽,也更致命。
我曾经接手过一个项目,一个函数写了 800 行。对,你没看错,800 行。里面混杂着数据库查询、业务逻辑、前端渲染、日志打印……我当时的心情,怎么说呢,就像打开了一个潘多拉魔盒。
好的结构应该遵循单一职责原则:一个函数只做一件事。
来看个例子:
function processOrder(order) {
// 验证订单
if (!order.items || order.items.length === 0) {
throw new Error('订单为空');
}
if (!order.userId) {
throw new Error('用户未登录');
}
// 计算价格
let total = 0;
for (let item of order.items) {
total += item.price * item.quantity;
}
if (order.coupon) {
total = total * 0.9;
}
// 保存订单
const savedOrder = database.save(order);
// 发送通知
email.send(order.userId, '订单已确认');
return savedOrder;
}
这个函数干了四件事:验证、计算、保存、通知。拆开它:
function validateOrder(order) {
if (!order.items || order.items.length === 0) {
throw new Error('订单为空');
}
if (!order.userId) {
throw new Error('用户未登录');
}
}
function calculateTotal(order) {
let total = 0;
for (let item of order.items) {
total += item.price * item.quantity;
}
if (order.coupon) {
total = total * 0.9;
}
return total;
}
function processOrder(order) {
validateOrder(order);
const total = calculateTotal(order);
const savedOrder = database.save({ ...order, total });
email.send(order.userId, '订单已确认');
return savedOrder;
}
现在 processOrder 变成了一个「指挥者」,它调用各个子函数。每个子函数只做一件事,测试起来也方便。你想测试价格计算逻辑?直接测 calculateTotal 就行,不用管验证和保存。
注意:拆分的粒度要适中。别把一个函数拆成十几个只有两三行的小函数,那样反而会增加阅读负担。我一般遵循「一个函数不超过 20 行」的原则,但这不是硬性规定,看具体情况。
3. 知识体系:一张图看懂
说了这么多,咱们用一张图来总结一下可读性重构的核心逻辑:
这张图展示了可读性重构的两个核心维度:命名和结构。两者相辅相成,缺一不可。命名好了,结构乱了,代码依然难读;结构好了,命名烂了,同样让人头疼。
4. 避坑指南
最后分享几个我踩过的坑:
- 过度抽象:我曾经为了「优雅」,把一个简单的 if-else 拆成了五个类加三个接口。结果呢?后来改需求的时候,我自己都找不到逻辑在哪。记住:可读性优先于「设计模式」。
- 注释当拐杖:如果代码需要大量注释才能看懂,说明代码本身有问题。好的代码应该是自解释的。注释应该解释「为什么」,而不是「是什么」。
- 忽略上下文:在某个模块里,
getData可能很清楚是获取用户数据。但在全局范围内,这个命名就太模糊了。命名时要考虑调用者的视角。
我的习惯:写完代码后,我会假装自己是第一次看到这段代码。如果三秒钟内看不懂某个变量或函数的作用,就说明命名或结构需要改进。这个方法虽然简单,但非常有效。
可读性重构不是锦上添花,而是雪中送炭。它直接关系到代码的维护成本、Bug 率,甚至团队的工作效率。下次写代码时,多花 30 秒想想命名和结构,你会感谢自己的。