重构带来的好处为何?如何重构?
2023年3月3日
💎 加入 E+ 成長計畫 與超過 500+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源
什么是重构?
重构 (Refactoring)指的是「在不改变外部行为的情况下,重组代码的过程」,因此对于外部用户而言,重构与否是没有感觉的,但重构的好处在于:
- 提高可读性:通过重构,代码变得更加清晰、简洁,并且具有更好的组织结构,从而提高可读性和理解难度。
- 提高可维护性:重构后的代码更加清晰,易于理解和修改,这有助于维护。
- 减少冗余:重构可以删除无用的代码、合并重复的代码和重新组织代码,从而减少代码冗余。
- 提高性能:重构可以帮助提高代码性能,例如通过减少循环次数和使用更高效的数据结构等。
- 改善安全性:通过重构,可以删除容易被攻击的代码,提高代码的安全性。
何时该重构?
重构是一个持续发生的过程,而遇到以下的状况时,都很适合开始着手重构:
- 代码重复:通过重构可以消除重复的代码,使代码库更加简洁。
- 技术债务:随着时间的推移,代码库可能变得混乱且难以维护,导致技术债务的累积。通过改善代码的结构和组织,重构可以减少这种债务。
- 添加新功能:在给现有代码添加新功能时,重构可以确保代码仍然易于维护和可扩展。
- 性能优化:如果代码运行过慢或需要太多资源,重构可以通过解决瓶颈和低效率来提高性能。
- 错误修复:重构可以使得更容易找到并修复代码中的错误,同时防止新的错误被引入。
- 团队合作:如果多个开发人员正在对同一代码库进行工作,重构可以通过使代码更容易理解和维护来提高合作。
如何重构?
好的重构建议是能够切得够小去做,并且不影响到外部行为,这里介绍几个常见的技术:
Red-Green-Refactor
Red-Green-Refactor 是一种软件开发流程,通常用测试驱动开发 (TDD),此流程分成三个步骤:
- Red(红色):开发人员首先编写一个失败的测试,以验证所需的功能不存在或不正确。
- Green(绿色):开发人员接着编写最少的代码来通过测试。
- Refactor(重构):开发人员再次检查代码,以确保其结构正确、可维护和易于理解。
如上图所示,通过这种方式,开发人员可以保证代码符合标准,同时避免因复杂的代码而导致的混乱。这种方法有助于确保代码质量,并通过经常测试来确保程序的正确性。
抽象化(Abstraction)
如果有很多地方需要做重构,可以用抽象化(Abstraction)的方式来做类继承、层次结构和提取,目标是减少重复且不必要得代码。
上图为 Pull-Up 和 Push-Down 的方法,Pull-Up 是将方法从子类移动到父类,Push-Down 则是将方法从父类别移动到子类别。
合成方法(Composing Method)
- Extract Method:如果有一段代码能够被独立出来,则将它放到独立的函数中,并让函数名称解释该函数用途。下方有重构前后的范例。
原来的代码为:
void Process(MyDataSet mds) {
int result = 0;
if (mds.isReady) {
int data1 = mds.param[0];
int data2 = mds.param[1];
result = data1 % data2;
}
}
重构后的代码为:
void Process(MyDataSet mds){
int result = 0;
if (mds.isReady)
result = CalculateMDS(mds.param[0], mds.param[1]);
}
int CalculateMDS(int data1, int data2) {
return data1 % data2;
}
可以将不易理解的代码,放入新方法中,并且取一个有意义的命名,这样可以提高可读性和可维护性。
- Inline Method: 在函数调用的地方,直接插入函数本体,并且移除函数。下方有重构前后的范例。
原来的代码为:
class PizzaDelivery {
// ...
int getRating() {
return moreThanFiveLateDeliveries() ? 2 : 1;
}
boolean moreThanFiveLateDeliveries() {
return numberOfLateDeliveries > 5;
}
}
重构后的代码为:
class PizzaDelivery {
// ...
int getRating() {
return numberOfLateDeliveries > 5 ? 2 : 1;
}
}
如果有些函数里面的代码,和函数名其实同样的清晰易懂,就可以直接去掉函数就好。