【轉】PHP 雜談《重構-改善既有代碼的設計》之一 從新組織你的函數

思惟導圖
 
點擊下圖,能夠看大圖。

 
 介紹
 
我把我比較喜歡的和比較關注的地方寫下來和你們分享。上次我寫了篇《php 跟老大的對話》。仍是有不少疑問,這書幫了我很多的忙。
 
若是你比較繁忙,或者懶得看文字,建議你直接看截圖,也會有很大的收穫的。你能夠經過比較截圖中的代碼就能知道孰優孰劣了。
 
代碼部分我爲何用圖呢?由於我常常用手機看代碼,博客園的代碼在手機裏亂七八糟的,仍是看圖比較舒服。
 
 專業術語
 
咱們畢竟是用英文字母編碼,因此用一些英語單詞,更能顯示出咱們的專業性。如下的英文單詞,你若是掌握了,與其餘coder交流的時候會更直接,更專業。——臭顯擺一下吧,呵呵。
「*」表示文中常常提到的
 
inline:內聯
function:函數
*method:方法
finely grained:細粒度的
rename:重命名
query:查詢
temp:臨時(temporary)——通常指臨時變量
*extract:提取——我我的更喜歡翻譯成「提煉」
*duplicate:複製
split:剖解
variable:變量
factor:因素,因子
 
 重構原則
 
1、何謂重構?
     名詞形式:對軟件內部結構的一種調整,目的是在不改變軟件之可察行爲前提下,提升其可理解型性,下降其修改爲本。
  動詞形式:使用一系列重構準則,在不改變軟件之可察行爲前提下,調整其結構。
 
 2、爲什麼重構 ?
  一、常常重構可讓代碼維持該有的形態。
  二、讓代碼找到合適的位置。
  三、讓軟件更易理解。
  四、能夠找到bug。
  五、提升咱們的編碼速度。

 3、重構的難題
  一、修改接口命名
    若是你的類中的方法是public,那麼你在rename的時候,冒着很大的風險,你不知道到底有哪些模塊在調用你的這個方法(咱們常常的作法是在整個項目下作grep操做,而後逐一看各個模塊的調用和邏輯)。——因此咱們在編寫類的時候無論是屬性仍是方法儘可能作到private,避免接口開放。
 
  二、什麼時候不應重構
    (1)重寫全部代碼,並且現有代碼實在太混亂,重構還不如重寫。
    (2)項目臨近結束的時候,應該避免重構。咱們能夠把重構放到二期去解決。 

 

 代碼的壞味道
  1、Duplicate Code
  一、同一個類,兩個方法含有相同表達式。
    解決方法:你能夠Extract Method提煉重複代碼,而後讓這兩個方法都調用這個Extract Method。
       二、兩個類,有類似的方法。
     解決方法:(1)把兩個類的方法提出來,共同構造一個父類。
             (2)把其中一個類的方法刪除,調用另外一個類的方法。
 2、Long Method
  一、短函數:代碼閱讀費點力氣,由於咱們必須常常轉換上下文去看看子程序作了什麼。可是讓small method容易理解的真正關鍵在於一個好的名字。讀者能夠經過名字瞭解函數的做用,根本沒必要去看其中寫了些什麼。—— 早期的編程語言中,調用方法須要額外開銷,這使得coder不肯意使用small method。可是現代的OO語言幾乎已經徹底免除了process內的額外開銷(函數調用)。
 
  二、註釋地方提煉信號:每當感受須要以註釋來講明點什麼的時候,咱們就把須要說明的東西寫進一個獨立函數中,並以其用途命名。能夠對一組或甚至短短一行代碼作這件事。——只要函數名稱可以解釋其用戶,咱們也該絕不猶豫地那麼作。
 
"函數"理解爲」作什麼「或」如何作「
 
  三、條件式和循環經常也是提煉信號。
 
  四、《代碼整潔之道》的一個例子。咱們能夠想一想!

 
3、Large Class
 
  一、Class內數個屬性變量有相同前綴或者字尾,可以使用Extract Class。
 
  二、Class內並不是大多數變量使用屬性變量,可以使用Extract Class。
  
  三、有太多代碼,可Extract Class。
 
4、Long Parameter
  作成Introduce Parameter Object。——這個我不太贊同,由於我在使用別人方法的時候,我不多去看代碼實踐,更不要說去看裏面都用到了對象的那些屬性或者方法,取我想要的數據了。
 
5、Switch Statements
  一、少用switch語句。——問題在於duplication。添加新case的時候,你必須找到全部case並修改它們。
  
  二、用多態來替換它。作法:1.將switch進行Extract Method;2.MoveMethod把case裏的實踐代碼放到多態性的class裏。
 
