2009-06-07 03:23:21
摘要:Parameterize Method:另方法携带参数
若干方法做了类似的工作,但在方法本体中却包括了不同的值,可以建立单一方法,以参数表达那些不同的值。
先看一个简单的例子:
public void TenPercentRaise()
{
salary *= 1.1;
}
public void FivePercentRaise()
{
salary *= 1.05;
}
这段代码可以替换如下:
public void Raise(double factor)
{
salary *= (1 + factor);
}
上面的那个例子太简单,所有人都能做到。下面是一个稍微复杂一点的例子:
public double BaseCharge()
{
double result = Math.Min(LastUsage(), 100) * 0.03;
if (LastUsage() 100)
{
result += (Math.Min(LastUsage(), 200) - 100) * 0.05;
}
if (LastUsage() 200)
{
result += (LastUsage() - 200) * 0.07;
}
return result;
}
上述代码可以替换如下:
public double BaseCharge()
{
double result = UsageInRange(0, 100) * 0.03;
result += UsageInRange(100,200) * 0.05;
result += UsageInRange(200, int.MaxValue) * 0.07;
return result;
}
private int UsageInRange(int start, int end)
{
if (LastUsage() start)
return Math.Min(LastUsage(), end) - start;
return 0;
}
本项重构的技巧在于:以可将少量数值视为参数为依据,找出带有重复性的代码。
阅读全文
2009-06-04 06:01:51
摘要:Remove Arrowhead Antipattern:删除箭头反模式
简单地说,当你使用大量的嵌套条件判断时,形成了箭头型的代码,这就是箭头反模式(arrowheadantipattern)。我经常在不同的代码库中看到这种现象,这提高了代码的圈复杂度(cyclomatic complexity)。下面的例子演示了箭头反模式:
public class Security
{
public ISecurityChecker SecurityChecker { get; set; }
public Security(ISecurityChecker securityChecker)
{
SecurityChecker = securityChecker;
}
public bool HasAccess(User user, Permission permission, IEnumerablePermission exemptions)
{
bool hasPermission = false;
if (user != null)
{
if (permission != null)
{
if (exemptions.Count() == 0)
{
if (SecurityChecker.CheckPermission(user, permission) ||
exemptions.Contains(permission))
{
hasPermission = true;
}
}
}
}
return hasPermission;
}
}
移除箭头反模式的重构和封装条件判断一样简单。这种方式的重构在方法执行之前往往会评估各个条件,下面是重构之后的代码:
public class Security
{
public ISecurityChecker SecurityChecker { get; set; }
public Security(ISecurityChecker securityChecker)
{
SecurityChecker = securityChecker;
}
public bool HasAccess……
阅读全文
2009-06-01 13:06:57
摘要:Remove Parameter:删除参数
本体方法不再需要某个参数,将该参数去除。 参数指出函数所需信息,不同的参数值代表不同的意义。函数调用者必须为每个参数操心该传什么东西进去。如果你不去掉多余参数,你就是让你的每一位用户多费一份心。
应用这个重构你只需删除不在需要的参数即可。简单吧。我就不举例了。
阅读全文
2009-05-31 20:25:47
摘要:Add Parameter:添加参数
某个方法需要从调用端得到更多信息,为此方法添加一个对象参数,让该对象带进方法所需信息。
应用这个重构你只需多加入一些参数即可。简单吧。我就不举例了。
阅读全文
2009-05-30 05:28:35
摘要:Rename Method:重命名方法
我们对方法/类/参数的命名往往不那么合适,以至于误导阅读者对于方法/类/参数功能的理解,我们应该**修改成合适的名称。这个重构看起来简单,但却十分重要。
应用这个重构你只需随手将名称修改得更具描述性、更容易传达其含义即可。简单吧。我就不举例了。
阅读全文
2009-05-23 07:06:08
摘要:Substitute Algorithm:替换你的算法
如果你发现做一件事可以有更清晰的方式,就应该以较清晰的方式取代复杂方式。随着对问题有了更多理解,你往往会发现,在你的原先作法之外,有更简单的解决方案,此时你就需要将方法本体替换为另一个算法。
public string FoundPerson(string[] people)
{
for (int i = 0; i people.Length; i++)
{
if (people[i].Equals(Don))
return Don;
if (people[i].Equals(John))
return John;
if (people[i].Equals(Kent))
return Kent;
}
return ;
}
如果将上面代码换一个算法代码会更清晰。
public string FoundPerson(string[] people)
{
Liststring candidates = new Liststring(people);
for (int i = 0; i people.Length; i++)
{
if (candidates.Contains(people[i]))
return people[i];
}
return ;
}
阅读全文
2009-05-21 10:03:42
摘要:Encapsulate Conditional:封装条件
当代码中充斥着若干条件判断时,代码的真正意图会迷失于这些条件判断之中。这时我喜欢将条件判断提取到一个易于读取的属性或方法中。
public class RemoteControl
{
private string[] Functions { get; set; }
private string Name { get; set; }
private int CreatedYear { get; set; }
public string PerformCoolFunction(string buttonPressed)
{
// Determine if we are controlling some extra function
// that requires special conditions
if (Functions.Length 1 Name == RCA
CreatedYear DateTime.Now.Year - 2)
return doSomething;
}
}
重构之后,代码的可读性更强,意图更明显:
public class RemoteControl
{
private string[] Functions { get; set; }
private string Name { get; set; }
private int CreatedYear { get; set; }
private bool HasExtraFunctions
{
get
{
return Functions.Length 1 Name == RCA
CreatedYear DateTime.Now.Year - 2;
}
}
public string PerformCoolFunction(string buttonPressed)
{
// Determine if we are controlling some extra function
// that requires special conditions
if (HasExtraFunctions)
return doSometh……
阅读全文
2009-05-17 21:02:00
摘要:Break Responsibilities:责任拆分
把一个类的多个职责进行拆分,这贯彻了单一职责原则(SRP)。尽管对于如何划分“职责”经常存在争论,但应用这项重构还是十分简单的。我这里并不会回答划分职责的问题,只是演示一个结构清晰的示例,将类划分为多个负责具体职责的类。
public class Video
{
public void PayFee(decimal fee)
{
}
public void RentVideo(Video video, Customer customer)
{
customer.Videos.Add(video);
}
public decimal CalculateBalance(Customer customer)
{
return customer.LateFees.Sum();
}
}
public class Customer
{
public IListdecimal LateFees { get; set; }
public IListVideo Videos { get; set; }
}
如你所见,Video类包含两个职责,一个负责处理录像租赁,另一个负责管理管理用户的租赁总数。要分离职责,我们可以将用户的逻辑转移到用户类中。
public class Video
{
public void RentVideo(Video video, Customer customer)
{
customer.Videos.Add(video);
}
}
public class Customer
{
public IListdecimal LateFees { get; set; }
public IListVideo Videos { get; set; }
public void PayFee(decimal fee)
{
}
public decimal CalculateBalance(Customer customer)
{
return customer.LateFees.Sum();
}
}
阅读全文
2009-05-14 23:03:01
摘要:Extract Method Object:提炼方法对象
当你尝试进行提炼方法的重构时,需要引入大量的方法。在一个方法中使用众多的本地变量有时会使代码变得丑陋。因此最好使用提炼方法对象这个重构,将执行任务的逻辑分开。
public class OrderLineItem
{
public decimal Price { get; private set; }
}
public class Order
{
private IListOrderLineItem OrderLineItems { get; set; }
private IListdecimal Discounts { get; set; }
private decimal Tax { get; set; }
public decimal Calculate()
{
decimal subTotal = 0m;
// Total up line items
foreach (OrderLineItem lineItem in OrderLineItems)
{
subTotal += lineItem.Price;
}
// Subtract Discounts
foreach (decimal discount in Discounts)
subTotal -= discount;
// Calculate Tax
decimal tax = subTotal * Tax;
// Calculate GrandTotal
decimal grandTotal = subTotal + tax;
return grandTotal;
}
}
我们通过构造函数,将返回计算结果的类的引用传递给包含多个计算方法的……
阅读全文
2009-05-11 16:34:10
摘要:Introduce Explaining Variable:引入解释性变量
你有一个表达式,有可能非常复杂而难以阅读。这种情况下,临时变量可以帮助你将表达式分解为比较容易管理的形式。将赋值表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式的用途。
if ((platform.ToUpper().IndexOf(MAC) -1)
(browser.ToUpper().IndexOf(IE)) -1
WasInitialized() resize 0)
{
//do something
}
在上面的代码中 if 语句内的条件判断你必须完全读完,也不一定很快就能知道它们的用意,但是按下面方式重构后,你可能很快就能读懂代码:
bool isMacOs = platform.ToUpper().IndexOf(MAC) -1;
bool isIEBrowser = browser.ToUpper().IndexOf(IE) -1;
bool wasResized = resize 0;
if (isMacOs isIEBrowser WasInitialized() wasResized)
{
//do something
}
阅读全文