0
0
0
1. 云栖社区>
2. 博客>
3. 正文

## 最常用的重构指导

luminji 2013-10-06 19:51:00 浏览292

1：避免重复代码

2：提取方法原则，超过30行？

namespace LosTechies.DaysOfRefactoring.ExtractMethod.Before
{
public class Receipt
{
private IList<decimal> Discounts { get; set; }
private IList<decimal> ItemTotals { get; set; }

public decimal CalculateGrandTotal()
{
decimal subTotal = 0m;
foreach (decimal itemTotal in ItemTotals)
subTotal += itemTotal;

if (Discounts.Count > 0)
{
foreach (decimal discount in Discounts)
subTotal -= discount;
}

decimal tax = subTotal * 0.065m;

subTotal += tax;

return subTotal;
}
}
}

namespace LosTechies.DaysOfRefactoring.ExtractMethod.After
{
public class Receipt
{
private IList<decimal> Discounts { get; set; }
private IList<decimal> ItemTotals { get; set; }

public decimal CalculateGrandTotal()
{
decimal subTotal = CalculateSubTotal();

subTotal = CalculateDiscounts(subTotal);

subTotal = CalculateTax(subTotal);

return subTotal;
}

private decimal CalculateTax(decimal subTotal)
{
decimal tax = subTotal * 0.065m;

subTotal += tax;
return subTotal;
}

private decimal CalculateDiscounts(decimal subTotal)
{
if (Discounts.Count > 0)
{
foreach (decimal discount in Discounts)
subTotal -= discount;
}
return subTotal;
}

private decimal CalculateSubTotal()
{
decimal subTotal = 0m;
foreach (decimal itemTotal in ItemTotals)
subTotal += itemTotal;
return subTotal;
}
}
}

3：警惕超过300行的类

4：过多的方法参数

5：没有必要的注释

6：不要用异常

7：要用异常

public bool Insert(Model model)
{
//some other code
Dal dal = new Dal();
if (dal.Insert(model))
{
return true;
}
else
{
return false;
}
}

public bool Insert(Model model)
{
//some other code
new Dal(.Insert(model));
}

8：方法内的代码属于一个层级

9：Dispose

10：Static Or Not

11：Shotgun Surgery（霰弹式修改）

12：Feature Envy（依恋情结）

13：组合与继承，你有两种选择

namespace LosTechies.DaysOfRefactoring.ReplaceInheritance.Before
{
public class Sanitation
{
public string WashHands()
{
return "Cleaned!";
}
}

public class Child : Sanitation
{
}
}

namespace LosTechies.DaysOfRefactoring.ReplaceInheritance.After
{
public class Sanitation
{
public string WashHands()
{
return "Cleaned!";
}
}

public class Child
{
private Sanitation Sanitation { get; set; }

public Child()
{
Sanitation = new Sanitation();
}

public string WashHands()
{
return Sanitation.WashHands();
}
}
}

14：分解复杂判断

{
public class Security
{
public ISecurityChecker SecurityChecker { get; set; }

public Security(ISecurityChecker securityChecker)
{
SecurityChecker = securityChecker;
}

public bool HasAccess(User user, Permission permission, IEnumerable<Permission> 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(User user, Permission permission, IEnumerable<Permission> exemptions)
{
if (user == null || permission == null)
return false;

if (exemptions.Contains(permission))
return true;

return SecurityChecker.CheckPermission(user, permission);
}
}
}

15：尽快返回

1：寻找边界

2：建立公共库

3：资源可以作为一个单独的项目

4：客户端逻辑最小化

.NET 程序最让人诟病的是：混淆了也可窥测你的源码。除了这个原因，从解耦的角度看，UI 或者其它客户端项目，都应该知道更少的逻辑才好。

5：基于测试的与MVC、MVVM、MVP

6：AOP

7：模版模式、继承与多态

8：工厂模式与工厂

9：观察者模式、事件通知

10：接口的存在都是有目的的

11：避免二转手的代码

12：见到条件，就考虑是否使用策略模式

“使用策略类” 是指用设计模式中的策略模式来替换原来的switch case和if else语句，这样可以解开耦合，同时也使维护性和系统的可扩展性大大增强。

```namespace LosTechies.DaysOfRefactoring.SwitchToStrategy.Before
{
public class ClientCode
{
public decimal CalculateShipping()
{
ShippingInfo shippingInfo = new ShippingInfo();
}
}

public enum State
{
NewYork,
Florida
}

public class ShippingInfo
{
public decimal CalculateShippingAmount(State shipToState)
{
switch (shipToState)
{
case State.NewYork:
return GetNewYorkShippingAmount();
case State.Florida:
return GetFloridaShippingAmount();
default:
return 0m;
}
}

{
return 15m;
}

private decimal GetNewYorkShippingAmount()
{
return 10m;
}

private decimal GetFloridaShippingAmount()
{
return 3m;
}
}
}```

```using System;
using System.Collections.Generic;
using System.Linq;

namespace LosTechies.DaysOfRefactoring.SwitchToStrategy.After_WithIoC
{
public interface IShippingInfo
{
decimal CalculateShippingAmount(State state);
}

public class ClientCode
{
[Inject]
public IShippingInfo ShippingInfo { get; set; }

public decimal CalculateShipping()
{
}
}

public enum State
{
NewYork,
Florida
}

public class ShippingInfo : IShippingInfo
{
private IDictionary<State, IShippingCalculation> ShippingCalculations { get; set; }

public ShippingInfo(IEnumerable<IShippingCalculation> shippingCalculations)
{
ShippingCalculations = shippingCalculations.ToDictionary(calc => calc.State);
}

public decimal CalculateShippingAmount(State shipToState)
{
return ShippingCalculations[shipToState].Calculate();
}
}

public interface IShippingCalculation
{
State State { get; }
decimal Calculate();
}

{
public State State { get { return State.Alaska; } }

public decimal Calculate()
{
return 15m;
}
}

public class NewYorkShippingCalculation : IShippingCalculation
{
public State State { get { return State.NewYork; } }

public decimal Calculate()
{
return 10m;
}
}

public class FloridaShippingCalculation : IShippingCalculation
{
public State State { get { return State.Florida; } }

public decimal Calculate()
{
return 3m;
}
}
} ```

13：分解依赖

1：为它们写一个包装类，让这个包装类是抽象的（继承自接口，或者抽象类，或者方法本身是Virtual的）；

2：通知客户端程序员，使用包装类来代替原先的静态类来写业务逻辑；

FCL 中的典型例子是：HttpResponseWrapper。

luminji
+ 关注

corcosa 12305人浏览