6、 Comments
  試試用Extract Method,若是還不行,那你試試Rename Method。
 
當你感受須要撰寫註釋,請先嚐試重構,試着讓全部註釋變得多餘。
 
  註釋通常用於未來的打算,還能夠用於你並沒有十足把握的區域(爲何作某事)。
 
 從新組織你的函數
 
  Long Method每每包含太多信息,這些信息又被錯綜複雜的邏輯掩蓋,不易鑑別。
 
1、Extract Method
情況:我看見一個過長的函數或者須要一段註釋才能讓人理解用途的代碼,那麼將這段代碼放進一個獨立函數中,並讓函數名稱解釋改函數的用途。

 

動機:php

簡短而有良好命名的函數:——finely grainedhtml

  一、複用機會大。算法

  二、函數讀起來像讀一系列comments。編程

  三、函數覆寫容易。編程語言

重點:函數長度關鍵在於函數名稱和函數本體之間的語義距離。若是提煉動做能夠強化代碼的清晰度,那麼就去作。函數

做法:post

  一、建立新函數,根據函數的意圖命名——以它「作什麼」命名,而不是以它「怎樣作」命名。性能

    =》 即便Extract Function 很是簡單,例如只是消息或函數調用,只要新Function可以以更好方式昭示代碼意圖,你也應該提煉它。但若是你想不出更有意義的名稱,就別動它。優化

  二、將Extract的代碼從Source Function 中Move到New Function中。編碼

2、Inline Method

  Method Body與Method Name同樣清晰易懂的時候,請Inline Method。

 

3、Inline Temp

一個臨時變量,只被一個簡單表達式賦值一次,並且賦值完也只使用了一次。——請Inline Temp

 

4、Replace Temp with Query

若是一個Temp變量,保存一個表達式,將這個表達式Extract Method。——這就是所謂的查詢式,query

 

動機:

  一、局部變量會使代碼難以提煉。

  二、臨時變量會驅使你寫出更長的代碼。若是改爲query method,那麼class下的method,均可以得到這份信息。——將編寫出更清晰的代碼。

  三、Replace Temp with Query每每是你運用Extract Method以前必不可少的步驟。

做法:

  一、找出只被賦值一次的臨時變量。

    =>  若是臨時變量賦值超過一次,考慮使用Split Temporary Variable將它分割成多個變量。

  二、對Temp Variable賦值的右側部分,Extract到一個獨立函數中。

           =>  將Method聲明爲private,往後若是有其餘class用的時候再放開它(public或protected)。

  

若是代碼組織良好,那麼你每每能發現更有效的優化方案。————若是性能真的很糟糕,那麼放回去也很容易。
 
5、Introduce Explaining Variable
 
將複雜表達式中(或其中一部分)的結果放進一個臨時變量,以此變量名稱來解釋表達式用途。
 

 
動機:
  表達式複雜並且難以閱讀。在這種狀況下,臨時變量能夠幫助你將表達式分解爲比較容易管理的形式。
  
 6、Split Temporator Variable
 
 某個臨時變量被賦值超過一次,它既不是循環變量,也不是集合變量。那麼 針對每次賦值,創造一個獨立的,對應的臨時變量。

 

 

動機:

  一、若是臨時變量承擔多個責任,它就應該被替換爲多個臨時變量。每一個變量只承擔一個責任。

  二、同一個臨時變量承擔兩件不一樣的事情,會令review變得糊塗。

6、Remove Assignments To Parameters
若是你的代碼對參數進行賦值,那麼 以一個臨時變量取代該參數的位置
 

 

7、Replace Method with Method Object

大型函數對局部變量的使用沒法採用Extract Method。那麼將這個Method放進一個單獨對象中,如此一來,讓局部變量成爲對象的filed,而後在同一個對象中將大型函數分解爲數個小型Method。

 

 

動機:

  一、將相對獨立的代碼從大型Method中Extract出來,就能夠大大提升代碼的可讀性。

  二、一個Method中,局部變量氾濫成災,分解這個函數將會很是困難。

  三、Replace Method with Method Object 會將全部局部變量變成對象的值域。而後對這個新對象進行Extract Method了。

8、Substitute Algorithm
 
若是你想把某個算法替換爲另外一個更清晰的算法,那麼 將Method Body替換爲另外一個算法。——就是直接修改原來的Method Body。
 
動機:隨着對問題有了更多的瞭解,你發現一件事能夠有更清晰的方式,就應該以較清晰的方式取代複雜方式。
 
 總結
 
這只是本書的一部份內容,我知道會有不少的coder應該有不一樣的觀點,我本身也是,有的很贊同,有的我也是不太贊同的。因此要「則其善之而從之,其不善之而改之」。
 
歡迎你們發表下本身的見解。
相關文章
相關標籤/搜索