临时字段(Temporary Field):坏味道识别与重构实战指南
临时字段(Temporary Field):坏味道识别与重构实战指南24种代码坏味道系列 · 第16篇
1. 开篇场景你是否遇到过这样的类:某些字段只在特定方法中使用,大部分时间为空或无效,就像房间里有一些”临时家具”,只在特定场合使用,平时占地方?
class BadExample {
std::string name;
int age;
// 临时字段:只在 calculateTax 方法中使用
double monthlyIncome;
double monthlyExpense;
bool isTaxCalculationMode;
double calculateTax(double income, double expense) {
isTaxCalculationMode = true;
monthlyIncome = income;
monthlyExpense = expense;
// ... 计算逻辑
...
夸夸其谈通用性(Speculative Generality):坏味道识别与重构实战指南
夸夸其谈通用性(Speculative Generality):坏味道识别与重构实战指南24种代码坏味道系列 · 第15篇
1. 开篇场景你是否遇到过这样的代码:为了”将来可能支持多种数据库”而创建了抽象接口,但实际上只使用了一种数据库;为了”将来可能支持多种格式”而创建了格式化器接口,但实际上只使用了一种格式?
class DatabaseConnection {
virtual void connect() = 0;
virtual void disconnect() = 0;
};
class MySQLConnection : public DatabaseConnection { /* ... */ };
class PostgreSQLConnection : public DatabaseConnection { /* ... */ }; // 从未使用
这就是夸夸其谈通用性的典型症状。为了”将来可能用到”而添加的过度抽象,实际上从未使用,就像买了一堆”可能用到的工具”,但从未真正使用过 ...
冗赘的元素(Lazy Element):坏味道识别与重构实战指南
冗赘的元素(Lazy Element):坏味道识别与重构实战指南24种代码坏味道系列 · 第14篇
1. 开篇场景你是否遇到过这样的代码:一个 StringWrapper 类只是简单地包装了 std::string,没有添加任何额外功能;一个 getName 方法只是简单地返回 name.getValue(),没有添加任何逻辑?
class StringWrapper {
std::string value;
public:
std::string getValue() { return value; }
void setValue(const std::string& str) { value = str; }
};
class BadExample {
StringWrapper name;
public:
std::string getName() {
return name.getValue(); // 只是简单地转发
...
循环语句(Loops):坏味道识别与重构实战指南
循环语句(Loops):坏味道识别与重构实战指南24种代码坏味道系列 · 第13篇
1. 开篇场景你是否遇到过这样的代码:使用 for 循环过滤、转换、求和、查找,虽然功能正确,但代码冗长且不够声明式?
std::vector<int> filterEvenNumbers(const std::vector<int>& numbers) {
std::vector<int> result;
for (int i = 0; i < numbers.size(); i++) {
if (numbers[i] % 2 == 0) {
result.push_back(numbers[i]);
}
}
return result;
}
这就是循环语句的典型症状。使用命令式循环处理集合,虽然可以工作,但代码冗长且不够声明式。现代C++提供了丰富的STL算法,可以更简洁、更安全地处理集合操作。
当 ...
重复的switch(Repeated Switches):坏味道识别与重构实战指南
重复的switch(Repeated Switches):坏味道识别与重构实战指南24种代码坏味道系列 · 第12篇
1. 开篇场景你是否遇到过这样的代码:相同的 switch 语句在多个地方重复出现,每次添加新的分支时,都需要在所有地方同步修改?
double calculateDiscount(UserType type, double price) {
switch (type) {
case UserType::REGULAR: return price * 0.0;
case UserType::VIP: return price * 0.1;
case UserType::PREMIUM: return price * 0.2;
}
}
int getMaxItems(UserType type) {
// 相同的 switch 逻辑重复了
switch (type) {
case UserType::REGULA ...
基本类型偏执(Primitive Obsession):坏味道识别与重构实战指南
基本类型偏执(Primitive Obsession):坏味道识别与重构实战指南24种代码坏味道系列 · 第11篇
1. 开篇场景你是否遇到过这样的代码:使用 std::string 表示邮箱地址,但没有验证;使用 std::string 表示电话号码,但没有验证;使用 int 表示年龄,但没有范围检查?
void sendEmail(std::string email, std::string subject, std::string body) {
// 使用 string 表示邮箱,但没有验证
std::cout << "Sending email to: " << email << std::endl;
}
void setAge(int age) {
// age 可能是负数或很大的数,但没有范围检查
std::cout << "Age set to: " << age << std::endl;
...
数据泥团(Data Clumps):坏味道识别与重构实战指南
数据泥团(Data Clumps):坏味道识别与重构实战指南24种代码坏味道系列 · 第10篇
1. 开篇场景你是否遇到过这样的代码:firstName 和 lastName 总是成对出现,street、city 和 zipCode 也总是同时传递,但它们却作为独立的参数在多个函数间传递?
void createUser(std::string firstName, std::string lastName,
std::string street, std::string city,
std::string zipCode) {
// firstName, lastName 总是成对出现
// street, city, zipCode 总是成对出现
}
void updateUser(std::string firstName, std::string lastName,
std::string street, std::string city, ...
依恋情结(Feature Envy):坏味道识别与重构实战指南
依恋情结(Feature Envy):坏味道识别与重构实战指南24种代码坏味道系列 · 第9篇
1. 开篇场景你是否遇到过这样的方法:它在一个类中,但大部分时间都在访问另一个类的数据,就像一个人住在A城市,但每天都要跑到B城市去工作?
class OrderCalculator {
public:
double calculateTotal(Order& order) {
// 这个方法频繁访问 Order 的字段,应该属于 Order 类
double discountedPrice = order.basePrice * (1.0 - order.discount);
double total = discountedPrice + (discountedPrice * order.tax);
return total;
}
};
这就是依恋情结的典型症状。一个方法过度使用另一个类的数据,应该移到那个类中。方法对另一个类的”依恋”超过了对自己所在类的 ...
霰弹式修改(Shotgun Surgery):坏味道识别与重构实战指南
霰弹式修改(Shotgun Surgery):坏味道识别与重构实战指南24种代码坏味道系列 · 第8篇
1. 开篇场景你是否遇到过这样的场景:需要修改用户验证规则(如最小长度从3改为5),却发现需要在 UserService、UserController、UserRepository 等多个类中逐一修改相同的验证逻辑?
// 需要在多个类中修改相同的验证逻辑
class UserService {
void createUser(const std::string& username) {
if (username.length() < 3) { // 需要修改这里
// ...
}
}
};
class UserController {
void registerUser(const std::string& username) {
if (username.length() &l ...
发散式变化(Divergent Change):坏味道识别与重构实战指南
发散式变化(Divergent Change):坏味道识别与重构实战指南24种代码坏味道系列 · 第7篇
1. 开篇场景你是否遇到过这样的类:当数据库格式改变时,需要修改它;当XML格式改变时,需要修改它;当计算逻辑改变时,也需要修改它?一个类因为多种不同的原因需要修改,就像一台多功能机器,任何一个功能出问题都需要整台机器停下来维修。
class BadExample {
// 原因1:数据库格式改变 → 修改这里
std::string toDatabaseFormat() const { /* ... */ }
// 原因2:XML格式改变 → 修改这里
std::string toXMLFormat() const { /* ... */ }
// 原因3:计算逻辑改变 → 修改这里
double calculateTax() const { /* ... */ }
// 原因4:显示格式改变 → 修改这里
voi ...
