<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    ivaneeo's blog

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

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks

    #

    你想要把某個算法替換為另一個更清晰的算法。

    將函數(shù)本體(method body)替換為另一個算法。

    String foundPerson(String[] people) {
        for(int i = 0; i < people.length; i++) {
           if(people[i].equals("Don")) {
              return "Don";
            }
           if(people[i].equals("John")) {
              return "John";
            }
           if(people[i].equals("Kent")) {
              return "Kent";
            }
        }
        return "";
    }

                                 |  |
                                \   /
    String foundPerson(String[] people) {
        List candidates = Arrays.asList(new String[],
                                                           {"Don", "John", "Kent"});
        for(int i = 0; i < people.length; i++)
           if(candidates.contains(people[i]))
              return people[i];
        return "";
    }
    posted @ 2005-08-29 17:03 ivaneeo 閱讀(203) | 評論 (0)編輯 收藏

    范例(Examples)
    class Account...
        int gamma(int inputVal, int quantity, int yearToDate) {
           int importantValue1 = (inputVal * quantity) + delta();
           int importantValue2 = (inputVal * yearToDate) + 100;
           if((yearToDate - importantValue1) > 100)
              importantValue2 -= 20;
           int importantValue3 = importantValue2 * 7;
           //   and so on.
           return importantValue3 -2 * importantValue1;
        }

    為了把這個函數(shù)變成一個函數(shù)對象(method object),我首先需要聲明一個新class。在此新class中我應(yīng)該提供一個final值域用以保存原先對象(源對象):對于函數(shù)的每一個參數(shù)和每一個臨時變量,也以一個個值域逐一保存。
    class Gamma...
        private final Account _account;
        private int inputVal;
        private int quantity;
        private int yearToDate;
        private int importantValue1;
        private int importantValue2;
        private int importantValue3;

    接下來,加入一個構(gòu)造函數(shù):

    Gamma (Account source, int inputValArg, int quantityArg, int yearToDateArg) {
        _account = source;
        inputVal = inputValArg;
        quantity = quantityArg;
        yearToDate = yearToDateArg;
    }

    現(xiàn)在可以把原來的函數(shù)搬到compute()了。函數(shù)中任何調(diào)用Account class的地方,我都必須改而使用_account值域:
    int compute() {
           int importantValue1 = (inputVal * quantity) + _account.delta();
           int importantValue2 = (inputVal * yearToDate) + 100;
           if((yearToDate - importantValue1) > 100)
              importantValue2 -= 20;
           int importantValue3 = importantValue2 * 7;
           //   and so on.
           return importantValue3 -2 * importantValue1;
    }
    然后,我修改舊函數(shù),讓它將它的工作轉(zhuǎn)發(fā)給剛完成的這個函數(shù)對象(method object):
    int gamma(int inputVal, int quantity, int yearToDate) {
        return new Gamma(this, inputVal, quantity, yearToDate).compute();
    }
    這就是本項(xiàng)重構(gòu)的基本原則。它帶來的好處是:現(xiàn)在我可以輕松地對compute()函數(shù)采取Extract Method(110),不必?fù)?dān)心引數(shù)(argument)傳遞。
    int compute() {
        int importantValue1 = (inputVal * quantity) + _account.delta();
           int importantValue2 = (inputVal * yearToDate) + 100;
           importantThing();
           int importantValue3 = importantValue2 * 7;
           //   and so on.
           return importantValue3 -2 * importantValue1;
    }
    void importantThing() {
        if((yearToDate - importantValue1) > 100)
           importantValue2 -= 20;
    }
    posted @ 2005-08-29 16:49 ivaneeo 閱讀(257) | 評論 (0)編輯 收藏

    作法(Mechanics)
      • 建立一個新class,根據(jù)[待被處理之函數(shù)]的用途,為這個class命名。
      • 在新class中建立一個final值域,用以保存原先大型函數(shù)所駐對象。我們將這個值域稱為[源對象]。同時,針對原(舊)函數(shù)的每個臨時變量和每個參數(shù),在新class中建立一個個對應(yīng)的值域保存之。
      • 在新class中建立一個構(gòu)造函數(shù)(constructor),接收源對象及原函數(shù)的所有參數(shù)作為參數(shù)。
      • 在新class中建立一個compute()函數(shù)。
      • 將原(舊)函數(shù)的代碼拷貝到compute()函數(shù)中。如果需要調(diào)用源對象的任何函數(shù),請以[源對象]值域調(diào)用。
      • 編譯。
      • 將舊函數(shù)的函數(shù)本體替換為這樣一條語句:[創(chuàng)建上述新class的一個新對象,而后調(diào)用其中的compute()函數(shù)]。
    現(xiàn)在進(jìn)行到很有趣的部分了。由于所有局部變量現(xiàn)在都成了值域,所以你可以任意分解這個大型函數(shù),不必傳遞任何參數(shù)。
    posted @ 2005-08-29 16:13 ivaneeo 閱讀(146) | 評論 (0)編輯 收藏

    動機(jī)(Motivation)
    我在本書中不斷向讀者強(qiáng)調(diào)小型函數(shù)的優(yōu)美動人。只要將相對獨(dú)立的代碼從大型函數(shù)中提煉出來,就可以大大提高代碼的可讀性。

    但是,局部變量的存在會增加函數(shù)分解難度。如果一個函數(shù)之中局部變量泛濫成災(zāi),那么想分解這個函數(shù)是非常困難的。Replace Temp with Query(120)可以助你減輕這一負(fù)擔(dān),但有時候你會發(fā)現(xiàn)根本無法拆解的函數(shù)。這種情況下,你應(yīng)該把手深深地伸入你的工具箱(好酒沉甕底呢),祭出函數(shù)對象(method object)這件法寶。

    Replace Method with Method Object(135)會將所有局部變量都變成函數(shù)對象(method object)的值域(field)。然后你就可以對這個新對象使用Extract Method(110)創(chuàng)造出新函數(shù),從而將原本的大型函數(shù)拆解變短。
    posted @ 2005-08-29 15:56 ivaneeo 閱讀(177) | 評論 (0)編輯 收藏

    你有一個大型函數(shù),其中對局部變量的使用,使你采用Extract Method(110)。

    將這個函數(shù)放進(jìn)一個單獨(dú)對象中,如此一來局部變量就成了對象內(nèi)的值域(field)。然后你可以在同一個對象中將這個大型函數(shù)分解為數(shù)個小型函數(shù)。

    class Order...
        double price() {
           double primaryBasePrice;
           double secondaryBasePrice;
           double tertiaryBasePrice;
           //   long computation;
          ...
        }
    posted @ 2005-08-29 15:47 ivaneeo 閱讀(145) | 評論 (0)編輯 收藏

    范例(Examples)
    我從下列這段簡單代碼開始:
    int discount(int inputVal, int quantity, int yearToDate) {
        if(inputVal > 50) inputVal -= 2;
        if(quantity > 100) inputVal -= 1;
        if(yearToDate > 1000) inputVal -= 4;
        return inputVal;
    }
    以臨時變量取代對參數(shù)的賦值動作,得到下列代碼:
     int discount(int inputVal, int quantity, int yearToDate) {
        int result = inputVal;
        if(inputVal > 50)
    result -= 2;
        if(quantity > 100) result -= 1;
        if(yearToDate > 1000) result -= 4;
        return result
    }
    還可以為參數(shù)加上關(guān)鍵詞final,從而強(qiáng)制它遵循[不對參數(shù)賦值]這一慣例:
      int discount(final int inputVal, final int quantity, final int yearToDate) {
        int result = inputVal;
        if(inputVal > 50)
    result -= 2;
        if(quantity > 100) result -= 1;
        if(yearToDate > 1000) result -= 4;
        return result
    }

    不過我的承認(rèn),我并不經(jīng)常使用final來修飾參數(shù),因?yàn)槲野l(fā)現(xiàn),對于提高短函數(shù)的清晰度,這個辦法并無太大幫助。我通常會在較長的函數(shù)中使用它,讓它幫助我檢查參數(shù)是否被做了修改。
    posted @ 2005-08-29 15:40 ivaneeo 閱讀(206) | 評論 (0)編輯 收藏

    作法(Mechanics)
      • 建立一個臨時變量,把待處理的參數(shù)值賦予它。
      • 以[對參數(shù)的賦值動作]為界,將其后所有對此參數(shù)的引用點(diǎn),全部替換為[對此臨時變量的引用動作]。
      • 修改賦值語句,使其改為對新建之臨時變量賦值。
      • 編譯,測試。
            • =》如果代碼的語義是pass by reference,請?jiān)谡{(diào)用端檢查調(diào)用后是否還使用了這個參數(shù)。也要檢查有多少個pass by reference參數(shù)[被賦值后又被使用]。請盡量只以return方式返回一個值。如果需要返回的值不只一個,看看可否把需返回的大堆數(shù)據(jù)變成單一對 象,或干脆為每個返回值設(shè)計(jì)對應(yīng)的一個獨(dú)立函數(shù)。
    posted @ 2005-08-29 15:26 ivaneeo 閱讀(185) | 評論 (0)編輯 收藏

    動機(jī)(Motivation)

    我只針對[foo被改而指向(引用)完全不同的另一個對象]這種情況來討論:
        void aMethod(Object foo) {
           foo.modifyInSomeWay();   //that's OK
           foo = anotherObject;   //throuble and despair will follow you
        }
    我之所以不喜歡這樣的作法,因?yàn)樗档土舜a的清晰度,而且混淆了pass by value(傳值)和pass by reference(傳址)這兩種參數(shù)傳遞方式。Java只采用pass by value傳遞方式,我們的討論也正是基于這一點(diǎn)。

    在pass by value情況下,對參數(shù)的任何修改,都不會調(diào)用端造成任何影響。那些用過pass by reference的人可能會在這一點(diǎn)上犯糊涂。
    posted @ 2005-08-29 15:16 ivaneeo 閱讀(178) | 評論 (0)編輯 收藏

    你的代碼對一個參數(shù)進(jìn)行賦值動作。

    以一個臨時變量取代該參數(shù)的位置。

    int discount(int inputVal, int quantity, int yearToDate) {
        if(inputVal > 50) inputVal -= 2;
                                                           |  |
                                        \  /
    int discount(int inputVal, int quantity, int yearToDate) {
        int result = inputVal;
        if(inputVal > 50) result -= 2;
    posted @ 2005-08-29 15:00 ivaneeo 閱讀(238) | 評論 (0)編輯 收藏

    范例(Examples)
    下面范例中我要計(jì)算一個蘇格蘭布丁(haggis)運(yùn)動的距離。在起點(diǎn)處,靜止的蘇格蘭布丁會受到一個初始力的作用而開始運(yùn)動。一段時機(jī)后,第二個力作用于布丁,讓它再次加速。根據(jù)牛頓第二定律,我可以這樣計(jì)算布丁運(yùn)動的距離:

    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變量有兩個責(zé)任:第一是保存第一個力造成的初始加速度;第二是保存兩個力共同造成的加速度。這就是我想要剖解的東西。

    首先,我在函數(shù)開始處修改這個臨時變量的名稱,并將新的臨時變量聲明為final。接下來我把第二次賦值之前對acc變量的所有引用點(diǎn),全部改用新的臨時變量。最后,我在第二次賦值處重新聲明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;
    }

    新的臨時變量的名稱指出,它只承擔(dān)原先acc變量的第一責(zé)任。我將它聲明為final,確保它只被賦值一次。然后,我在原先acc變量第二次被賦值處重新聲明acc。現(xiàn)在,重新編譯并測試,一切都應(yīng)該沒有問題。

    然后,我繼續(xù)處理acc臨時變量的第二次賦值。這次我把原先的臨時變量完全刪掉,代之以一個新的臨時變量。新變量的名稱指出,它只承擔(dān)原先acc變量的第二個責(zé)任:

    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;
    }
    posted @ 2005-08-29 14:56 ivaneeo 閱讀(184) | 評論 (0)編輯 收藏

    僅列出標(biāo)題
    共67頁: First 上一頁 46 47 48 49 50 51 52 53 54 下一頁 Last 
    主站蜘蛛池模板: 香蕉视频在线免费看| 亚洲一区二区三区香蕉| 久久免费区一区二区三波多野| 亚洲精品av无码喷奶水糖心| 亚洲一区二区三区夜色| 亚洲国产综合人成综合网站| 一二三四免费观看在线视频中文版| 拍拍拍无挡免费视频网站| 小说专区亚洲春色校园| 亚洲乱码在线播放| 亚洲AV无码一区二区二三区入口| 午夜亚洲av永久无码精品| 永久免费的网站在线观看| 久久狠狠躁免费观看| 最近免费中文字幕中文高清| 国产亚洲欧美日韩亚洲中文色| 亚洲啪啪免费视频| 精品无码一区二区三区亚洲桃色| 亚洲男人的天堂www| 亚洲第一视频在线观看免费| 四虎影院免费视频| 性生交片免费无码看人| 99久久精品日本一区二区免费| 免费无码中文字幕A级毛片| 国产精品免费AV片在线观看| aa毛片免费全部播放完整| 无遮挡呻吟娇喘视频免费播放| 亚洲AV无码成人精品区日韩 | 久久亚洲精品无码av| 国产成人精品亚洲2020| 亚洲性色成人av天堂| 亚洲视频精品在线观看| 亚洲精品视频在线| 久久亚洲AV无码精品色午夜麻| 亚洲中文字幕无码不卡电影| 久久激情亚洲精品无码?V| 国产精品亚洲产品一区二区三区| 免费成人午夜视频| 亚洲AV无码一区二三区| 国产成人亚洲综合无码| 亚洲自偷自偷在线制服|