ivaneeo's blog

自由的力量,自由的生活。

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks
范例(Examples):局部变量再赋值(Reassigning)
如果被提炼码对局部变量赋值,问题就变得复杂了.这里我们只讨论临时变量的问题.如果你发现源函数的参数被赋值,应该马上使用Remove Assignments to Parameters(131).

被赋值的临时变量也分两种情况.较简单的情况是:这个变量只在被提炼码区段中使用.果真如此,你可以将这个临时变量的声明式移到被提炼码中,然后一起提炼出去.另一种情况是:被提炼码之外的代码也使用了这个变量.这又分为两种情况:如果这个变量在被提炼码之后未再被使用,你只需直接在目标函数中修改它就可以了;如果被提炼码之后的代码还使用了这个变量,你就需要让目标函数返回该变量改变后的指.我以下列代码说明这几种不同情况:
void printOwing() {
    Enumeration e = _orders.elements();
    double outstanding = 0.0;

   printBanner();

    // calculate outstanding
    while(e.hasMoreElements()) {
       Order each = (Order) e.nextElement();
       outstanding += each.getAmount();
    }

   printDetails(outstanding);
}

现在我把[计算]代码提炼出来:

void printOwing() {
   printBanner();
   double outstanding = getOutstanding();
   printDetails(outstanding);
}

double getOutstanding() {
       Enumeration e = _orders.elements();
       double outstanding = 0.0;

       while(e.hasMoreElements()) {
          Order each = (Order) e.nextElement();
          outstanding += each.getAmount();
       }
      return outstanding;
}

Enumeration变量e只在被提炼码中用到,所以我可以将它整个搬到新函数中.double变量outstanding在被提炼码内外都被用到,所以我必须让提炼出来的新函数返回它.编译测试完成后,我就把传值改名,遵循我的一贯命名原则:

double getOutstanding() {
       Enumeration e = _orders.elements();
       double result = 0.0;

       while(e.hasMoreElements()) {
          Order each = (Order) e.nextElement();
          result += each.getAmount();
       }
      return result;
}

本例中的outstanding变量只是很单纯地被初始化为一个明确初值,所以我可以只在新函数中对它初始化.如果代码还对这个变量做了其他处理,我就必须将它的值作为参数传给目标函数.对于这种变化,最初代码可能是这样:

void printOwing(double previousAmount) {
    Enumeration e = _orders.elements();
    double outstanding = previousAmount * 1.2;

   printBanner();

    // calculate outstanding
    while(e.hasMoreElements()) {
       Order each = (Order) e.nextElement();
       outstanding += each.getAmount();
    }

   printDetails(outstanding);
}

提炼后的代码可能是这样:

void printOwing(double previousAmount) {
   double outstanding = previousAmount * 1.2;

   printBanner();
   double outstanding = getOutstanding(outstanding);
   printDetails(outstanding);
}
double getOutstanding(double initialValue) {
       double result = initialValue;
       Enumeration e = _orders.elements();
       

       while(e.hasMoreElements()) {
          Order each = (Order) e.nextElement();
          result += each.getAmount();
       }
      return result;
}
编译并测试后,我再将变量outstanding的初始化过程整理一下:
void printOwing(double previousAmount) {
   printBanner();
   double outstanding = getOutstanding(previousAmount * 1.2);
   printDetails(outstanding);
}

这时候,你可能会问:[如果需要返回的变量不止一个,又该怎么办?]

你有数种选择.最好的选择通常是:挑选另一块代码来提炼.我比较喜欢让每个函数都只返回一个值,所以我会安排多个函数,用以返回多个值.如果你使用的语言支持[输出式参数](output parameters),你可以使用它们带回多个回传值.但我还是尽可能选择单一返回值.

临时变量往往为数众多,甚至会使提炼工作举步维艰.这种情况下,我会尝试先运用Replace Temp with Query(120)减少临时变量.如果即使这么做了提炼依旧困难重重,我就会动用Replace Method with Method Object(135),这个重构手法不在乎代码中有多少临时变量,也不在乎你如何使用它们.

posted on 2005-08-24 16:14 ivaneeo 阅读(204) 评论(0)  编辑  收藏 所属分类: refactoring-从地狱中重生

只有注册用户登录后才能发表评论。


网站导航: