代码的坏味道(7)——临时字段(Temporary Field)

坏味道——临时字段(Temporary Field)

特征

临时字段的值只在特定环境下有意义,离开这个环境,它们就什么也不是了。

代码的坏味道(7)——临时字段(Temporary Field)

问题原因

有时你会看到这样的对象:其内某个实例变量仅为某种特定情况而设。这样的代码让人不易理解,因为你通常认为对象在所有时候都需要它的所有变量。在变量未被使用的情况下猜测当初设置目的,会让你发疯。
通常,临时字段是在某一算法需要大量输入时而创建。因此,为了避免函数有过多参数,程序员决定在类中创建这些数据的临时字段。这些临时字段仅仅在算法中使用,其他时候却毫无用处。
这种代码不好理解。你期望查看对象字段的数据,但是出于某种原因,它们总是为空。

解决方法

  • 可以通过 提炼类(Extract Class) 将临时字段和操作它们的所有代码提炼到一个单独的类中。此外,你可以运用 以函数对象取代函数(Replace Method with Method Object) 来实现同样的目的。
  • 引入 Null 对象(Introduce Null Object) 在“变量不合法”的情况下创建一个null对象,从而避免写出条件表达式。

代码的坏味道(7)——临时字段(Temporary Field)

收益

  • 更好的代码清晰度和组织性。

代码的坏味道(7)——临时字段(Temporary Field)

重构方法说明

提炼类(Extract Class)

问题

某个类做了不止一件事。

代码的坏味道(7)——临时字段(Temporary Field)

解决

建立一个新类,将相关的字段和函数从旧类搬移到新类。

代码的坏味道(7)——临时字段(Temporary Field)

以函数对象取代函数(Replace Method with Method Object)

问题

你有一个过长函数,它的局部变量交织在一起,以致于你无法应用提炼函数(Extract Method) 。

class Order {
  //...
  public double price() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;
    // long computation.
    //...
  }
}

解决

将函数移到一个独立的类中,使得局部变量成了这个类的字段。然后,你可以将函数分割成这个类中的多个函数。

class Order {
  //...
  public double price() {
    return new PriceCalculator(this).compute();
  }
}

class PriceCalculator {
  private double primaryBasePrice;
  private double secondaryBasePrice;
  private double tertiaryBasePrice;

  public PriceCalculator(Order order) {
    // copy relevant information from order object.
    //...
  }

  public double compute() {
    // long computation.
    //...
  }
}

引入 Null 对象(Introduce Null Object)

问题

你需要再三检查某对象是否为null。

if (customer == null) {
  plan = BillingPlan.basic();
}
else {
  plan = customer.getPlan();
}

解决

将null值替换为null对象。

class NullCustomer extends Customer {
  Plan getPlan() {
    return new NullPlan();
  }
  // Some other NULL functionality.
}

// Replace null values with Null-object.
customer = (order.customer != null) ? order.customer : new NullCustomer();

// Use Null-object as if it's normal subclass.
plan = customer.getPlan();

引申阅读

欢迎继续阅读 代码的症与药 系列文章。

上一篇:Shell 读取用户输入


下一篇:Python核心编程——正则表达式