学习之路三十三:重构技巧的学习
最近看了圣殿骑士大哥的重构文章,其中有几个重构技巧让我颇有感触,特此记录下。
文章地址: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 }
以同步至:个人文章目录索引