Clean Code_Note7_Remove Duplicated If Statements_Simplify If Statements_Replace Nested If Statements With Guard Clauses
Remove Duplicated If Statements
程式中若出現多段重複的if判斷區塊
可以觀察是否為雷同的判斷情境(回傳值固定之類的)
以下為一個範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | using System; namespace CleanUpConditionals { public class RemoveDuplicatedIfStatements { public static bool IsFibonnaciNumber(int number) { if (number == 0) { return true; } if (number == 1) { return true; } if (number == 2) { return true; } double fi = (1 + Math.Sqrt(5)) / 2.0; int n = (int)Math.Floor(Math.Log(number * Math.Sqrt(5) + 0.5, fi)); int actualFibonacciNumber = (int)Math.Floor(Math.Pow(fi, n) / Math.Sqrt(5) + 0.5); return actualFibonacciNumber == number; } } } |
事實上一個只要符合其中一種條件就返回true的情境
那可合併一個if即可並間接把這段實作抽離成額外一個method
經化簡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | using System; namespace CleanUpConditionals { public class RemoveDuplicatedIfStatements { public static bool IsFibonnaciNumber(int number) { if (IsWithinFirstThreeNumbers(number)) { return true; } double fi = (1 + Math.Sqrt(5)) / 2.0; int n = (int)Math.Floor(Math.Log(number * Math.Sqrt(5) + 0.5, fi)); int actualFibonacciNumber = (int)Math.Floor(Math.Pow(fi, n) / Math.Sqrt(5) + 0.5); return actualFibonacciNumber == number; } private static bool IsWithinFirstThreeNumbers(int number) { return number == 0 || number == 1 || number == 2; } } } |
Simplify If Statements
再針對if多重條件化簡時候都會建議額外抽離一個method命名為有意義的符合條件情境的名稱
會使得程式可閱讀性大增
以下一個也是類似上面的複合條件(OR連接)判斷情境
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | using System; using System.Collections.Generic; using System.IO; namespace CleanUpConditionals { public class SimplifyIfStatements { public void SaveHomeAddress(string name, string homeAddress, string country, string email, string fileLocation) { if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(homeAddress) || string.IsNullOrEmpty(fileLocation)) { Console.WriteLine("Input parameters are empty"); } else { using (FileStream fileStream = new FileStream(fileLocation, FileMode.Append)) using (StreamWriter writer = new StreamWriter(fileStream)) { List<string> aPersonRecod = new List<string> { name, homeAddress, country, email }; writer.WriteLine(aPersonRecod); } } } } } |
經過重構後
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | using System; using System.Collections.Generic; using System.IO; namespace CleanUpConditionals { public class SimplifyIfStatements { public void SaveHomeAddress(string name, string homeAddress, string country, string email, string fileLocation) { if (InputParametersAreEmpty(name, homeAddress, fileLocation)) { WriteErrorToConsole(); } else { WritePersonRecord(name, homeAddress, country, email, fileLocation); } } private static void WritePersonRecord(string name, string homeAddress, string country, string email, string fileLocation) { using (FileStream fileStream = new FileStream(fileLocation, FileMode.Append)) using (StreamWriter writer = new StreamWriter(fileStream)) { List<string> aPersonRecod = new List<string> { name, homeAddress, country, email }; writer.WriteLine(aPersonRecod); } } private static void WriteErrorToConsole() { Console.WriteLine("Input parameters are empty"); } private static bool InputParametersAreEmpty(string name, string homeAddress, string fileLocation) { return string.IsNullOrEmpty(name) || string.IsNullOrEmpty(homeAddress) || string.IsNullOrEmpty(fileLocation); } } } |
Replace Nested If Statements With Guard Clauses
通常會建議不要有太多層的if 判斷,可利用Guard Clause來替代。
以下為一個範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | namespace CleanUpConditionals { public class ReplaceNestedIfStatementsWithGuardClauses { public double GetInterestRate(ClientType clientType) { double result; if (clientType == ClientType.Business) { result = 0.05; } else { if (clientType == ClientType.ExistingClient) { result = 0.02; } else { result = 0.03; } } return result; } } public enum ClientType { Business, ExistingClient, NewClient } } |
以這個範例來說我們只是針對符合特定條件去回傳值就好
不太需要再else區塊分割
因此可以精簡如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | namespace CleanUpConditionals { public class ReplaceNestedIfStatementsWithGuardClauses { public double GetInterestRate(ClientType clientType) { if (clientType == ClientType.Business) { return 0.05; } if (clientType == ClientType.ExistingClient) { return 0.02; } return 0.03; } } public enum ClientType { Business, ExistingClient, NewClient } } |
留言
張貼留言