學習之路三十三:重構技巧的學習


最近看了聖殿騎士大哥的重構文章,其中有幾個重構技巧讓我頗有感觸,特此記錄下。

文章地址:31天重構學習筆記重新整理下載

1.封裝集合,返回集合接口類型 

  這個技巧讓我想起了項目中的代碼,比如:

 1     public class Check
 2     {
 3         private List<Detail> _details = new List<Detail>();
 4 
 5         public IList<Detail> GetDetails()
 6         {
 7             return _details;
 8         }
 9     }
10 
11     public class Detail
12     {
13         public string Name { get; set; }
14     }

    如果這樣設計,那么用戶通過調用GetDetails方法之后就可以對你的集合做任意的改動,這樣的做法是非常危險的,所以必須要改進。

  重構原則:返回可迭代器類型接口來保證對集合的封裝,改進如下:

 1     public class Check
 2     {
 3         private List<Detail> _details = new List<Detail>();
 4 
 5         private Dictionary<int, Detail> _specificDetail = new Dictionary<int, Detail>();
 6 
 7         public IEnumerable<Detail> GetDetails()
 8         {
 9             return _details;
10         }
11 
12         public IEnumerable<KeyValuePair<int, Detail>> GetSpecificDetail()
13         {
14             return _specificDetail;
15         }
16     }
17 
18     public class Detail
19     {
20         public string Name { get; set; }
21     }

  迭代器文章入口:迭代器學習之一:使用IEnumerable和IEnumerator接口

    我將在項目中運用此重構技巧。

 

2.提取判斷條件作為方法 - 方法名要有意義

  當遇到復雜的判斷后,如果沒有注釋,很多人第一眼都不會理解這個判斷是做什么的。

  所以把復雜的判斷條件提取為方法,再取個有意義的名字,那么別人看一眼就明白做什么的,比如:

 1     public class Check
 2     {
 3         public Detail GetDetail { get; set; }
 4 
 5         public void SendMessage()
 6         {
 7             //這樣的判斷別人根本不知道是干什么的
 8             if (GetDetail != null && GetDetail.Number > 0)
 9             {
10                 //Send Message
11             }
12 
13             //重構后的代碼
14             //這樣別人就知道這個判斷的作用:判斷當前的信息有沒有提交
15             if (HasConfirm(GetDetail))
16             {
17                 //Send Message
18             }
19         }
20 
21         public bool HasConfirm(Detail detail)
22         {
23             return GetDetail != null && GetDetail.Number > 0;
24         }
25     }
26 
27     public class Detail
28     {
29         public int Number { get; set; }
30     }

 

3.為帶有大量bool參數的方法重新進行拆分組合

  這個重構手法在項目中還沒有用過,方法帶有大量的bool參數本來就很奇葩,不過如果真的遇到了,我們也有應對方法,如下:

1     public class Test
2     {
//如果是這樣的一個方法,你知道它是干什么的嗎,根本就不能理解它的用意
3 private void Create(bool isA, bool isB, bool isC) 4 { } 5 }

   重構后的代碼:

 1     public class Test
 2     {
 3         //進行拆分后在重新組合
 4         public void CreateA()
 5         {
 6             this.Create(true, false, false);
 7         }
 8 
 9         public void CreateB()
10         {
11             this.Create(false, true, false);
12         }
13 
14         public void CreateC()
15         {
16             this.Create(false, false, true);
17         }
18 
19         private void Create(bool isA, bool isB, bool isC)
20         { }
21     }

 

 4.避免雙重否定

  其實這個重構手法我理解為盡量避免使用在if條件里使用 - “!”.

  因為如果本來你的判斷條件就是表達否定的意思,那么在加上一個否定的判斷,那么就會是雙重否定。

  那別人理解起來是不是會很抓狂,他會在心理畫個圈圈狠狠的詛咒你的,:-),比如:

 1     public class Test
 2     {
 3         public void TestOne()
 4         {
 5             //本來想表達已經付款了,所以只能加個否定來判斷咯
 6             //可是這個交別人理解起來真的很抓狂
 7             if (!NoPayment)
 8             {
 9                 //TO DO
10             }
11         }
12 
13         public bool NoPayment { get; set; }
14     }

   重構后的代碼:

 1     public class Test
 2     {
 3         public void TestOne()
 4         {
 5             //本來想表達已經付款了,所以只能加個否定來判斷咯
 6             //可是這個交別人理解起來真的很抓狂
 7             if (!NoPayment)
 8             {
 9                 //TO DO
10             }
11 
12             //重構后的代碼
13             //避免使用雙重否定來作為判斷條件
14             if (HasPayment)
15             {
16 
17             }
18         }
19 
20         public bool NoPayment { get; set; }
21 
22         public bool HasPayment { get; set; }
23     }

 

5.盡快返回 - 返回值

  這個重構技巧可以分解復雜的判斷條件,是那些冗余的判斷分支化成簡介的小分支,比如:

 1     public class TestOne
 2     {
 3         private List<Detail> _details;
 4 
 5         public void Display()
 6         {
 7             //這么一大長串的判斷條件是不是很惡心
 8             if (_details != null)
 9             {
10                 if (_details.Count > 0)
11                 {
12                     foreach (var item in _details)
13                     {
14                         if (item.Number > 0)
15                         {
16                             //TO DO
17                         }
18                     }
19                 }
20             }
21         }
22     }
23 
24     public class Detail
25     {
26         public int Number { get; set; }
27     }

   重構后的代碼:

 1     public class TestOne
 2     {
 3         private List<Detail> _details;
 4 
 5         public void Display()
 6         {
 7             //重構之后是不是很清爽呀
 8             //哈哈
 9             if (_details == null || _details.Count <= 0)
10                 return;
11             foreach (var item in _details.Where(p => p.Number > 0).Select(p => p))
12             {
13                 //TO DO
14             }
15         }
16     }
17 
18     public class Detail
19     {
20         public int Number { get; set; }
21     }

 

以同步至:個人文章目錄索引


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM