日期:2014-05-18 浏览次数:21094 次
上一篇讲了如何使用原始(待重构的)代码构建自动单元测试,以保障后面重构的进行。如果你跟着一步一步地做,会发现,自动测试绝对是重构过程必不可少的工具。那么现在开始真刀真枪地进行重构。
等等,在开始前的最后一刻,还需要提醒的是,也许你带着满腔热情,想把代码重构得优雅极致,但就像平时的工作一样,重构的过程更需要的是理性思考,而不是冲动。每一次重构实践,都应该包含了对设计、实现、可维护、可扩展性,以及成本的估算和权衡。
所以,首先看看对于Statement方法来说,从哪里入手比较合适?
public string Statement()
{
double totalAmount = 0;
int frequentRenterPoints = 0;
string result = "Rental Record for " + Name + "\n";
foreach (Rental rental in Rentals)
{
double thisAmount = 0;
// determine amounts for each line
switch (rental.Movie.PriceCode)
{
case Movie.REGULAR:
thisAmount += 2;
if (rental.DaysRented > 2)
thisAmount += (rental.DaysRented - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += rental.DaysRented * 3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if (rental.DaysRented > 3)
thisAmount += (rental.DaysRented - 3) * 1.5;
break;
}
// add frequent renter points
frequentRenterPoints++;
// add bonus for a two day new release rental
if (rental.Movie.PriceCode == Movie.NEW_RELEASE &&
rental.DaysRented > 1) frequentRenterPoints++;
// show figures for this rental
result += "\t" + rental.Movie.Title + "\t" + thisAmount.ToString() + "\n";
totalAmount += thisAmount;
}
// add footer lines
result += "Amount owed is " + totalAmount.ToString() + "\n";
result += "You earned " + frequentRenterPoints.ToString() + " frequent renter points";
return result;
}实际上,应该换一个问题:对现在的程序来说,哪里最容易产生变化?毕竟,如果代码不会变化,重构就是多余的行为。优雅的代码只能满足程序员的审美需求,而不是客户对于功能的需求。public int AmountFor(Rental rental)
{
return 0;
}2.把switch的代码copy(不是剪切)到AmountFor里:public int AmountFor(Rental rental)
{
switch (rental.Movie.PriceCode)
{
case Movie.REGULAR:
thisAmount += 2;
if (rental.DaysRented > 2)
thisAmount += (rental.DaysRented - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += rental.DaysRented * 3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if (rental.DaysRented > 3)
thisAmount += (rental.DaysRented - 3) * 1.5;
break;
}
return 0;
}
3.但此时的代码是编译不了得,因为AmountFor中,thisAmount不存在。所以,在switch前面添加一个thisAmount的声明:
public int AmountFor(Rental rental)
{
int thisAmount = 0;
switch (rental.Movie.PriceCode)
{
case Movie.REGULAR:
thisAmount += 2;
if (rental.DaysRented > 2)
thisAmount += (rental.DaysRented - 2) * 1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += rental.DaysRented * 3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if (rental.DaysRented > 3)
thisAmount += (rental.DaysRented - 3) * 1.5;
break;
}
return thisAmount;
}4.此时,代码还是编译不了,因为花费计算时用到了小数,而thisAmount是整数。加上强制转换后:public int AmountFor(Rental rental)
{
int thisAmount = 0;
switch (rental.Movie.PriceCode)
{
case Movie.REGULAR:
thisAmount += 2;
if (rental.DaysRented > 2)
thisAmount += (int)((rental.DaysRented - 2) * 1.5);
break;
case Movie.NEW_RELEASE:
thisAmount += rental.DaysRented * 3;
break;
case Movie.CHILDRENS:
thisAmount += (int)1.5;
if (rental.DaysRented > 3)
thisAmount += (int)((rental.DaysRented - 3) * 1.5);
break;
}
return thisAmount;
}5.在认为新的方法完成后,去掉Statement中的switch代码块,变成:public string Statement()
{
double totalAmount = 0;
int frequentRenterPoints = 0;
string result = "Rental Record for " + Name + "\n"