函數主體短小
函數應該以完成功能爲前提,函數主體能短小就多短小。
一件事
函數應該只完成一件事,如果函數存在多種事件處理,需要進行解構整合。如果該函數處理的都在同一抽象層,則代表該函數製作一件事。
每個函數一個抽象層級
自頂向下閱讀,如果出現不同抽象層級的應當進行重構。
Swtich語句
儘量將它使用到抽象底層
使用描述名稱
函數越短小,功能越集中,就越容易取得好名稱。不要害怕長名稱。
函數參數
參數最佳是零參數,其次是一參數,再次是雙參數,如果沒用特殊理由不要使用三(多)參數。
不要使用輸出參數,閱讀難度太大,使用返回值來替代。
無副作用
例如:在檢查賬戶和密碼的時候
checkPassword(userName, password) {
let user = findUserName(userName)
if(user){
let codePhrase = getPhraseEncodeByPassword(userName)
let phtrase = decrypt(codePhrase, password)
if(phtrase === 'Vaild Password'){
Session.initialize()
return true
}
}
return false
}
這裏Session
就是副作用,造成了時許耦合——checkPassword
只有在特定時候調用。如果在不合適的時候調用,就有可能造成會話數據沉默地丟失。如果這些副作用不可避免,應當在函數名體現:checkPasswordAndSessionInit
分隔與指令
當函數需要同時需要修改與返回相關信息的時候,常常會混亂。
set(userName,unclebob)
這個是需要判斷userName
的值是否設置爲unclebob
,還是詢問userName
的值是否成功設置爲unclebobo
呢?從這行語句無法判斷。
所以需要通過指令來分割
if(attributeExists(userName)){
setAttribute(userName, unclebobo)
}
異常替代返回錯誤碼
例如:
if('ok'===deletePage(page)){
if('ok'===registyPage(page)){
//
}else{
throw new Error('registy error')
}
}else {
throw new Error('deletePage error')
}
如果用異常來替代
try{
deletePage(page)
registryPage(page)
}catch(e){
throw new Error(e)
}
這樣就可以把錯誤主體分離出邏輯
避免重複出現
結構化編程
每個函數應該保持一個輸入、輸出,循環中不能出現break,continue,尤其是goto永遠不能出現。
這個適用於大函數編寫,對於小函數而言,偶爾出現break、continue、return可以讓函數表達更明確。
多次修改才能出現好函數
初稿或許會很難堪,你需要不斷的斟酌推敲才能寫出心目中的樣子。從一開始就按照這些規則來寫代碼是不現實的,應該也沒有幾個人能做到。