学习之路三十三:重构技巧的学习

最近看了圣殿骑士大哥的重构文章,其中有几个重构技巧让我颇有感触,特此记录下。

文章地址: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     }

 

以同步至:个人文章目录索引

posted @ 2013-07-21 23:02  TimYang  阅读(599)  评论(11编辑  收藏  举报