读《重构-改善既有代码的设计》第六章:重新组织函数

本文介绍了《重构-改善既有代码的设计》第六章的主要内容,包括9种函数重构技术:提炼函数、内联函数、内联临时变量、以查询代替临时变量、引入解释性变量、分解临时变量、移除对参数的复制、以函数对象取代函数和替换算法。这些技术有助于提高代码可读性和复用性,强调在重构过程中应保持单一职责原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Extract Method(提炼函数)

将一段可以被组织在一起并可以独立出来的代码放进一个独立函数中,并让函数名称解释该函数的用途。
  • 如果每个函数的颗粒度都很小,那么函数被复用的机会就更大,复写也会更容易些,也会使高层函数越多企鹅来就像一系列的注释。
private void PrintOwing(int amount){
	int[] integers = _orders.integers();
	double intSum= 0;
	
	//print banner
	System.Console.Write("*****************************" );
	System.Console.Write("****** Sum Of Integers ******" );
	System.Console.Write("*****************************" );

	//calculate sum
	for(int i = 0;i<integers.Length;i++){
		intSum += integers[i];
	}

	//print details
	System.Console.Write("name:" + _name);
	System.Console.Write("sum:" + intSum);
} 
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓等价于↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
private void PrintOwing(int amount){
	PrintBanner();
	double intSum = GetIntSum();
	Detaile(intSum);
} 

private void PrintBanner(){
	System.Console.Write("*****************************" );
	System.Console.Write("****** Sum Of Integers ******" );
	System.Console.Write("*****************************" );
}

private void GetIntSum(){
	int[] integers = _orders.integers();
	double intSum= 0;
	for(int i = 0;i<integers.Length;i++){
		intSum += integers[i];
	}
}

private void Detaile(double intSum){
	System.Console.Write("name:" + _name);
	System.Console.Write("sum:" + intSum);
}

2、Inline Method(内联函数)

一个函数的本体与名称同样清楚易懂,那么在函数的调用点插入函数本体,然后移除该函数。
private int GetRating(){
	return (IsTopFive()) ? 1 : 0;
}

private bool IsTopFive(){
	return mRanking >5;
}
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓等价于↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
private int GetRating(){
	return  mRanking >5 ? 1 : 0;
}

3、Inline Temp(内联临时变量)

一个临时变量只被简单表达式复制一次,那么将对该变量的引用动作,替换成那个表达式自身。
int heroHp = Hero.currentHp;
return heroHp >= 0;
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓等价于↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
return Hero.currentHp >= 0;

4、Replace Temp with Query(以查询代替临时变量)

把一个由临时变量保存结果的表达式提炼到一个独立函数中,然后将这个变量的引用点换成该函数。
private float GetTotalPrice(){
	float basePrice = quatity * itemPrice;
	if(basePrice > 10) return basePrice * 0.9f;
	return basePrice;
}
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓等价于↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
private float GetTotalPrice(){
	if(GetBasePrice() > 10) return GetBasePrice()* 0.9f;
	return GetBasePrice();
}
private float  GetBasePrice(){
	return quatity * itemPrice;
}
  • 本方法一般配合提炼函数一起使用
  • 如果某个变量被多次复制,可以考虑使用分解临时变量将它分割成多个变量
  • 如果提炼出来的函数还有其他作用,就使用Separate Query from Modifer(将查询函数和修改函数分离)
  • 如果提取在循环中累加的变量,同时该循环有多个累加的变量,那么应该针对每个累加变量重复一遍循环。如:某 for 循环有3个累加的变量,那么就写3遍 for 循环,如果担心性能问题,那么在优化性能的阶段再优化。

5、Introduce Explaining Variable(引入解释性变量)

将一个复杂的表达式的结果放进一个临时变量。
private float GetTotalPrice(){
	return quatity * itemPrice - Math.max(0,quatity - 5) * itemPrice * 0.5f + 
		   Math.min(quatity * itemPrice * 0.2f, 1000);
}
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓等价于↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
private float GetTotalPrice(){
	float basePrice = quatity * itemPrice;
	float baseQuantity =Math.max(0,quatity - 5) * itemPrice * 0.5f ;
	float shiping = Math.min(basePrice  * 0.2f, 1000);
	
	return basePrice  - baseQuantity + shiping  ;
}

PS: 请一步只修改一个!也可把三个变量提成函数。
这一方法很像是提炼函数查询替代变量的结合体,具体如何运用,自斟酌。

6、Split Temporary Variable (分解临时变量)

float price = quatity * itemPrice;
System.Console.Write(price);
price  = quatity * itemPrice * 0.9f;
System.Console.Write(price);
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓等价于↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
float basePrice = quatity * itemPrice;
System.Console.Write(basePrice );
float discountPrice  = quatity * itemPrice * 0.9f;
System.Console.Write(discountPrice  );
  • 每个变量只承担一个责任。
    PS:上面的代码相当丑陋。

7、Remove Assignments to Parameters(移除对参数的复制)

private int Discount(int inputVal, int quantity , int yearToDate){
	if(inputVal > 10) inputVal -= 1;
	if(quantity > 10) inputVal -= 2;
	if(yearToDate > 10) inputVal -= 3;
	return inputVal;
} 
/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓等价于↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
private int Discount(int inputVal, int quantity , int yearToDate){
	int result = inputVal ;
	if(inputVal > 10) result -= 1;
	if(quantity > 10) result -= 2;
	if(yearToDate > 10) result -= 3;
	return result ;
} 
  • 当参数是引用类型时,直接修改会导致上层的也会修改。

8、Replace Method with Method Object(以函数对象取代函数)

一个大型函数无法使用**提取函数**时,着这个函数提成一个对象。

9、Substitute Algorithm(替换算法)

你想把某个算法替换成另一个算法时,将函数本体替换成另一个算法。
  • 准备好新算法,让他通过编译
  • 与就算发进行参照比较

PS:第六章完成,后面的内容大部分都是对本章手法的扩展与深入。一个良好的编码习惯是在日积月累的编码过程中积累。在编码过程中思考,在思考中优化,在优化中头秃。。。

上一章:读《重构-改善既有代码的设计》第四章:构筑测试体系

下一章:读《重构-改善既有代码的设计》第七章:在对象之间搬移特性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值