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
    }
}






留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header