日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

重构——解决过长参数列表(long parameter list)

發(fā)布時間:2023/12/1 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 重构——解决过长参数列表(long parameter list) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

    • 1、Replace Param with Query
    • 2、Preserve Whole Object
    • 3、Introduce Param Object
    • 4、Remove Flag Argument
    • 5、Combine Functions into Class
    • Reference

當我們需要在超長函數(shù)中提煉子函數(shù)時,如果函數(shù)內(nèi)有大量的參數(shù)和臨時變量,這將會對函數(shù)的提煉形成很大阻礙,你可能會形成過長參數(shù)列表,當然你也可以使用全局變量,顯然上面兩種都不是很好的辦法。
函數(shù)參數(shù)列表應該總結出函數(shù)的可變性,標志出函數(shù)可能體現(xiàn)出行為差異的主要方式。參數(shù)列表應當避免重復以及過長。
《重構》給我們提供了幾個好點子:(WHAT)
1、以查詢?nèi)〈鷧?shù)
2、保持對象完整
3、引入?yún)?shù)對象
4、移除標記參數(shù)
5、函數(shù)組合成類
接下來講解它們具體怎么做(HOW)

1、Replace Param with Query

注意點:若移除參數(shù)可能會給函數(shù)體增加不必要的依賴關系,不要使用。
具體做法:使用提煉函數(shù)將參數(shù)的計算過程提煉到一個獨立的函數(shù)

class Order { /* ... */ double getFinalPrice() {const double basePrice = this.quantity * this.itemPrice;int discountLevel = 1;if (this.quantity > 100) discountLevel = 2;return this.discountedPrice(basePrice, discountLevel); }double discountedPrice(const double basePrice, int discountLevel) {switch (discountLevel) {case 1: return basePrice * 0.95;case 2: return basePrice * 0.9;} }};

修改后的代碼:

class Order { public:int quantity = 0;int itemPrice = 0;int discountLevel = 0;Order(int quan, int price, int level){quantity = quan;itemPrice = price;discountLevel = level;}double getFinalPrice(){const double basePrice = this->quantity * this->itemPrice;return this->discountedPrice(basePrice);}int getDiscountLevel(){return (this->quantity > 100) ? 2 : 1;}double discountedPrice(const double basePrice){switch (this->getDiscountLevel()) {case 1: return basePrice * 0.95;case 2: return basePrice * 0.9;}}};

當需要使用discountLevel 變量的時候,后者自己調(diào)用函數(shù),不需要把結果傳入了。
debug結果正確:

int main() {Order* order = new Order(1000,1,0);double res = order->getFinalPrice();std::cout << res << std::endl; }

2、Preserve Whole Object

需要注意:
如果從一個對象中抽取幾個值,單獨對這幾個值做某些邏輯操作,通常標志著這段邏輯應該被搬移到對象中,然后從外部調(diào)用它。
當看見代碼從一個記錄結構中導出幾個值,然后又把這幾個之一起傳給一個函數(shù),那么最好把整個記錄傳給這個函數(shù),在函數(shù)體內(nèi)部導出所需要的值。
舉例:一個室溫監(jiān)控系統(tǒng),負責記錄一天中最高氣溫和最低氣溫,然后將實際溫度范圍與預定溫度控制計劃比較,如果不符合要求,發(fā)出警告。

class HeatingPlan { public:bool withinRange(int bottom, int top){return (bottom >= this._tempRange.low) && (top <= this._tempRange.high);} }; int main() {// 調(diào)用方const int low = aRoom.daysTempRange.low;const int high = aRoom.daysTempRange.high;if(aPlan.withinRange(low, high))std:: cout << "Warning" << std::endl; }

我們不必將溫度范圍的信息拆開單獨傳遞,只需要將整個范圍對象傳遞給withinRange即可
通過重構,可以寫成下面形式:

class HeatingPlan { public:bool withinRange(int bottom, int top){return (bottom >= this._tempRange.low) && (top <= this._tempRange.high);}bool xxNewWithinRange(tempRange range){const int low = range.low;const int high = range.high;const bool res = this.withinRange(low, high);return res;} }; int main() {// 調(diào)用方const tempRange range = aRoom.daysTempRange;const bool isWithinRange = aPlan.xxNewWithinRange(range);if(isWithinRange)std:: cout << "Warning" << std::endl; }

3、Introduce Param Object

當一組數(shù)據(jù)項總是結伴而行,出沒于一個又一個函數(shù),這樣的一組數(shù)據(jù)稱為數(shù)據(jù)泥團,通常用一個數(shù)據(jù)結構來代替它們。
如下方,查看一組溫度讀數(shù)是否有超出運行范圍。

bool readingsOutsideRange(Station station, int min, int max) {return station.readings.filter(station.temp < min || station.temp > max); } int main() {// 調(diào)用方bool res = readingsOutsideRange(station, operatingPlan.temperatureFloor,operatingPlan.temperatureCeiling); }

很顯然,temperatureFloor與temperatureCeiling是一堆數(shù)據(jù)泥團。
我們構造一個新的類去聚合它們,并將判斷邏輯up到這個類的內(nèi)部。

class NumberRange { public:int min;int max;NumberRange(int min, int max){this->min = min;this->max = max;}bool contains(int argv) {return (argv >= this->min) && (argv <= this->max);} }; bool readingsOutsideRange(Station station, NumberRange range) {return station.readings.filter(!range.contains(station.temp)); } int main() {// 調(diào)用方const NumberRange range = new NumberRange(operatingPlan.temperatureFloor, operatingPlan.temperatureCeiling);bool res = readingsOutsideRange(station, range); }

4、Remove Flag Argument

以明確的函數(shù)取代參數(shù)
如:

function setDimension(name, value) {if (name == "height")this->_height = value;else if(name == "width")this->_width = value;return; } 應當轉換為 ====> function setHeight(value) {this->_height = value;} function setWidth(value) {this->_width = value;}

標記參數(shù)指的是調(diào)用者用它來指示被調(diào)函數(shù)應該執(zhí)行哪一部分的邏輯。
上面的情況還算簡單,可以重新構造兩個函數(shù)以及內(nèi)部邏輯,但有時想將標記參數(shù)的分發(fā)邏輯剝離到頂層,需要的工作量很大:
我們可以退而求其次,保留原有的函數(shù),在其之上添加兩個函數(shù):

function setHeight(value) {return setDimension("height", value);} function setWidth(value) {return setDimension("width", value);}

這兩個包裝函數(shù)分別代表了原函數(shù)的一部分使用方式,不過并非從原函數(shù)拆分,而是使用代碼文本強行定義的。

5、Combine Functions into Class

function base(aReading) {...} function taxable(aReading) {...} function calBaseCharge(aReading) {...}應當改為 ======> class Reading {base() {...}taxable() {...}calBaseCharge() {...} };

如果發(fā)現(xiàn)一組函數(shù)形影不離地操作同一塊數(shù)據(jù),且通常使用參數(shù)傳遞的方式將數(shù)據(jù)塊傳給函數(shù),那么,是時候組建一個類。
類能夠明確地給這些函數(shù)提供一個共用地環(huán)境,在對象內(nèi)部調(diào)用函數(shù)可以減少參數(shù)傳遞

Reference

《重構 改善既有代碼的設計.第二版》P324 P319 P140 P314 P144

總結

以上是生活随笔為你收集整理的重构——解决过长参数列表(long parameter list)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。