Split Temporary Variable (分解臨時變量)

Summary:

程序有某個臨時變量被賦值超過一次,它既不是循環變量,也不被用於收集計算結果。針對每次賦值,創造一個獨立、對應的臨時變量。 java

Motivation:

臨時變量有各類不一樣用途,其中某些用途會很天然地致使臨時變量被屢次賦值。「循環變量」和「結果收集變量」就是兩個典型例子:循環變量(loop variable)會歲循環的每次運行而改變(例如for(int i=0; i<10; i++)語句中的i);結果收集變量(collecting temporary variable)負責將「經過整個函數的運算」而構成的某個值收集起來。 函數

除了這兩種狀況,還有不少臨時變量用於保存一段冗長代碼的運算結果,以便稍後使用。這種臨時變量應該只被賦值一次。若是它們被賦值超過一次,就意味着它們在函數中承擔了一個以上責任。若是臨時變量承擔多個責任,它就應該被替換(分解)爲多個臨時變量,每一個變量只承擔一個責任。同一個變量承擔兩件不一樣的事情,會令代碼閱讀者糊塗。 oop

Mechanics:

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;
    }
如今這段代碼確定可讓你想起更多的其餘重構手法。
相關文章
相關標籤/搜索