用好#region指令实现良好的代码组织_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 用好#region指令实现良好的代码组织

用好#region指令实现良好的代码组织

 2010/9/19 23:40:05  lynnlin  http://lynnlin.javaeye.com  我要评论(0)
  • 摘要:这篇文章我将不会去介绍如何使用#region指令。因为每个C#开发人员都应该见过和使用过#region指令的。这篇文章将讨论如何在代码中正确的使用它。使用#region就是将一些有关联的代码组织在一起,然后折叠起来。这样你就在一个函数中看不到很长很长的代码段。例如:publicvoidDoSomething(){boolshouldIDoSomething;#regionDecideifIshoulddosomethingif(needToDoSomething&&
  • 标签:用好#region指令实现良好 代码组织

这篇文章我将不会去介绍如何使用#region指令。因为每个C#开发人员都应该见过和使用过#region指令的。这篇文章将讨论如何在代码中正确的使用它。使用#region就是将一些有关联的代码组织在一起,然后折叠起来。这样你就在一个函数中看不到很长很长的代码段。例如:

  1. public?void?DoSomething() ?
  2. {?? ?
  3. bool?shouldIDoSomething;??? ?
  4. #region?Decide?if?I?should?do?something? ?
  5. if(needToDoSomething?&&?haventDoneSomethingThisDay) ?
  6. shouldIDoSomething?=?true;? ?
  7. ?else?? ?
  8. { ?
  9. //?do?some?other?logic?to?decide?and?
  10. set?shouldIDoSomething?to?some?value ?
  11. ?}?? ?
  12. #endregion??? ?
  13. if(shouldIDoSomething)?? ?
  14. {done++;??}}?

当然这段代码很简单。在实际项目中,你可能看到上百行甚至更多的代码在一个#region中。如果把它折叠起来。看起来就会很整洁。是吧?

  1. public?void?DoSomething() ?
  2. {?? ?
  3. bool?shouldIDoSomething;??? ?
  4. [Decide?if?I?should?do?something]??? ?
  5. if(shouldIDoSomething)?? ?
  6. {done++;?? ?
  7. }}?

我们只是把一些代码和一些变量组合起来放在#region中。如果你在仔细想想,其实我们相当与创建了一个新的函数,只是将这些方法内置到当前方法中。一个函数只做单一的一件事情,这是Clean Code这本书的一个原则。为什么我们不把它提取为一个方法呢,这样一来,一个函数就只做一件事情了。

  1. public?void?DoSomething(){?? ?
  2. if(ShouldIDoSomething())? ?
  3. ?{done++;??}}? ?
  4. private?bool?ShouldIDoSomething(){?? ?
  5. if(needToDoSomething?&&?haventDoneSomethingThisDay) ?
  6. shouldIDoSomething?=?true;?? ?
  7. else? ?
  8. ?{ ?
  9. //?do?some?other?logic?to?decide? ?
  10. and?set?shouldIDoSomething?to?some?value??}}?

这样看起来就清楚很多,因为我们降低了之前的DoSomething函数的复杂度。两个函数可以分开测试,确保没有逻辑错误
小段总结1:? #region 不适合在大方法中使用,当你在一个方法中使用#region 的时候,停下来想想你刚刚写了什么代码?大多数时候,你可以将这些代码段独立成一个函数。

看看下面这段非常漂亮的代码:

  1. #region?Get?Customer? ?
  2. public?void?GetCustomer(){?? ?
  3. //?code?to?get?the?customer}? ?
  4. #endregion? ?
  5. #region?Save?Customer? ?
  6. public?void?SaveCustomer(){?? ?
  7. //?code?to?save?the?customer}? ?
  8. #endregion?

将它折叠之后,变成下面这样:

  1. [Get?Customer]?[Save?Customer]?

这样做很容易阅读吗?这样做的目的是什么,我不明白?代码折叠就会变得更好?我觉得这样做只会让代码更难以阅读,因为你每次要看region中的代码,你都要展开一次。

小段总结2:不要因为你能,你就使用#region 。

再看下面这个例子

  1. public?class?PriceCalculator{?? ?
  2. public?decimal?CalculatePrice()?? ?
  3. {decimal?price?=?100m;decimal?discount?=?CalculateDiscount(); ?
  4. return?price?*?(1m?-?discount));? ?
  5. ?}??? ?
  6. #region?Discount?Calculation??? ?
  7. private?void?CalculateDiscount()?? ?
  8. {decimal?discount?=?0m;? ?
  9. if(CanApplyDiscount())?? ?
  10. discount?=?0.05m;? ?
  11. return?discount;? ?
  12. ?}??? ?
  13. private?void?CanApplyDiscount()??{ ?
  14. //?some?logic,?other?method?calls??}??? ?
  15. //?some?other?discount?calculation?methods??...??? ?
  16. #endregion}?

如果你将这个例子和本文中的第一个例子做下比较,你可能会看到它们的共同点。他们是相同的,不过一个是在类中,一个是在函数中,层级不同而已。这里在提一个原则:单一职责原则,一个类应该只有一个职责。看上面的类,你可以很容易看出它有两个职责:价格计算和折扣计算。折扣计算的方法被放到一个#region中。同样,可以将它们提取出来做为一个新类。

小段总结3:可以将一组相关的函数提取到一个职责单一的新类中。

那我们到底怎么使用 #region 呢。将东西用它来分组,它是非常有用的。在我写的类中或多或少有几个regions,用来对类中不同的结构进行分组。比如: fields, properties, methods, events, types等。如果你打开我写的类文件,你会看到结构如下:

  1. public?class?SomeClass{??
  2. [Events]??
  3. [Fields]??
  4. [Properties]???
  5. [Methods]}?

总的来说:我将region看成能控制阅读源代码的复杂度的一种方式。因为你可以将一些相关的代码放在一个区域(region)里面。但是,这不是随便就创建的新的方法或者新类的借口。其实Region并不能消除复杂度,它只是在你阅读代码的时候,隐藏了部分代码。你必须通过写出小巧,清晰,重点突出的方法和类,才能控制代码的复杂度。当你做到这些的时候,你甚至会发现region是不必要的。

发表评论
用户名: 匿名