如何編寫函數(續)----《代碼整潔之道》讀書筆記

(使用markdown排版后重發一次)
上一篇關于函數的文章寫到編寫函數的幾個注意事項:

  • 函數要短小。
  • 函數只應該做一件事。
  • 函數的參數要盡量少,避免使用輸出函數。
  • 函數要無副作用。
  • 函數要區分指令和詢問。

本篇接著寫關于函數的其他知識。

避免傳標識符參數給函數。標識符是指truefalse。標識符參數意味著函數至少要做兩件事情:true,做一件事;false,做另一件事。我的代碼、其他同事的代碼,用標識符做參數的函數,很常見。如果要將標識從函數中消除,那么將增加函數個數,而且,在函數中由標識符帶來的if...else...結構將轉移到函數之外。這似乎沒有好處。

指令型函數要使用異常處理代替狀態碼返回。請看代碼A。

if(deleteUserById(id) === ERROR_CODE){
    if(deleteUserFriendById(id) === ERROR_CODE){
        return true;
    }else{
        log(errorMsg);
    }
}else{
   log(errorMsg); 
}

deleteUserById(id)deleteUserFriendById(id)都是指令型函數。將上面的代碼改造為代碼B。

try{
    deleteUserById(id);
    deleteUserFriendById(id);
}catch(Exception e){
    log(e);
}

代碼B明顯簡潔了很多,但是我不明白:不同函數拋出的異常是不同的,捕捉到異常后進行處理的代碼也可能是不同的。假如需要針對不同的代碼,進行不同的處理,必須去了解封裝在函數內部的代碼才行。這違背了“開放---封閉”原則。工作至今,我只用過幾次此類處理錯誤的方式。需要深入函數內部去了解所拋出的異常情況,是我不使用此方式的原因。但這個方式是專家提倡的,我需慢慢琢磨,直至透徹理解它的精妙。

代碼B可以進一步改寫為代碼C。

try{
    deleteUserAndFriendById(id);
}catch(Exception e){
    log(e);
}

function deleteUserAndFriendById(id){
    deleteUserById(id);
    deleteUserFriendById(id);
}

從代碼B到代碼C,遵循著編寫函數的又一個原則:把其他大段代碼丑陋不堪的try...catch中剝離出來。至于為什么這么做,除了簡潔,我想不出其他原因。

函數命名,應該使用動詞或動詞短語+名詞的形式。例如,write(name),就是很好的函數名稱。

說點題外話。今日周五,懈怠了,中午一直在看動漫,沒有寫作。

同事前些天推薦使用markdown寫作,今天嘗試了一下。我雖然沒有掌握所有的markdown技巧,但稍加運用,就有不少好處:排版好看了些,尤其是代碼的排版。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容