《重构-改善既有代码的设计》- 重新组织函数
所谓的重构就是在不改变代码外部行为(功能)的情况下对代码进行内部修改以实现代码可读性、可维护性、可复用性以及可扩展性的大幅度增加,便于后续进行扩展和维护(直观提高代码可读性,利于定位Bug并加以修复)。
避免出现 “too-long" 方法,要求方法表现的逻辑简洁明了(concise and easy to understand)。
🍎【Extract Method】- 提炼方法
将代码放入一个独立方法中,并让方法的名称具有自我描述性
特点:
- 功能模块化
- 模块集成化
- 局部变量局部化
- 初始变量分离化
处理对象:
- 过长方法
- 方法包含的代码逻辑复杂混乱,直观性差。
实现目标:
降低方法粒度,提高方法复用性,让高层函数读起来像是(just like)读注释一样。
方法粒度小便于后续的复写、复用和扩展
class Order { private double price; public Order(double price){ this.price = price; } double getAmount(){ return this.price; } } public class Sample01 { private Vector<Order> _orders; private String _name; public Sample01(String name){ this._name = name; } //【高层函数】遵守"单一指责型"这个原则,实现模块(方法)功能独立 void printOwing(){ printBanner(); // print banner double outstanding = getOutstanding(); // calculate outstanding printDetails(_name,outstanding); // print details } // calculate outstanding 【局部变量局部化】 private double getOutstanding() { Enumeration e = _orders.elements(); double result = 0.0; while(e.hasMoreElements()){ Order order = (Order)e.nextElement(); result += order.getAmount(); } return result; } // print details private void printDetails(String username, Double outstanding) { System.out.println("username: " + username); System.out.println("amount: " + outstanding); } // print banner private void printBanner() { System.out.println("*************************"); System.out.println("***** Customer Owes *****"); System.out.println("*************************"); } } /** * the characteristic of Extract Method * 1. 局部变量局部化 * 2. 初始变量分离化 * 3. 功能模块化 * 4. 模块集成化 * */
🍎【Inline Method】- 内联方法
在函数调用点插入函数本体,然后移除函数
处理对象: 代码之间太多的间接层(间接层有价值但不是所有的间接层都有价值)
🍎【Inline Temp】- 内联临时变量
将所有对该变量的引用动作,替换为对它赋值的表达式本身
处理对象:减少临时变量的出现,只用通过内联表达式来达到临时变量的作用(内联临时变量要用于所替代临时变量只会被使用一次的情况下)
🍎【Replace Temp With Query】- 以查询取代临时变量
将这个表达式提炼到一个独立函数中。将这个临时变量的所有引用点替换为对新函数调用。
特点:
- 模块功能化
- 功能集成化
处理对象: 减少长函数的出现
确保提炼出来的函数无任何副作用,该函数并不修改任何对象内容。
运用此方法可能会存在性能方面的考虑,但如果性能真的出现问题可以在优化阶段解决。代码组织良好更有助于发现有效的优化方案
🍎【Introduce Explaining Variable】- 引入解释型变量
将该复杂表达式(或其中一部分)的结果放进一个临时比那辆,以此变量名称来解释表达式用途
处理好处: 通过自我描述性的变量代替冗杂、逻辑不清的表达式以提高代码可读性(concise and easy to understand)
public class Sample05 { private double _quantity; private double _itemPrice; // *************** initial version 1.0.0 *************** double calculatePrice01(){ // price is base_price - quantity_discount + shipping return _quantity * _itemPrice - Math.max(0, _quantity - 500) * _itemPrice * 0.05 + Math.min(_quantity * _itemPrice * 0.1, 100.0); } // *************** 【Introduce Explaining Variables】initial version 1.0.1 *************** double calculatePrice02(){ // price is base_price - quantity_discount + shipping final double basePrice = _quantity * _itemPrice; return basePrice - Math.max(0, _quantity - 500) * _itemPrice * 0.05 + Math.min(basePrice * 0.1, 100.0); } // *************** 【Introduce Explaining Variables】initial version 1.0.2 *************** double calculatePrice03(){ // price is base price - quantity discount + shipping final double basePrice = _quantity * _itemPrice; final double quantityDiscount = Math.max(0, _quantity - 500) * _itemPrice * 0.05; final double shipping = Math.min(basePrice * 0.1, 100.0); return basePrice - quantityDiscount + shipping; } // *************** 【Extract Method】initial version 1.0.3 *************** double calculatePrice04(){ return basePrice() - quantityDiscount() + shipping(); } private double basePrice(){ return _quantity * _itemPrice; } private double quantityDiscount(){ return Math.max(0, _quantity - 500) * _itemPrice * 0.05; } private double shipping(){ return Math.min(basePrice() * 0.1, 100.0); } // Concise and easy to understand }
🍎【Remove Assignments to Parameters】- 移除对参数的赋值
以一个临时变量取代该参数的位置
public class Sample07 { // ****************【Remove Assignments To Parameters】version 1.0.0 **************** int discount01(int inputVal, int quantity, int yearToDate){ if(inputVal > 50){ inputVal -= 2; } if(quantity > 100){ inputVal -= 1; } if(yearToDate > 10000){ inputVal -= 4; } return inputVal; } // ****************【Remove Assignments To Parameters】version 1.0.1 **************** int discount02(int inputVal, int quantity, int yearToDate){ int result = inputVal; if(inputVal > 50){ result -= 2; } if(quantity > 100){ result -= 1; } if(yearToDate > 10000){ result -= 4; } return result; } // ****************【Remove Assignments To Parameters】version 1.0.2 **************** int discount03(final int inputVal, final int quantity, final int yearToDate){ // final: 1. 保证变量一致性 2. 防止出现参数再次赋值 int result = inputVal; if(inputVal > 50){ result -= 2; } if(quantity > 100){ result -= 1; } if(yearToDate > 10000){ result -= 4; } return result; } // To implement compulsory no-assignment to parameter with the "final" keyword.(the "final" better use in too long method) }
🍎【Split Temporary Variable】- 分解临时变量
针对每次赋值,创建一个独立、对应的临时变量(临时变量的唯一化和遵守单一职责的原则)
🍎【Replace Method With Method Object】- 以函数对象取代函数
将这个方法放进一个单独对象中,如此一来局部变量就成了对象内的字段。然后可以在同一个对象中将这个大型方法分解为多个小型方法。
处理对象: 无法拆解的方法
处理好处:将相对独立的代码从大型函数中提炼处理啊,就可以大大提高代码的可读性。
class Account{ private int inputVal; private int quantity; private int yearToDate; // traditional Method int gamma01(int inputVal, int quantity, int yearToDate){ int importantValue1 = (inputVal * quantity) + delta(); int importantValue2 = (inputVal * yearToDate) + 100; if((yearToDate - importantValue1) > 100){ importantValue2 -= 20; } int importantValue3 = importantValue2 * 7; // and so on return importantValue3 - 2 * importantValue1; } int gamma02(int inputVal, int quantity, int yearToDate){ 【⭐️Nice Shot】 return new Gamma(this,inputVal,quantity,yearToDate).compute(); } int delta(){ return 1; } } // Method Object class Gamma{ private final Account _account; // The _account field must be used anywhere in a function that calls the Account class private int inputVal; private int quantity; private int yearToDate; // 【extract method】 // private int importantValue1; // private int importantValue2; // private int importantValue3; Gamma(Account source, int inputValArg, int quantityArg, int yearToDateArg){ this._account = source; this.inputVal = inputValArg; this.quantity = quantityArg; this.yearToDate = yearToDateArg; } // refactoring method int compute(){ if((yearToDate - importantValue1()) > 100){ return getImportantValue3(importantValue2() - 20) - 2 * importantValue1(); } return getImportantValue3(importantValue2()) - 2 * importantValue1(); } int importantValue1(){ return (inputVal * quantity) + _account.delta(); } int importantValue2(){ return (inputVal * yearToDate) + 100; } int getImportantValue3(int val){ return val * 7; } }
🍎【Substitute Algorithm】- 替换算法
把某个算法替换为另一个更清晰的算法
"重构"充分发挥
Divide and Conquer
的思想,将复杂的东西分解为小块。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具