閱讀文章時,如果某個段落已經傳達了關鍵信息,我們可能就不會逐字逐句地將文章讀完,因為我們已經知道了這篇文章的核心內容。 與此類似,如果方法中某些條件判斷可以得到結果,我們應該儘快返回該結果。 儘快返回可以帶來三個好處:1. 節省閱讀代碼的時間 2. 避免執行無效的邏輯 3. 增強代碼的可讀性 ...
概述
閱讀文章時,如果某個段落已經傳達了關鍵信息,我們可能就不會逐字逐句地將文章讀完,因為我們已經知道了這篇文章的核心內容。
與此類似,如果方法中某些條件判斷可以得到結果,我們應該儘快返回該結果。
儘快返回可以帶來三個好處
- 節省閱讀代碼的時間——如果方法能夠儘快返回,後面的代碼邏輯可以不必閱讀。
見下圖,如果①已經返回了,就不必閱讀②部分的代碼 - 避免執行無效的邏輯——如果方法能夠儘快返回,後面的代碼邏輯就不會被執行。
見下圖,如果①已經返回了,②部分的邏輯不會被執行 - 增強代碼的可讀性
在分解大括弧這篇文章中,我們已經用到了“儘快返回”這個重構策略。
在實現複雜的業務邏輯時,可能會形成多層的代碼嵌套,如果某些條件判斷可以得到結果,我們應該儘快返回這個結果,這也能夠減少嵌套層數,從而增強代碼的可讀性。
示例
下麵沿用了分解大括弧這篇文章中的實例,但我會從“儘快返回”的角度去講解這個示例。
重構前
Security類的HasAccess方法為了判斷用戶是否有許可權訪問,直到方法的最後一行才返回結果。
這個方法有4層嵌套,它的可讀性本身是較差的,這意味著我們需要理解所有的嵌套邏輯,才能知道返回結果。
public class Security { public ISecurityChecker SecurityChecker { get; set; } public Security(ISecurityChecker securityChecker) { SecurityChecker = securityChecker; } public bool HasAccess(User user, Permission permission, IEnumerable<Permission> exemptions) { bool hasPermission = false; if (user != null) { if (permission != null) { if (exemptions.Count() == 0) { if (SecurityChecker.CheckPermission(user, permission) || exemptions.Contains(permission)) { hasPermission = true; } } } } return hasPermission; } } public interface ISecurityChecker { bool CheckPermission(User user, Permission permission); }
HasAccess方法的邏輯可以分解為3個步驟:
- 當user或permission為null時,返回false
- 當參數permission是參數exemptions的一個元素時,返回true
- 返回SecurityChecker.CheckPermission(user, permission)的調用結果
下圖標示了這3個步驟。
這3個步驟都能決定方法的返回結果,它們之間沒有相互依賴性。
我們可以將這3個步驟分離開來,然後指定這3個步驟的執行順序,並儘快返回結果。
重構後
重構後,HasAccess方法的邏輯一目瞭然,它的3步邏輯都用到了return,易於閱讀和理解。
隱藏代碼public class Security { public ISecurityChecker SecurityChecker { get; set; } public Security(ISecurityChecker securityChecker) { SecurityChecker = securityChecker; } public bool HasAccess(User user, Permission permission, IEnumerable<Permission> exemptions) { if (user == null || permission == null) return false; if (exemptions.Contains(permission)) { return true; } return SecurityChecker.CheckPermission(user, permission); } } public interface ISecurityChecker { bool CheckPermission(User user, Permission permission); }
小結
如果能夠儘快得到結果,何必等到最後一刻?
小酌重構系列目錄彙總 【關註】keepfool