重构 - 9. 重新组织数据
🏷️ 《重构》
9.1 拆分变量(Split Variable)
曾用名:移除对参数的赋值(Remove Assignments to Parameters)
曾用名:分解临时变量(Split Temp)
如果变量承担多个职责,它就应该被替换(分解)为多个变量,每个变量只承担一个责任。
重构前:
csharp
var temp = 2 * (height + width);
Console.WriteLine(temp);
temp = height * width;
Console.WriteLine(temp);
重构后:
csharp
var perimeter = 2 * (height + width);
Console.WriteLine(perimeter);
var area = height * width;
Console.WriteLine(area);
9.2 字段改名(Rename Field)
命名很重要,对于程序中广泛使用的记录结构,其中字段的命名格外重要。
重构前:
csharp
public class Organization
{
public string Name { get; set; }
}
重构后:
csharp
public class Organization
{
public string Title { get; set; }
}
9.3 以查询取代派生变量(Replace Derived Variable with Query)
可变数据是软件中最大的错误源头之一。
很多时候,完全去掉可变数据并不现实,但还是强烈建议:尽量把可变数据的作用域限制在最小范围。
重构前:
csharp
public double DiscountTotal { get; private set; }
private double _discount;
public double Discount
{
get
{
return _discount;
}
set
{
var old = _discount;
_discount = value;
DiscountTotal += old - value;
}
}
重构后:
csharp
public double DiscountTotal
{
get
{
return _baseTotal - Discount;
}
}
public double Discount { get; set; }
9.4 将引用对象改为值对象(Change Reference to Value)
反向重构:将值对象改为引用对象(Change Value to Reference)
在把一个对象(或数据结构)嵌入一个对象时,位于内部的这个对象可以被视为引用对象,也可以被视为值对象。两者的差异在于如何更新内部对象的属性。
若视为引用对象,更新时保留原对象不动,更新内部对象的属性;
若视为值对象,替换整个内部对象。
值对象在分布式系统和并发系统中尤为有用。
重构前:
csharp
class Product
{
public Money Price { get; set; }
public void ApplyDiscount(double arg)
{
Price.Amount -= arg;
}
}
class Money
{
public double Amount { get; set; }
public string Currency { get; set; }
}
重构后:
csharp
class Product
{
public Money Price { get; set; }
public void ApplyDiscount(double arg)
{
Price = new Money(Price.Amount - arg, Price.Currency);
}
}
struct Money
{
public Money(double amount, string currency) : this()
{
Amount = amount;
Currency = currency;
}
public double Amount { get; set; }
public string Currency { get; set; }
}
9.5 将值对象改为引用对象(Change Value to Reference)
反向重构:将引用对象改为值对象(Change Reference to Value)
把值对象改为引用对象会带来一个结果:对于一个客观实体,只有一个代表它的对象。
这通常意味着需要某种形式的仓库,在仓库中可以找到所有这些实体对象。只为每个实体创建一次对象,以后始终从仓库获取该对象。
重构前:
csharp
var customer = new Customer(customerData);
重构后:
csharp
var customer = customerRepository.Find(customerData.Id);
附 1. 引用
- 《重构:改善既有代码的设计》 -- 马丁·福勒(Martin Fowler)