ivaneeo's blog

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

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks

#

作法(Mechanics)
  • 在[待剖解]之临时变量的声明式及其第一次被赋值处,修改其名称。
      • ==》如果稍后之赋值语句是[i = i + 某表达式]形式,就意味这是个集用临时变量,那么就不要剖解它。集用临时变量的作用通常是累加、字符串接合、写入stream或者向群集(collection)添加元素。
  • 将新的临时变量声明为final。
  • 以该临时变量之第二次赋值动作为界,修改此前对该临时变量的所有引用点,让它们引用新的临时变量。
  • 在第二次赋值处,重新声明原先那个临时变量。
  • 编译,测试。
  • 逐次重复上述过程。每次都在声明处对临时变量易名,并修改下次赋值之前的引用点。
posted @ 2005-08-29 14:19 ivaneeo 阅读(162) | 评论 (0)编辑 收藏

动机(Motivation)
临时变量有各种不同用途,其中某些用途会很自然地导致临时变量被多次赋值。[循环变量]和[集用临时变量]就是两个典型例子:循环变量(loop variable)会随循环的每次运行而改变(例如for(int i=0; i <10;i++)语句中的i);集用临时变量(collection temporary variable)负责将[通过整个函数的运算]而构成的某个值收集起来。

除了这两种情况,还有很多临时变量用于保存一段冗长代码的运算结果,以便稍后使用。这种临时变量应该只被赋值一次。如果它们被赋值超过一次,就意味它们在 函数中承担了一个以上的责任。如果临时变量承担多个责任,它就应该被替换(剖解)为多个临时变量,每个变量只承担一个责任。同一个临时变量承担两件不同的 事情,会令代码阅读者糊涂。
posted @ 2005-08-29 14:11 ivaneeo 阅读(167) | 评论 (0)编辑 收藏

你的程序有某个临时变量被赋值超过一次,它既不是循环变量,也不是一个集用临时变量(collection temporary variable)。

针对每次赋值,创造一个独立的、对应的临时变量。

    double temp = 2 * (_height + _widgth);
    System.out.println(temp);
    temp = _height * _widgth;
    System.out.println(temp);
                                                 | |
                                \  /
    final double perimeter = 2 * (_height + _widgth);
    System.out.println(perimeter);
    final double area = _height * _widgth;
    System.out.println(area);
posted @ 2005-08-29 13:40 ivaneeo 阅读(185) | 评论 (0)编辑 收藏

google talk使用了Jabber协议,因此我们这些linuxfans可以很happy地使用google的服务:)

登入选项
协议:Jabber
用户名:gmail邮箱前缀
服务器:gmail.com
资源:google talk
密码:gmail邮箱密码

显示主要选项:
Jabber选项
选中“若可用则使用tls和允许在不加密流上的纯文本验证
端口:5222
连接服务器:64.233.167.125

posted @ 2005-08-28 13:45 ivaneeo 阅读(355) | 评论 (0)编辑 收藏

运用Extract Method处理上述范例
面对上代码,我通常不会以临时变量来解释其动作意图,我更喜欢使用Extract Method(110).让我们回到起点:
double price() {
   //price is base price - quantity discount + shipping
   return _quantity * _itemPrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(_quantity * _itemPrice * 0.1, 100.0);
}

这次我把底价计算提炼到一个独立函数中:
double price() {
   //price is base price - quantity discount + shipping
   return basePrice() -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(basePrice() * 0.1, 100.0);
}
private double basePrice() {
   return _quantity * _itemPrice;
}

我继续我的提炼,每次提炼出一个新函数.最后得到下列代码:
double price() {
   //price is base price - quantity discount + shipping
   return basePrice() - quantityDiscount() + shipping();      
}
private double quantityDiscount() {
   Math.max(0, _quantity - 500) * _itemPrice * 0.05;
}
private double shipping() {
   Math.min(basePrice() * 0.1, 100.0);
}
private double basePrice() {
   return _quantity * _itemPrice;
}


