编码指南:如何拆分大型源文件?

时间:2009-03-03 22:38:31

标签: c# visual-studio oop class-design coding-style

我正在处理的项目刚刚在主C#文件中命中了4200行,这导致IntelliSense需要几秒钟(有时最多6个左右)才能响应,在此期间Visual Studio会锁定。我想知道其他人如何分割他们的文件以及是否达成共识。

我试图寻找一些指南并找到Google's C++ guide,但我看不到任何关于语义的信息,例如函数大小和文件大小;也许它就在那里 - 我有一段时间没有看过它。

那么你如何拆分你的文件?您是按照所服务的功能对方法进行分组吗?按类型(事件处理程序,私人/公共)?你在什么尺寸限制下拆分功能?

为了澄清,有问题的应用程序处理数据 - 所以它的界面是一个大网格,一切都围绕网格。它有一些用于管理的对话框表单,但它都是关于数据的。它之所以如此之大,是因为存在大量错误检查,事件处理以及网格设置为主细节,每行有三个网格(但主扩展上的这些加载)。我希望这有助于澄清我的目标。

14 个答案:

答案 0 :(得分:19)

我认为您的问题总结为您使用的术语:“主C#文件”。

除非你的意思是main(如方法main()),否则就没有这个概念的地方。

如果你有一个catch-all实用程序类或其他常用方法,你应该将它们分解为类似的功能部分。

通常我的文件只是一对一的类映射。

有时,非常相关的类在同一个文件中。

如果您的文件太大,则表明您的课程太大而且过于笼统。

我尝试将我的方法保持在半个屏幕或更少。 (当我从头开始编写代码时,它通常是12行或更少,但最近我一直在使用其他开发人员的现有代码,并且必须重构100行函数...)

有时它是一个屏幕,但是它变得非常大。

编辑:

要解决有关函数的大小限制问题 - 对我而言,它不是关于大小(尽管这是一个很好的问题指示器),而是关于只做一件事并保持每一个简单。

答案 1 :(得分:15)

在经典着作“Structured Programming”中,Dijkstra曾写过一篇题为“我们无法做多少”的章节。他的观点很简单。人类不是很聪明。我们不能同时在脑海中处理多个概念。

保持你的课程和方法很小很重要。当一个方法超过十几行时,它应该分开。当一个类超过几百行时,它应该被分开。这是保持代码组织良好和易于管理的唯一方法。我已经编程了近40年,随着每一年的过去,我意识到编写软件时“小”这个词的重要性。

至于如何你这样做,这是一个非常大的主题,已经写了很多次。一般来说,它都是关于依赖管理,信息隐藏和面向对象的设计。这是一个阅读清单。

答案 2 :(得分:14)

