注释(Comments):坏味道识别与重构实战指南
注释(Comments):坏味道识别与重构实战指南24种代码坏味道系列 · 第24篇
1. 开篇场景你是否遇到过这样的代码:代码中充满了注释,每个步骤都有注释说明,但代码本身却难以理解,就像在一本难懂的书上写满了注释,但书本身就应该写得清楚?
12345678910111213141516171819202122232425262728293031// 这个方法计算用户的总费用// 参数:users - 用户列表// 返回:总费用double calc(std::vector<std::string> users) { double total = 0.0; // 初始化总费用为0 // 遍历所有用户 for (int i = 0; i < users.size(); i++) { std::string u = users[i]; // 获取当前用户 // 检查用户是否为空 if (u.empty()) { continue ...
被拒绝的遗赠(Refused Bequest):坏味道识别与重构实战指南
被拒绝的遗赠(Refused Bequest):坏味道识别与重构实战指南24种代码坏味道系列 · 第23篇
1. 开篇场景你是否遇到过这样的继承关系:子类继承了父类的方法和字段,但大部分都不需要或需要重写,就像继承了一笔”遗产”,但大部分都用不上,还要想办法处理?
123456789101112class BadVehicle { void drive() { /* ... */ } void fly() { /* ... */ } // ... 很多方法};class BadCar : public BadVehicle { void fly() override { std::cout << "Cars cannot fly!" << std::endl; // 拒绝继承的方法 } // hasWings, canFly 字段对汽车没用,但继承了};
这就是被拒绝的遗赠的典型症状。子 ...
纯数据类(Data Class):坏味道识别与重构实战指南
纯数据类(Data Class):坏味道识别与重构实战指南24种代码坏味道系列 · 第22篇
1. 开篇场景你是否遇到过这样的类:它只有数据字段和简单的getter/setter,所有业务逻辑都在使用这个类的地方,就像一个”空壳”,没有自己的行为?
123456789101112131415class BadPerson {public: std::string firstName; std::string lastName; int age; std::string email;};// 所有逻辑都在使用类中void processPerson(BadPerson& person) { std::string fullName = person.firstName + " " + person.lastName; if (person.age < 0 || person.age > 150) { // 验证逻辑 }}
这就是 ...
异曲同工的类(Alternative Classes with Different Interfaces):坏味道识别与重构实战指南
异曲同工的类(Alternative Classes with Different Interfaces):坏味道识别与重构实战指南24种代码坏味道系列 · 第21篇
1. 开篇场景你是否遇到过这样的代码:Rectangle 类使用 computeArea() 和 computePerimeter(),而 Box 类使用 area() 和 perimeter(),虽然功能相同,但接口不同,使用时需要记住不同的方法名?
123456789class Rectangle { double computeArea() const { return width * height; } double computePerimeter() const { return 2 * (width + height); }};class Box { double area() const { return length * breadth; } double perimeter() con ...
过大的类(Large Class):坏味道识别与重构实战指南
过大的类(Large Class):坏味道识别与重构实战指南24种代码坏味道系列 · 第20篇
1. 开篇场景你是否遇到过这样的类:它包含了用户管理、订单管理、支付管理、地址管理、购物车管理等多个功能,就像一个”万能工具箱”,虽然什么都能做,但找起工具来却要翻遍整个箱子?
12345678910111213141516class BadExample { // 用户相关字段 std::string userName; std::string userEmail; // ... 更多字段 // 订单相关字段 std::vector<int> orderIds; // ... 更多字段 // 支付相关字段 double balance; // ... 更多字段 // 50+ 方法处理各种功能};
这就是过大的类的典型症状。类承担了太多职责,包含太多字段和方法,就像一个”万能工具箱”,虽然功能齐全,但难以理解和维护。
当你需要修改某个功能时,你必须在庞大的类中查找和 ...
内幕交易(Insider Trading):坏味道识别与重构实战指南
内幕交易(Insider Trading):坏味道识别与重构实战指南24种代码坏味道系列 · 第19篇
1. 开篇场景你是否遇到过这样的代码:一个类过度访问另一个类的内部字段,直接操作另一个类的状态,就像在进行”内幕交易”,过度依赖另一个类的内部实现?
12345678910111213class BadOrder { void processOrder(BadCustomer& customer, double amount) { // 过度访问 Customer 的内部字段 std::string fullName = customer.firstName + " " + customer.lastName; // 直接操作 Customer 的内部状态 if (customer.isVip) { amount *= 0.9; } customer.balance -= amount; ...
中间人(Middle Man):坏味道识别与重构实战指南
中间人(Middle Man):坏味道识别与重构实战指南24种代码坏味道系列 · 第18篇
1. 开篇场景你是否遇到过这样的类:它的大部分方法只是简单地转发调用给另一个类,没有添加任何逻辑,就像一个”传话筒”,只是把消息传递过去?
12345678910class PersonManager { Person* person;public: std::string getName() { return person->getName(); // 只是简单地转发 } void setName(const std::string& n) { person->setName(n); // 只是简单地转发 }};
这就是中间人的典型症状。类的大部分方法只是简单地委托给另一个类,没有添加价值,就像一个”传话筒”,只是把消息传递过去,没有添加任何信息。
当你需要理解代码时,你必须穿过这些中间层。当你需要修改代码时,你必须在多个层次中查找和修改。这种设计 ...
过长的消息链(Message Chains):坏味道识别与重构实战指南
过长的消息链(Message Chains):坏味道识别与重构实战指南24种代码坏味道系列 · 第17篇
1. 开篇场景你是否遇到过这样的代码:连续调用多个方法,形成过长的调用链,就像一条长长的链条,任何一个环节断裂都会导致整个链条失效?
12345678void printEmployeeCity(Employee* employee) { // 过长的调用链:employee -> company -> address -> city if (employee != nullptr && employee->company != nullptr && employee->company->address != nullptr) { std::cout << "City: " << employee->company->address->city << std:: ...
临时字段(Temporary Field):坏味道识别与重构实战指南
临时字段(Temporary Field):坏味道识别与重构实战指南24种代码坏味道系列 · 第16篇
1. 开篇场景你是否遇到过这样的类:某些字段只在特定方法中使用,大部分时间为空或无效,就像房间里有一些”临时家具”,只在特定场合使用,平时占地方?
12345678910111213141516171819class 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. 开篇场景你是否遇到过这样的代码:为了”将来可能支持多种数据库”而创建了抽象接口,但实际上只使用了一种数据库;为了”将来可能支持多种格式”而创建了格式化器接口,但实际上只使用了一种格式?
1234567class DatabaseConnection { virtual void connect() = 0; virtual void disconnect() = 0;};class MySQLConnection : public DatabaseConnection { /* ... */ };class PostgreSQLConnection : public DatabaseConnection { /* ... */ }; // 从未使用
这就是夸夸其谈通用性的典型症状。为了”将来可能用到”而添加的过度抽象,实际上从未使用,就像买了一堆”可能用到的工具”,但从未真正使用 ...
