22 Apr 2009

重构技巧──inline类成员变量

这是今天在和 李教授 pair的时候学到的:

问题

有一个这样的类定义(简化版):


public class OnCurrentActivityPage {
  private String pipelineName;
  
  public OnCurrentActivityPage(ScenarioState scenarioState) {
    this.pipelineName = scenarioState.pipelineName();
  }

  public void triggerPipeline() {
    selenium.trigger(pipelineName);
  }

  public void rerunStage() {
    selenium.rerun(pipelineName, stageName);
  }

  public void pausePipeline() {
    selenium.pause(pipelineName);
  }

  // 很多其它方法也要用到pipelineName
}

我们发现在OnCurrentActivityPage构造函数里调用scenarioState.pipelineName()有bug,需要把它改成不缓存pipelineName而在每次需要它的时候直接调用scenarioState.pipelineName()。

解决方案一(人工替换)

最直接的办法是删掉pipelineName,把scenarioState保存成类成员变量,然后把所有使用pipelineName的代码替换成使用scenarioState.pipelineName()。由于这个类里面有不少方法(超过10个)需要修改,这个方案颇花时间。

解决方案二(自动重构)

Intellij支持对类成员变量做inline重构。但是前提是:

  • 成员变量必须在声明的同时做初始化
  • 成员变量必须被标记为final

这两点要求都很容易满足。为了满足第一点,我们可以把pipelineName的初始化移到声明处:


private String pipelineName = scenarioState.pipelineName();

这时候IDE会报错说scenarioState没有定义,不要理它,因为inline的时候Intellij会把该代码原样移走。

为了满足第二点,我们只需要把pipelineName标记为final:


private final String pipelineName = scenarioState.pipelineName();

然后,再在任何一个使用pipelineName的地方用Ctrl + N执行inline重构,并且指定重构范围为所有的pipelineName调用。转瞬之间,费时费力的重构被工具自动化完成了!

blog comments powered by Disqus