重构——解决过长参数列表(long parameter list)
目錄
- 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 { 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結果正確:
2、Preserve Whole Object
需要注意:
如果從一個對象中抽取幾個值,單獨對這幾個值做某些邏輯操作,通常標志著這段邏輯應該被搬移到對象中,然后從外部調(diào)用它。
當看見代碼從一個記錄結構中導出幾個值,然后又把這幾個之一起傳給一個函數(shù),那么最好把整個記錄傳給這個函數(shù),在函數(shù)體內(nèi)部導出所需要的值。
舉例:一個室溫監(jiān)控系統(tǒng),負責記錄一天中最高氣溫和最低氣溫,然后將實際溫度范圍與預定溫度控制計劃比較,如果不符合要求,發(fā)出警告。
我們不必將溫度范圍的信息拆開單獨傳遞,只需要將整個范圍對象傳遞給withinRange即可
通過重構,可以寫成下面形式:
3、Introduce Param Object
當一組數(shù)據(jù)項總是結伴而行,出沒于一個又一個函數(shù),這樣的一組數(shù)據(jù)稱為數(shù)據(jù)泥團,通常用一個數(shù)據(jù)結構來代替它們。
如下方,查看一組溫度讀數(shù)是否有超出運行范圍。
很顯然,temperatureFloor與temperatureCeiling是一堆數(shù)據(jù)泥團。
我們構造一個新的類去聚合它們,并將判斷邏輯up到這個類的內(nèi)部。
4、Remove Flag Argument
以明確的函數(shù)取代參數(shù)
如:
標記參數(shù)指的是調(diào)用者用它來指示被調(diào)函數(shù)應該執(zhí)行哪一部分的邏輯。
上面的情況還算簡單,可以重新構造兩個函數(shù)以及內(nèi)部邏輯,但有時想將標記參數(shù)的分發(fā)邏輯剝離到頂層,需要的工作量很大:
我們可以退而求其次,保留原有的函數(shù),在其之上添加兩個函數(shù):
這兩個包裝函數(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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis一个命令请求从发送到完成的步骤
- 下一篇: 单例模式的七种实现方法(java版)