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 閱讀(169) | 評論 (0)編輯 收藏

          動機(Motivation)
          臨時變量有各種不同用途,其中某些用途會很自然地導致臨時變量被多次賦值。[循環變量]和[集用臨時變量]就是兩個典型例子:循環變量(loop variable)會隨循環的每次運行而改變(例如for(int i=0; i <10;i++)語句中的i);集用臨時變量(collection temporary variable)負責將[通過整個函數的運算]而構成的某個值收集起來。

          除了這兩種情況,還有很多臨時變量用于保存一段冗長代碼的運算結果,以便稍后使用。這種臨時變量應該只被賦值一次。如果它們被賦值超過一次,就意味它們在 函數中承擔了一個以上的責任。如果臨時變量承擔多個責任,它就應該被替換(剖解)為多個臨時變量,每個變量只承擔一個責任。同一個臨時變量承擔兩件不同的 事情,會令代碼閱讀者糊涂。
          posted @ 2005-08-29 14:11 ivaneeo 閱讀(173) | 評論 (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 閱讀(193) | 評論 (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 閱讀(369) | 評論 (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 閱讀(187) | 評論 (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 閱讀(146) | 評論 (0)編輯 收藏

          作法(Mechanics)

            • 聲明一個final 臨時變量,將待分解之復雜表達式中的一部分動作的運算結果賦值給它.
            • 將表達式中的[運算結果]這一部分,替換為上述臨時變量.
                • ==>如果被替換的這一部分在代碼中重復出現,你可以每次一個,逐一替換.
            • 編譯,測試.
            • 重復上述過程,處理表達式的其他部分.
          posted @ 2005-08-25 16:26 ivaneeo 閱讀(180) | 評論 (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 閱讀(161) | 評論 (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 閱讀(199) | 評論 (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 閱讀(258) | 評論 (0)編輯 收藏

          僅列出標題
          共67頁: First 上一頁 47 48 49 50 51 52 53 54 55 下一頁 Last 
          主站蜘蛛池模板: 乌拉特前旗| 东山县| 隆林| 女性| 文登市| 溆浦县| 噶尔县| 武强县| 莱芜市| 乐亭县| 乌拉特后旗| 星座| 东港市| 龙州县| 东莞市| 潼南县| 柘城县| 平度市| 嵊泗县| 宣化县| 镇安县| 云阳县| 偃师市| 扬中市| 玉门市| 定安县| 金湖县| 鸡泽县| 大冶市| 南开区| 孝感市| 阿图什市| 湘阴县| 城市| 吴江市| 嘉祥县| 平乐县| 荥经县| 紫阳县| 雷山县| 冕宁县|