七、重构4:使用“以查询取代临时变量”再次对Statement()方法进行重构
1. 经过了之前几篇文章的重构后,Customer中的statement()方法的具体代码,如下图所示。在计算每部电影的金额和积分时,我们调用的是Rental类的对象的相应的方法。下图中的方法与充电项计费项目的原始代码中的方法相比可谓是简洁了许多,而且易于理解与维护。
2.不过上面的代码仍然有重构的空间,举个例子,如果我们要将结果以HTML的形式进行组织的话,我们需要将上面的代码进行复制,然后修改result变量的文本组织方式即可。这可能就是程序员经常做的事情Ctrl+C、Ctrl+V,很多程序员是这样来修改代码的,这种修改代码快速,功能实现方便,但是这样的修改代码会给我们的系统遗留很多无用的代码。使用Ctrl+C、Ctrl+V这种非常方便的方式来修改代码,会造成方法中的好多临时变量都被复制一份,这是完全相同的,这样就容易产生重复的代码。在这种情况下,我们需要使用“Replace Temp with Query”(已查询取代临时变量)的重构手法来取出上图所示的红框中的临时变量。
上图中红框所框出来的每个临时变量我们都会提取出一个查询方法,下图中所示的代码,就是使用“Replace Temp with Query”(已查询取代临时变量)规则重构后的Statement()方法,以及提取的两个查询函数。
3.经过上面这些步骤的重构,Customer类的具体代码如下所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LeasePowerBank
{
/// <summary>
/// 客户类
/// </summary>
public class Customer
{
string Name;//用户名称
public List<Rental> listRentals=new List<Rental>();//用户租赁的充电宝
public Customer(string name)
{
Name = name;
}
public void AddRental(Rental rental)
{
listRentals.Add(rental);
}
public string Statement()
{
string result = $"{Name} 的租赁账单:
";
result += $"总金额为:{GetTotalAmount()}
";
result += $"你本次获得了:{GetTotalFrequentRenterPoints()}积分 ";
return result;
}
/// <summary>
/// 计算总金额
/// </summary>
private decimal GetTotalAmount()
{
decimal totalAmount = 0M; //总金额
foreach (var item in listRentals)
{
totalAmount+= item.GetAmount();//总价计算
}
return totalAmount;
}
/// <summary>
/// 计算积分
/// </summary>
private decimal GetTotalFrequentRenterPoints()
{
int frequentRenterPoints = 0; //用户积分
foreach (var item in listRentals)
{
frequentRenterPoints += item.GetFrequentRenterPoints();//计算积分
}
return frequentRenterPoints;
}
}
}
4. 我们的测试用例依然不变。在每次重构后我们都需要调用上述的测试用例来检查重构是否产生了副作用。现在我们的类间的依赖关系没怎么发生变化,只是相应类中的方法有些变化。在Visual Studio 2019的菜单栏上找到“测试-->运行所有测试”菜单项。或者在“测试资源管理器中”选择 “在视图中运行所有测试”按钮, 运行测试用例。监测重构的结果是否正确。如下图。