将你的类型拆分成自然分割的类型 - 但要注意那些做得太多的类型。在大约500行(Java或C#)我很担心。在大约1000行,我开始认真考虑是否应该拆分类型......但有时它不能/不应该。

至于方法:当我无法一次在屏幕上看到整个方法时,我不喜欢它。显然这取决于显示器的大小等,但这是一个合理的经验法则。我更喜欢它们更短。同样,也有例外 - 某些逻辑很难解开,特别是如果有很多局部变量本身并不希望被封装在一起。

有时单个类型有一个 lot 方法是有意义的 - 比如System.Linq.Enumerable但是在这种情况下,如果你可以将类型分解为逻辑,则部分类可以提供帮助组(在Enumerable的情况下,通过聚合/设置操作/过滤等进行分组似乎很自然)。根据我的经验,这种情况很少见。

答案 3 :(得分:5)

Martin Fowler的书Refactoring我认为这为你提供了一个很好的起点。它指示如何识别“代码味道”以及如何重构代码以修复这些“气味”。自然结果(虽然它不是主要目标)是你最终得到更小的可维护类。

修改

根据您的编辑,我一直坚持认为后端代码的良好编码实践在表示层中是相同的。 UI重构要考虑的一些非常有用的模式是命令,策略,规范和状态。

简而言之,您的视图应该只包含代码来处理事件和分配值。所有逻辑都应该分成另一个类。一旦你这样做,你会发现在你可以重构的地方变得更加明显。网格使得 little 更加困难,因为它们使得在表示逻辑和视图之间拆分表示状态变得太容易了,但是通过一些工作,你可以放入间接以最小化由此引起的痛苦

答案 4 :(得分:4)

不要在程序上进行编码,并且在一个文件中最终不会有4,200行。

在C#中,遵循一些SOLID面向对象的设计原则是个好主意。每个班级都应该只有一个改变的理由。主要方法应该只是启动应用程序的起始点(并配置您的依赖注入容器,如果您使用的是StructureMap)。

我通常没有超过200行代码的文件,如果他们不到100,我更喜欢它们。

答案 5 :(得分:3)

没有严格的规则,但人们普遍认为更多,更短的功能比单个大功能更好,更小的类比1大类更好。

大于40行左右的功能应该让你考虑如何分解它。特别是看看嵌套循环,这些循环很容易混淆,并且通常很容易转换为具有良好描述性名称的函数调用。

当我觉得他们做的不仅仅是一件事,比如混合演示和逻辑时,我就分手了。只要班级做了一件事,一个大班级就不是一个大问题而是一个大问题。

我见过的样式指南中的共识是通过访问对方法进行分组,顶部是构造函数和公共方法。任何一致都很棒。

您应该阅读C#样式和重构,以真正了解您正在解决的问题。

Refactoring是一本优秀的书,其中包含重写代码的提示,以便保留行为但代码更清晰,更易于使用。

Elements of C# Style是一个很好的死树C#风格指南,这个blog post有许多指向优秀在线风格指南的链接。

最后,请考虑使用FxCopStyleCop。这些对您提出的问题没有帮助,但可以检测代码的其他风格问题。因为你已经将脚趾浸入水中,所以你也可以跳进去。

这很多,但是开发品味,风格和清晰度是优秀开发者和不良开发者之间的主要区别。

答案 6 :(得分:2)

每个班级都应该做一件小事,做得好。你的班级是一个表格吗?然后它不应该有任何业务逻辑。

它是代表一个单一的概念,如用户还是国家?然后它不应该有任何绘图,加载/保存等...

每个程序员都要经历各个阶段和关卡。您认识到当前级别的问题,并且您已准备好接近下一级。

从你的说法来看,听起来你现在的水平是“解决问题”,很可能是使用程序代码,你需要开始更多地寻找接近它的新方法。

我建议如何真正做OO设计。有许多理论你可能听说过没有意义。他们不这样做的原因是他们不适用于你目前的编程方式。

Lemme找到一个好帖子......看看这些开头:

how-do-i-break-my-procedural-coding-habits

are-there-any-rules-for-oop

object-oriented-best-practices-inheritance-v-composition-v-interfaces

还有一些帖子会将您推荐给优秀的OO设计书籍。 “重构”一书可能是你可以开始的最好的地方之一。

你现在处于一个好点,但你不会相信你必须走多远。我希望你对它感到兴奋,因为在不久的将来,这些东西中的一些是你将拥有的最佳编程“学习经历”。

祝你好运。

答案 7 :(得分:1)

好吧,我不敢说你手头上的问题比缓慢的加载时间要大。您将遇到紧密耦合的代码和可维护性/可读性问题。

有很好的理由将类文件拆分成较小的文件(同样很好的理由将文件移动到不同的项目/程序集)。

想想你班级应该达到的目的是什么。每个文件应该只有一个目的。如果它的目标过于笼统,例如“包含购物篮逻辑”,那么你就走错了路。

另外,如上所述,您使用的术语:“主C#文件”只是说明您有一个非常程序化的思维模式。我的建议是停下来,退后一步,快速阅读以下一些主题:

  • 一般OOP原则
  • 域驱动设计
  • 单元测试
  • IoC容器

祝你好运。

答案 8 :(得分:1)

你可以随时查找要改变的小东西,然后慢慢改变。

  • 该类中仅使用了所有方法吗?寻找支持方法,例如验证,字符串操作,可以移出到helper / util类中。

  • 您使用的是#region部分吗? #region中相关方法的逻辑分组通常可以分成不同的类。

  • 班级是表格吗?考虑对表单控件或表单控件组使用用户控件。

由于许多开发人员在不考虑整体设计的情况下进行快速修复/新功能,有时大型课程会随着时间的推移而发展。重新审视其他人在此提供的一些设计理论链接,并考虑持续支持以执行这些,例如代码审查和团队研讨会,以审查设计。

答案 9 :(得分:0)

使用部分课程。您基本上可以将一个类分成多个文件。

答案 10 :(得分:0)

如果一个类中有代码区域,一个简单的方法是使用partial关键字并将该类的定义分解到该文件中。我通常会为大班做这件事。

我使用的约定是拥有ClassName_RegionName.cs。例如,如果我想打破一个管理数据库连接模式的类,并且我调用了类DatabaseConnection,我将为主类创建一个名为DatabaseConnection.cs的文件,然后为模式功能创建一个DatabaseConnection_Schema.cs文件。 / p>

有些课程必须很大。这不错设计;他们只是执行力很大。

答案 11 :(得分:0)

也许OP可以回应:您的项目是否使用面向对象编程?您使用“文件”一词的事实表明它不是。

在您理解面向对象之前,没有希望以任何重要方式改进您的代码。你最好不要拆分文件,等到它变得无法忍受缓慢和错误,然后不再支持它,去学习OO。

答案 12 :(得分:0)

Visual Studio 2008中的Intellisense解析器似乎比2005年快得多(我知道他们在这个领域特别做了很多工作),所以尽管你应该在某些时候考虑将文件拆分为其他人已经提到,Visual Studio 2008可能会解决您的即时性能问题。我已经用它来打开100K +行Linq到SQL文件而没有太多问题。

答案 13 :(得分:0)

拆分代码,使每个类/文件/函数/等。只做One Thing™。 The Single Responsibility Principle是将功能划分为类的好指南。

如今,我写的最大的课程大约有200行,而且这些方法大多是1-10行。