日期:2014-05-18 浏览次数:20881 次
上一篇讲了如何使用原始(待重构的)代码构建自动单元测试,以保障后面重构的进行。如果你跟着一步一步地做,会发现,自动测试绝对是重构过程必不可少的工具。那么现在开始真刀真枪地进行重构。
等等,在开始前的最后一刻,还需要提醒的是,也许你带着满腔热情,想把代码重构得优雅极致,但就像平时的工作一样,重构的过程更需要的是理性思考,而不是冲动。每一次重构实践,都应该包含了对设计、实现、可维护、可扩展性,以及成本的估算和权衡。
所以,首先看看对于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"