最近看了聖殿騎士大哥的重構文章,其中有幾個重構技巧讓我頗有感觸,特此記錄下。
文章地址: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 }
以同步至:個人文章目錄索引