我比较喜欢使用Extract Method(110),因为同一对象中的任何部分,都可以根据自己的需要去取用这些提炼出来的函数.一开始我会这些新函数声明为private;如果其他对象也需要它们,我可以轻易释放这些函数的访问限制.我还发现,Extract Method(110)的工作量通常并不必Introduce Explaining Variable(124)来得大.

那么,应该在什么时候使用Introduce Explaining Variable(124)呢?答案是:在Extract Method(110)需要花费更大工作量时.如果我要处理的是一个拥有大量局部变量的算法,那么使用Extract Method(110)绝非易事.这种情况下我会使用Introduce Explaining Variable(124)帮助我清理代码,然后再考虑下一步该怎么办.搞清楚代码逻辑之后,我总是可以运用Replace Temp with Query(120)把被我引入的那些解释性临时变量去掉.况且,如果我最终使用Replace Method with Method Object(135),那么被我引入的那些解释性临时变量也有其价值.
posted @ 2005-08-25 17:07 ivaneeo 阅读(181) | 评论 (0)编辑 收藏

范例(Examples)
我们从一个简单计算开始:
double price() {
   //price is base price - quantity discount + shipping
   return _quantity * _itemPrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(_quantity * _itemPrice * 0.1, 100.0);
}

这段代码还算简单,不过我可以让它变得更容易理解.首先我发现,底价(base price)等于数量(quantity)乘以单价(item price).于是我把这一部分计算的结果放进一个临时变量中:
double price() {
   //price is base price - quantity discount + shipping
   final double basePrice = _quantity * _itemPrice;
   return basePrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(_quantity * _itemPrice * 0.1, 100.0);
}

稍后也用上了[数量乘以单价]运算结果,所以我同样将它替换为basePrice临时变量:
double price() {
   //price is base price - quantity discount + shipping
   final double basePrice = _quantity * _itemPrice;
   return basePrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(basePrice * 0.1, 100.0);
}


然后,我将批发折扣(quantity discount)的计算提炼出来,将结果赋予临时变量quantityDiscount:
double price() {
   //price is base price - quantity discount + shipping
   final double basePrice = _quantity * _itemPrice;
   final double quantityDiscount = Math.max(0, _quantity - 500) * 
                                                      _itemPrice * 0.05;

   return basePrice - quantityDiscount  +
      Math.min(basePrice * 0.1, 100.0);
}

最后,我再把运费(shipping)计算提炼出来,将运算结果赋予临时变量shipping.同时我还可以删掉代码中的注释,因为现在代码已经可以完美表达自己的意义了:
double price() {
   //price is base price - quantity discount + shipping
   final double basePrice = _quantity * _itemPrice;
   final double quantityDiscount = Math.max(0, _quantity - 500) * 
                                                      _itemPrice * 0.05;
   final double shipping = Math.min(basePrice * 0.1, 100.0);
   return basePrice - quantityDiscount  + shipping;
}

posted @ 2005-08-25 16:46 ivaneeo 阅读(140) | 评论 (0)编辑 收藏

作法(Mechanics)

    • 声明一个final 临时变量,将待分解之复杂表达式中的一部分动作的运算结果赋值给它.
    • 将表达式中的[运算结果]这一部分,替换为上述临时变量.
        • ==>如果被替换的这一部分在代码中重复出现,你可以每次一个,逐一替换.
    • 编译,测试.
    • 重复上述过程,处理表达式的其他部分.
posted @ 2005-08-25 16:26 ivaneeo 阅读(173) | 评论 (0)编辑 收藏

动机(Motivation)
表达式有可能非常复杂而难以阅读.这种情况下,临时变量可以帮助你将表达式分解为比较容易管理的形式.

在条件逻辑(conditional logic)中,Introduce Explaining Variable(124)特别有价值:你可以用这项重构将每个条件子句提炼出来,以一个良好命名的临时变量来解释对应条件子句的意义.使用这项重构的另一种情况是,在较长算法中,可以运用临时变量来解释每一步运算的意义.

Introduce Explaining Variable(124)是一个很常见的重构手法,但我得承认,我并不常用它.我几乎总是尽量使用Extract Method(110)来解释一段代码的意义.毕竟临时变量只在它所处的那个函数中才有意义,局限性较大,函数则可以对象的整个生命中都有用,并且可被其他对象使用.但有时候,当局部变量使Extract Method(110)难以进行时,我就使用Introduce Explaining Variable(124).
posted @ 2005-08-25 16:08 ivaneeo 阅读(154) | 评论 (0)编辑 收藏

你有一个复杂的表达式.

将该复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途.

if((platform.toUpperCase().indexOf("MAC") > -1) &&
   (brower.toUpperCase().indexOf("IE") > -1) &&
   wasInitialized() && resize > 0)
{
   //do something
}
                                 |   |
                                 |   |
                                \    /
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;

if(isMacOs && isIEBrowser && wasInitialized() && wasResized) {
   //do something
}

posted @ 2005-08-25 15:46 ivaneeo 阅读(194) | 评论 (0)编辑 收藏

范例(Examples)
首先,我从一个简单函数开始:
double getPrice() {
   int basePrice = _quantity * _itemPrice;
   double discountFactor;
   if(basePrice > 1000) discountFactor = 0.95;
   else   discountFactor = 0.98;
   return basePrice * discountFactor;
}

我希望将两个临时变量都替换掉.当然,每次一个.

尽管这里的代码十分清楚,我还是先把临时变量声明为final,检查它们是否的确只被赋值一次:
double getPrice() {
   final int basePrice = _quantity * _itemPrice;
   final double discountFactor;
   if(basePrice > 1000) discountFactor = 0.95;
   else   discountFactor = 0.98;
   return basePrice * discountFactor;
}

这么一来,如果有任何问题,编译器就会警告我.之所以先做这件事,因为如果临时变量不知被赋值一次,我就不该进行这项重构.接下来我开始替换临时变量,每次一个.首先我把赋值(assignment)动作的右侧表达式提炼出来:
double getPrice() {
   final int basePrice = basePrice();
   final double discountFactor;
   if(basePrice > 1000) discountFactor = 0.95;
   else   discountFactor = 0.98;
   return basePrice * discountFactor;
}
private int basePrice() {
   return _quantity * _itemPrice;
}

编译并测试,然后开始使用Inline Temp(119).首先把临时变量basePrice的第一个引用点替换掉:
double getPrice() {
   final int basePrice = basePrice();
   final double discountFactor;
   if(basePrice() > 1000) discountFactor = 0.95;
   else   discountFactor = 0.98;
   return basePrice * discountFactor;
}


编译,测试,下一个.由于[下一个]已经是basePrice的最后一个引用点,所以我把basePrice临时变量的声明式一并摘除:
double getPrice() {
   final double discountFactor;
   if(basePrice() > 1000) discountFactor = 0.95;
   else   discountFactor = 0.98;
   return basePrice() * discountFactor;
}


搞定basePrice之后,我再以类似办法提炼出一个discountFactor():
double getPrice() {
   final double discountFactor = discountFactor();
      return basePrice() * discountFactor;
}
private double discountFactor() {
   if(basePrice() > 1000) return 0.95;
   else   return 0.98;
}

你看,如果我没有把临时变量basePrice替换为一个查询式,将多么难以提炼discountFactor()!

最终,getPrice()变成了这样:
double getPrice() {
      return basePrice() * discountFactor();
}

posted @ 2005-08-25 15:14 ivaneeo 阅读(251) | 评论 (0)编辑 收藏

仅列出标题
共67页: First 上一页 47 48 49 50 51 52 53 54 55 下一页 Last