第二讲:代码坏味道识别——那些让你头疼的“代码病”
大家好,欢迎来到第二讲。上一讲我们聊了重构的价值,今天咱们来点实在的——怎么一眼看出代码里藏着哪些“坏味道”。
说实话,我刚开始做C++开发那几年,根本不懂什么叫“坏味道”。代码能跑就行,管它长什么样。直到有一次,我接手一个遗留项目,打开一个源文件,好家伙,光一个函数就800多行。我盯着屏幕看了十分钟,愣是没看懂它在干嘛。那一刻我才明白——代码的“味道”,真的很重要。
今天我们就来聊聊最常见的几种坏味道。你想想看,是不是经常遇到?
1. 重复代码——最臭的味道
重复代码,说白了就是“复制粘贴”的后遗症。我见过最夸张的,一个项目里同样的排序逻辑出现了7次,每次就改了个变量名。
典型症状:
- 相同的逻辑出现在多个函数中
- 相似的循环结构反复出现
- 几乎一样的if-else分支
// 坏味道:重复代码
void processOrderA() {
for (int i = 0; i < items.size(); i++) {
if (items[i].price > 100) {
applyDiscount(items[i], 0.9);
}
}
}
void processOrderB() {
for (int i = 0; i < items.size(); i++) {
if (items[i].price > 100) {
applyDiscount(items[i], 0.9); // 完全一样!
}
}
}
我的经验:遇到重复代码,别犹豫,直接提取成函数。我曾经在一个模块里提取了5个公共函数,代码量直接减少40%。
2. 过长函数——一眼望不到头
一个函数超过50行,我就开始警惕了。超过100行?那基本可以断定,这个函数至少干了三件事。
为什么会这样?因为很多人习惯把“所有逻辑”塞进一个函数里。我见过一个函数,从读取配置文件、解析数据、计算统计、生成报表到发送邮件,全在一个函数里完成。你想想看,这怎么维护?
// 坏味道:过长函数
void processData() {
// 读取文件(30行)
// 解析数据(50行)
// 计算统计(40行)
// 生成报表(60行)
// 发送邮件(20行)
// 总共200行!
}
避坑指南:我曾经把一个300行的函数拆成6个小函数,每个函数只做一件事。结果呢?bug率下降了70%。记住:一个函数只做一件事,做好一件事。
3. 过大的类——上帝类的诞生
一个类超过500行?嗯,这很可能是“上帝类”的前兆。上帝类,就是那种什么都能干、什么都往里塞的类。
我个人习惯,一个类的职责应该单一。如果一个类既负责数据存储,又负责业务逻辑,还负责界面展示,那它迟早会变成一团乱麻。
| 类的大小 | 建议 |
|---|---|
| < 200行 | 正常 |
| 200-500行 | 需要审视 |
| > 500行 | 必须拆分 |
4. 过长参数列表——函数签名像购物清单
一个函数有6个以上参数?我建议你停下来想想。参数越多,调用越容易出错,测试越难写。
我记得有一次,一个同事写了个函数,参数列表长达12个。每次调用都要对着文档一个一个填,填错一个就出bug。后来我们把它改成了参数对象,世界清净了。
// 坏味道:过长参数列表
void createOrder(int userId, int productId, double price,
int quantity, string address, string phone,
string couponCode, int paymentMethod) {
// ...
}
// 改进:使用参数对象
struct OrderParams {
int userId;
int productId;
double price;
int quantity;
string address;
string phone;
string couponCode;
int paymentMethod;
};
void createOrder(const OrderParams& params) {
// ...
}
5. 发散式变化——改一处,动全身
发散式变化,说白了就是“牵一发而动全身”。当你修改一个功能时,需要改动多个不同的类或模块,这就是发散式变化。
我遇到过最典型的例子:一个支付系统,每次新增支付方式,都要修改订单类、支付类、日志类、报表类……改得人心力交瘁。
判断标准:如果同一个原因(比如新增支付方式)导致你修改了3个以上的文件,那就有问题了。
知识体系总览
下面这张图,是我自己总结的代码坏味道识别框架。你可以把它当作一个检查清单,每次review代码时对照着看。
如何快速识别?我的实战技巧
说了这么多,你可能想问:有没有快速识别的方法?当然有。我总结了一套“三看”法则:
- 看长度:函数超过50行、类超过300行、参数超过5个,直接标记
- 看重复:搜索代码库,相同的代码片段出现2次以上,必须提取
- 看变化:每次需求变更,需要改动的文件数超过3个,说明设计有问题
我的小工具:我习惯用clang-tidy的静态分析功能,它能自动检测出很多坏味道。比如过长函数、过大的类、重复代码等。配合代码review,效果翻倍。
好了,这一讲的内容就到这里。记住:识别坏味道不是目的,目的是让代码变得更好。下一讲,我们会深入讨论如何用设计模式来消除这些坏味道。
可可精品资料库