天天看點

代碼整潔之道—函數

在程式設計的早期,系統由程式和子程式組成,後來,在Fortran和PL/1的年代,系統由程式,子程式和函數組成。如今,隻有函數存活下來。

函數的規則

短小

函數的第一規則是要短小,第二規則還是要更短小。雖無法證明,但是經驗告訴作者,函數就該短小。

if ,else,while語句,其中的代碼塊應該隻有一行,該行應該是一個函數調用語句,這樣不但能保持函數短小,而且塊調用内的函數擁有較具說明性的名稱,進而增加了文檔的價值。

這也意味着函數不應該大到足以容納嵌套結構,是以,函數的縮進層級不應該多于一層或兩層。當然這樣的函數易于了解。

隻做一件事

新手寫程式的時候,容易覺得函數隻是用來重複利用代碼塊,隻要有重複性的東西都提取的函數中,其實不僅僅這樣。

函數應該做一件事,做好這件事,隻做這一件事。

要判斷函數是否不止做了一件事,還有一個方法,就是看能否再拆出一個函數。

每個函數一個抽象層級

要確定函數隻做一件事,函數中的語句都要在同一個抽象層級上。函數中混雜不同的抽象層級,往往令人迷惑,讀者可能無法判斷某個表達式是基礎概念還是細節。更惡劣的是,一旦細節與基礎概念混雜,更多的細節就會在函數中糾結起來。

自頂向下讀程式,每個函數後面跟着位于下一抽象層級的函數。

代碼整潔之道—函數

函數調用過程

看圖,了解每個函數的邏輯層級關系。我們自己寫的函數能理為如此清晰的思路就夠了。

函數參數

最理想的參數量是零個,其實是一個,再次是二,應該盡量避免三個及以上的參數。

如果函數需要兩個,三個,或三個以上的參數,就說明其中一些參數該封裝為類了。

從測試的角度來看,要編寫能確定參數的各種組合運作正常的測試用例,是多麼的困難。如果沒有參數,就很簡單,隻有一個參數,也不太困難,有兩個參數,問題就麻煩多了。如果參數多于兩個,測試覆寫的可能性值的組合令人生畏。

辨別函數

最好不要像函數傳入bool類型的值,這樣做,方法簽名立刻變得複雜起來,大聲宣布函數不止做一件事,辨別為true會這樣做,辨別為false會那樣做。

滾動螢幕,看到render(Boolen isSuite),應該将函數一分為二: renderForSuite()和renderForSingleTest()

分隔指令與詢問

函數要麼做什麼事,要麼回答做什麼事,但兩者不可得兼。函數應該修改某對象的狀态,或者傳回改對象的有關資訊,兩樣常幹常會導緻混亂。

含糊不清的語句:這是判斷某個屬性是否為為某個值,還是給屬性設定某個值呢?

public boolen set(String attribute,String value)
           

修改方案,把指令分隔開來,防止混淆的發生

if (attributesExists("userName")){
  setAttribute("userName","aihe")
}
           

抽離try/catch代碼塊

try/catch會把程式弄的醜陋不堪,搞亂了代碼結構,把錯誤與正常流程混為一談。最好把tray和catch的主體部分抽離出來,另外形成函數。

//隻處理錯誤,無需關心其它的
public void delete(Page page){
  try{
        deletePageAndAllReferences(page);
   }
   catch(Exception e ){
       logError(e)
   }
}

//隻處理邏輯,無需關心錯誤
public void  deletePageAndAllReferences(Page page) throw Exception{
    ....
}

           

結構化程式設計

結構化程式設計規則:

每個函數,函數中的代碼塊都應該隻有一個入口,一個出口。遵循這些規則,意味着每個函數中隻該由一個return語句,循環中不能有break貨continue語句。

結構化程式設計的目标和規範可以遵守,但偶爾出現的return語句沒有多大壞處,但是盡量遵守規則。

書小結

每個系統都是使用某種領域特定語言搭建,而這種語言是程式員設計來描述那個系統的。函數是語言的動詞,類是名詞。

大師級程式員把系統當做故事來寫,而不是當做程式來寫。他們使用程式設計語言提供的工具建構一種更為豐富且更具有表達力的語言,用來講那個故事。

最後

仔細品味開發的精髓,代碼整潔之道,獲益良多。

繼續閱讀