- 短小
- 說明:20行的函數是最佳的。每一個函數只作一件事,而且函數都以順序帶到下一個函數,這就是函數應該到達的短小程度。
- 只作一件事
- 說明:函數應該只作一件事。作好一件事。只作這一件事。判斷函數是否只作一件事,看是否還能在拆分出一個函數。
- 使用描述性的名稱
- 說明:函數的名字正好描述了該函數所作的事,要作到見名知意。別懼怕長名稱,長而具備描述性的名稱,要比短而使人費解的名稱好,要比描述性的長註釋好。函數命名有個好辦法,首先考慮應該給這個函數寫上一句怎樣的註釋,而後想辦法將註釋變成函數的名稱。
- 無反作用
- 函數承若只作一件事,可是隱藏作了另一些事,讓人迷惑,致使古怪的時序性耦合及順序依賴。
// 下面這個函數有「反作用」,有隱藏邏輯
public boolean isExpired(String key) {
if (currentTimes - begainTimes > MAX_EXPIRE_SECONDS) {
// 注意這個地方的delete是個隱藏邏輯
delete(key);
return true;
}
return false;
}
// 優化方式1:提煉判斷邏輯,去除刪除邏輯
public boolean isExpired(String key) {
if (currentTimes - begainTimes > MAX_EXPIRE_SECONDS) {
return true;
}
return false;
}
// 優化方式2:修改函數名稱,讓其名副其實
public boolean delKeyIfExpired(String key) {
if (currentTimes - begainTimes > MAX_EXPIRE_SECONDS) {
delete(key);
return true;
}
return false;
}
- 每一個函數一個抽象層級
- 說明:要確保函數只作一件事,函數中的語句都要在一個抽象級上。自頂向下讀代碼。
- 函數參數
- 說明:儘可能避免三個參數以上,參數越多測試覆蓋全部可能的值的組合就越多,
若是參數過多就該將參數封裝成類了。儘可能使用零參數函數,一參數函數,函數參數越多就越難理解。
public void doTask(Integer taskType, String value, Long taskId, Date createTime, String creater) {
// dosomething
}
// 優化:一個參數,之後再擴展參數也能夠靈活添加,不用改接口
public void doTask(Task task) {
// dosomething
}
- 使用異常,不要返回錯誤碼
- 說明:使用異常代替錯誤碼,錯誤的處理代碼就能從主路徑代碼中分離出來,獲得簡化。
// 假設出異常返回錯誤碼,對異常邏輯當即處理,下面判斷邏輯和嵌套邏輯就會很是複雜。
if (buildTask() == SUCCESS) {
if (buildIndex() == SUCCESS) {
if (doTask() == SUCCESS) {
if (releaseIndex()) {
log.error("releaseIndex success!!")
} else {
log.error("releaseIndex failed!!")
}
} else {
log.error("doTask failed!!")
}
} else {
log.error("buildIndex failed!!");
}
} else {
log.error("buildTask failed!!");
}
// 優化:錯誤處理代碼從主路徑中分離出來,這樣就會簡潔不少。
try {
buildTask();
buildIndex();
doTask();
releaseIndex();
} catch (Exception e) {
log.error("", e)
}
- 別重複本身
- 說明:若是過多的重複代碼就應該抽取出來,消除冗餘,減小重複。DRY,若是你們代碼能作到這點,代碼就會提高很多。
// 假設代碼中有大量相似判斷taskType作邏輯的,若是後面改了增長了一種類型也走之前邏輯,這樣就要改N處,很容易漏掉
if (taskType in (START,PAUSE)) {
// dosomthing
}
// 優化:提煉公共邏輯,這樣增長taskTyoe類型,只用修改一出地方
boolean isDoTasktype (Interger taskType) {
return taskType in (START,PAUSE,RELEASE,REMOVE);
}
// 優化:原有判斷邏輯改成統一調用函數實現
if (isDoTasktype(taskType)) {
// dosomething
}
- 儘可能少用switch語句
- switch語句會致使如下問題:第一,會變的很長;第二,很容易違反單一權責原則(SRP);第三,很容易違反開閉原則(OCP)。簡單的switch語句還好,複雜的語句能夠經過策略模式來替代。
- 如何寫出這樣的函數
- 說明:一開始寫函數都不會太完美,須要反覆打磨、分解函數、修更名稱、消除重複、測試。讓函數更加短小,職責更加單一,命名更加合理。