重構——重新組織函數 - 新聞資(zī)訊 - 雲南小程序開發|雲南軟件開發|雲南網站(zhàn)建設-西山區知普網絡科技工作室

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不管是網站(zhàn),軟件還是小程序,都要直接或間接能為您産生價值,我們在追求其視覺表現的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網站(zhàn)成為營銷工具,讓軟件能切實提升企業(yè)内部管理水平和(hé)效率。優秀的程序為後期升級提供便捷的支持!

您當前位置>首頁 » 新聞資(zī)訊 » 技術(shù)分享 >

重構——重新組織函數

發表時間:2020-10-19

發布人:葵宇科技

浏覽次數:30

Extract Method提煉函數

動(dòng)機

首先如(rú)果每個(gè)函數的粒度都很小,那麼函數被複用的機會就更大;其次,這會使高層函數讀起來就像一系列注釋;再次,如(rú)果函數都是細粒度,那麼函數的覆寫也會更容易。

做法

  • 創造一個(gè)新函數,根據這個(gè)函數的意圖來對它進行命名(以它“做什麼”來命名而是“怎麼做”)。

  • 将提煉出來的代碼從源函數複制到新建的目标函數中(zhōng)。

  • 仔細檢查提煉出的代碼,看看其中(zhōng)是否引用了作用域限于源函數的變量(包括局部變量和(hé)源函數參數);

  • 檢查是否有“僅用于被提煉代碼段”的臨時變量,如(rú)果有,在目标函數中(zhōng)将它們聲明為臨時變量。

  • 檢查被提煉代碼段,看看是否有任何局部變量的值被它改變,如(rú)果有一個(gè)臨時變量值被修改了,看看是否可(kě)以将提煉代碼段處理為一個(gè)查詢,并将結果賦值給相關(guān)變量。

  • 将被提煉代碼段中(zhōng)需要讀取的局部變量當做參數傳給目标函數。

  • 處理完所有局部變量後,進行編譯。

Inline Method(内聯函數)

在這裡插入圖片描述

動(dòng)機

  • 簡短(duǎn)的函數表現動(dòng)作意圖會使代碼更清晰易讀,但有時候會遇到某些函數,其内部代碼和(hé)函數名稱同樣清晰易讀;
  • 将一群不甚合理的函數内聯到一個(gè)大型函數中(zhōng),再從中(zhōng)提煉出組織合理的小型函數,比起既要移動(dòng)一個(gè)函數、又要移動(dòng)它所調用的其他所有函數,将整個(gè)大型函數作為曾提移動(dòng)會比較簡單;
  • 如(rú)果别人使用了套太多間接層,使得系統中(zhōng)的所有函數都似乎隻是對另一個(gè)函數的簡單委托,造成代碼閱讀時候在這些委托動(dòng)作之間暈頭轉向,通(tōng)常使用内聯函數,當前指的是那些無用的間接層。

做法

  1. 檢查函數,确定它不具有多态性;

  2. 找出這個(gè)函數的所有被調用點;

Inline Temp(内聯臨時變量)

在這裡插入圖片描述

動(dòng)機

内聯臨時變量多半是作為以查詢替代臨時變量的一部分使用的,所以真正的動(dòng)機出現在後者那,但是,如(rú)果你(nǐ)發現某個(gè)臨時變量被賦予某個(gè)函數調用的返回值,雖然這并沒有任何危害,但是如(rú)果妨礙了其他重構手法,就應該将它内聯化。

做法

  1. 檢查給臨時變量賦值的語句,确保等号右邊的表達式沒有副作用;

  2. 如(rú)果這個(gè)臨時變量并未被聲明為final,則聲明;

  3. 找到該臨時變量的所有引用點,将它們替換為為臨時變量賦值的表達式;

  4. 每次修改後,編譯并測試;

  5. 修改完所有引用點之後,删除該臨時變量的聲明和(hé)賦值語句;

Replace Temp with Query(以查詢取代臨時變量)

在這裡插入圖片描述

動(dòng)機

臨時變量的問(wèn)題在于:它們是暫時的,而且隻能在所屬函數内使用,由于臨時變量隻在所屬函數内可(kě)見,所以它們會驅使你(nǐ)寫出更長的函數,因為這樣才能訪問(wèn)到函數上面定義的臨時變量。如(rú)果把臨時變量替換為一個(gè)查詢,那麼同一個(gè)類中(zhōng)的所有函數都将可(kě)以獲得這份信息。局部變量會使代碼難以被提煉,所以應盡可(kě)能把他們替換為查詢式

