程序有某個臨時變量被賦值超過一次,它既不是循環變量,也不被用於收集計算結果。針對每次賦值,創造一個獨立、對應的臨時變量。 java
臨時變量有各類不一樣用途,其中某些用途會很天然地致使臨時變量被屢次賦值。「循環變量」和「結果收集變量」就是兩個典型例子:循環變量(loop variable)會歲循環的每次運行而改變(例如for(int i=0; i<10; i++)語句中的i);結果收集變量(collecting temporary variable)負責將「經過整個函數的運算」而構成的某個值收集起來。 函數
除了這兩種狀況,還有不少臨時變量用於保存一段冗長代碼的運算結果,以便稍後使用。這種臨時變量應該只被賦值一次。若是它們被賦值超過一次,就意味着它們在函數中承擔了一個以上責任。若是臨時變量承擔多個責任,它就應該被替換(分解)爲多個臨時變量,每一個變量只承擔一個責任。同一個變量承擔兩件不一樣的事情,會令代碼閱讀者糊塗。 oop
1. 在待分解臨時變量的聲明及其第一次被賦值處,修改其名稱。 測試
若是稍後之賦值語句是[i=i+某表達式],就意味着這是個結果收集變量,那麼就不要分解它。結果收集變量的做用一般是累加、字符串接合、寫入流或者向集合添加元素 spa
2. 將新的臨時變量聲明爲final code
3.以該臨時變量的第二次賦值動做爲界,修改此前對該臨時變量的全部引用點,讓它們引用新的臨時變量。 字符串
4.在第二次賦值處,從新聲明原先那個臨時變量。 get
5.編譯,測試。 io
6. 逐次重複上述過程。每次都在聲明處對臨時變量更名,並修改下次賦值以前的引用點。 編譯
下面的範例中,咱們計算一個蘇格蘭布丁運動的距離。在起點處,靜止的蘇格蘭布丁會受到一個初始力的做用而開始運動。一段時間後,第二個力做用於布丁,讓它再次加速。根據牛頓第二定律,咱們能夠這樣計算布丁運動的距離
double getDistanceTravelled( int time ) { double result; double acc = primaryForce / mass; int primaryTime = Math.min( time, delay ); result = 0.5 * acc * primaryTime * primaryTime; int secondaryTime = time - delay; if( secondaryTime > 0 ) { double primaryVel = acc * delay; acc = ( primaryForce + secondaryForce ) / mass; result += primaryVel * secondaryTime + 0.5 * acc * secondaryTime * secondaryTime; } return result; }
注意觀察此例中的acc變量如何被賦值兩次。acc變量有兩個責任:第一是保存第一個力形成的初始加速度;第二是保存兩個力共同形成的加速度。這就是咱們想要分解的東西。
首先,咱們在函數開始處修改這個臨時變量的名稱,並將新的臨時變量聲明爲final。接着,我把第二次賦值以前對acc變量的全部引用點,所有改用新的臨時變量。最後,咱們在第二次賦值處從新聲明acc變量:
double getDistanceTravelled( int time ) { double result; final double primaryAcc = primaryForce / mass; int primaryTime = Math.min( time, delay ); result = 0.5 * primaryAcc * primaryTime * primaryTime; int secondaryTime = time - delay; if( secondaryTime > 0 ) { double primaryVel = primaryAcc * delay; double acc = ( primaryForce + secondaryForce ) / mass; result += primaryVel * secondaryTime + 0.5 * acc * secondaryTime * secondaryTime; } return result; }新的臨時變量的名稱指出,它只承擔原先acc變量的第一個責任。咱們將它聲明爲final,確保它只被賦值一次。而後,咱們在原先acc變量第二次被賦值處從新聲明acc。如今,從新編譯並測試,一切應該都沒有問題。
而後,咱們繼續處理acc臨時變量的第二次賦值。此次咱們把原先的臨時變量徹底刪掉,代之以一個新的變量。新變量的名稱指出,它只承擔原先acc變量的第二個責任:
double getDistanceTravelled( int time ) { double result; final double primaryAcc = primaryForce / mass; int primaryTime = Math.min( time, delay ); result = 0.5 * primaryAcc * primaryTime * primaryTime; int secondaryTime = time - delay; if( secondaryTime > 0 ) { double primaryVel = primaryAcc * delay; final double secondaryAcc = ( primaryForce + secondaryForce ) / mass; result += primaryVel * secondaryTime + 0.5 * secondaryAcc * secondaryTime * secondaryTime; } return result; }如今這段代碼確定可讓你想起更多的其餘重構手法。