這個(gè)重構手法比較簡單的情況是:臨時變量隻被賦值一次,或者賦值給臨時變量的表達式不受其他條件影響。對于其他情況可(kě)能需要先運用分解臨時變量以查詢函數和(hé)修改函數分離(lí)使得情況變得簡單一些,如(rú)果你(nǐ)想替換的臨時變量是用來收集結果的(例如(rú)循環中(zhōng)的累加值),就需要将這些程序邏輯複制到查詢函數去。

做法

簡單情況:

  1. 找出制備複制一次的臨時變量,如(rú)果某個(gè)臨時變量被賦值超過一次,考慮使用分離(lí)臨時變量法将它分割成多個(gè)變量;

  2. 将該臨時變量聲明為final;

  3. 對該臨時變量賦值之語句的等号右側部分提煉到一個(gè)獨立函數中(zhōng);

對臨時變量進行累加的循環可(kě)以被提煉為一個(gè)獨立的函數,對于一個(gè)循環累加好幾個(gè)值的時候,你(nǐ)應該針對每個(gè)累加值重複一遍,這樣可(kě)以将所有臨時變量替換為查詢。

Introduce Explaining Variable(引入解釋性變量)

在這裡插入圖片描述

動(dòng)機

你(nǐ)可(kě)以用這項重構将每個(gè)條件子(zǐ)句提煉出來,以一個(gè)良好命名的臨時變量來解釋對應條件子(zǐ)句的意義。

Split Temporary Variable(分解臨時變量)

在這裡插入圖片描述

動(dòng)機

臨時變量有各種不同的用途,其中(zhōng)某些用途會很自然地導緻臨時變量被多次賦值,循環變量和(hé)結果收集變量就是典型的例子(zǐ),除此之外,還有很多臨時變量用于保存一段冗長代碼的運算結果,以便稍後使用。這種臨時變量應該隻被賦值一次,如(rú)果它們被賦值多次,就意味着它們在函數中(zhōng)承擔一個(gè)以上的責任,如(rú)果臨時變量承擔多個(gè)責任,它就應該被替換為多個(gè)臨時變量,每個(gè)變量隻承擔一個(gè)責任。

做法

  1. 在待分解臨時變量的聲明及其第一次被賦值處修改其名稱,除了累加、字符串結合、寫入流或者向集合添加元素的變量。

  2. 将新的臨時變量聲明為final;

  3. 以該臨時變量的第二次賦值動(dòng)作為界,修改此前對該臨時變量的所有引用點,讓它們引用新的臨時變量。

  4. 在第二次賦值處,重新聲明原先那個(gè)臨時變量;

  5. 逐次重複上述過程;

Remove Assignments to Parameters(移除對參數的賦值)

在這裡插入圖片描述

動(dòng)機

不要對參數賦值,因為它降低了代碼的清晰度,而且混用了按值傳遞和(hé)按引用傳遞這兩種參數傳遞方式,Java隻采用按值傳遞的方式。

在按值傳遞的情況下(xià),對參數的任何修改都不會對調用端造成任何影響

做法

  1. 建立一個(gè)臨時變量,把待處理的參數值賦予它;
  2. 對參數的賦值為界,将其後所有對此參數的引用點,全部替換為對此臨時變量的引用
  3. 修改賦值語句,使其改為對新建臨時變量賦值;

Replace Method with Method Object(以函數對象取代函數)

動(dòng)機

将相對獨立的代碼從大型函數中(zhōng)提煉出來就可(kě)以大大提高代碼的可(kě)讀性,但是局部變量的存在會增加函數分解難度。

以函數對象取代函數會将所有局部變量都變成函數對象的字段,然後就可(kě)以對這個(gè)新對象使用提煉函數創造新函數,從而将原本的大型函數拆解變短(duǎn)。

做法

  1. 建立一個(gè)新類,根據待處理函數的用途,為這個(gè)類命名;
  2. 在新類中(zhōng)建立一個(gè)final字段,用以保存原先大型函數所在的對象,将這個(gè)字段稱為源對象,同時,針對這個(gè)原函數的每個(gè)臨時變量和(hé)每個(gè)參數在新類中(zhōng)建立一個(gè)對應的字段保存。
  3. 在新類中(zhōng)建立一個(gè)構造函數,接收源對象及原函數的所有參數作為參數;
  4. 在新類中(zhōng)建立一個(gè)compute()函數;
  5. 将原函數的代碼複制到compute()函數中(zhōng),如(rú)果需要調用源對象的任何函數,請通(tōng)過源對象字段調用;
  6. 将就函數的函數本體替換為創建上述新類的一個(gè)新對象,而後調用其中(zhōng)的compute()函數

Substitile Algorithm(替換算法)

在這裡插入圖片描述

相關(guān)案例查看更多