8

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

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

那么如何拆分文件呢?你是否按照它们所服务的功能对你的方法进行分组?按类型(事件处理程序、私有/公共)?您拆分功能的大小限制是多少?

澄清一下,有问题的应用程序处理数据——所以它的界面是一个大网格,一切都围绕着网格。它有一些用于管理的对话框,但都是关于数据的。它如此之大的原因是有很多错误检查、事件处理以及将网格设置为主从网格,每行多三个网格(但是这些在主行上的负载扩展了)。我希望这有助于澄清我在说什么。

4

14 回答 14

19

我认为您的问题可以用您使用的术语来概括:“主 C# 文件”。

除非您的意思是 main(如在方法 main() 中),否则该概念没有位置。

如果您有一个包罗万象的实用程序类或其他常用方法,您应该将它们分解为类似的功能部分。

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

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

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

我尽量将我的方法控制在半屏或更少。(当它是我从头开始编写的代码时,它通常是 12 行或更少,但最近我一直在使用其他开发人员的现有代码并且不得不重构 100 行函数......)

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

编辑:

为了解决您关于函数的大小限制问题 - 对我来说,它与大小无关(尽管这是一个很好的问题指标),而更多的是关于只做一件事并保持每件事简单。

于 2009-03-03T22:42:34.620 回答
16

在经典著作《结构化编程》中,Dijkstra 曾写过一段题为:“论我们无能为力”。他的观点很简单。人类不是很聪明。我们不能同时在脑海中处理多个概念。

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

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

于 2009-03-07T17:29:54.260 回答
14

在很自然的地方拆分你的类型——但要注意那些做得太多的类型。大约 500 行(Java 或 C#)我很担心。在大约 1000 行时,我开始努力研究是否应该拆分类型......但有时它不能/不应该。

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

有时,单一类型有很多方法是有意义的——例如System.Linq.Enumerable,如果您可以将类型分解为逻辑组(在这种情况下Enumerable,通过聚合/集合操作/过滤进行分组),部分类在这种情况下会有所帮助等看起来很自然)。不过,根据我的经验,这种情况很少见。

于 2009-03-03T22:41:46.213 回答
5

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

编辑

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

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

于 2009-03-03T22:50:07.097 回答
4

不要按程序编写代码,您最终不会在一个文件中包含 4,200 行。

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

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

于 2009-03-03T22:44:24.350 回答
3

没有硬性规定,但普遍认为更多、更短的函数比单个大函数更好,更多更小的类优于 1 个大类。

大于 40 行左右的函数应该让你考虑如何分解它。尤其是嵌套循环,它令人困惑,而且通常很容易转换为具有良好描述性名称的函数调用。

当我觉得他们做的事情不止一件事时,我会分班,比如混合演示和逻辑。一个大类比一个大方法的问题要少,只要这个类做一件事。

我看到的风格指南中的共识是按访问权限对方法进行分组,构造函数和公共方法在顶部。任何一致的东西都很棒。

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

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

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

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

这很多,但开发品味、风格和清晰度是优秀开发人员和坏开发人员之间的主要区别。

于 2009-03-03T22:57:57.237 回答
2

每个班级都应该做一件小事,并且把它做好。你的班级是表格吗?那么它不应该有任何业务逻辑。

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

每个程序员都会经历阶段和级别。你意识到你当前的水平存在问题,你已经准备好接近下一个水平。

从您所说的情况来看,您当前的水平听起来像是“解决问题”,很可能使用程序代码,您需要开始更多地寻找新的方法来解决它。

我建议研究如何真正进行 OO 设计。您可能听说过许多没有意义的理论。它们不适用的原因是它们不适用于您当前的编程方式。

让我找到一个好帖子...看看这些开始:

我如何打破我的程序编码习惯

是否有任何规则

面向对象的最佳实践-继承-v-composition-v-interfaces

还有一些帖子会向您推荐好的 OO 设计书籍。“重构”一书可能是您可以开始的最佳起点之一。

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

祝你好运。

于 2009-03-03T23:25:43.347 回答
1

好吧,恐怕你手头的问题可能比加载时间慢。您将遇到紧密耦合的代码和可维护性/可读性问题。

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

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

此外,如前所述,您使用的术语:“主要 C# 文件”只是让人觉得您有一种非常程序化的心态。我的建议是停下来,退后一步,快速阅读以下一些主题:

祝您搜索顺利。

于 2009-03-03T22:48:30.253 回答
1

你可以寻找一些小的东西来改变,随着时间的推移慢慢改变。

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

  • 您是否使用任何#region 部分?#region 中相关方法的逻辑分组通常有助于将它们拆分为单独的类。

  • 类是一种形式吗?考虑将用户控件用于表单控件或表单控件组。

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

于 2009-03-04T01:07:01.170 回答
0

使用部分类。您基本上可以将单个类分解为多个文件。

于 2009-03-03T22:41:27.977 回答
0

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

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

有些班级必须很大。这不是糟糕的设计。它们只是执行繁重。

于 2009-03-03T23:23:09.280 回答
0

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

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

于 2009-03-04T02:46:06.173 回答
0

Visual Studio 2008 中的 Intellisense 解析器似乎比 2005 中的解析器快得多(我知道他们专门在这方面做了很多工作),所以尽管您绝对应该像其他人提到的那样考虑在某个时候拆分文件, Visual Studio 2008 可能会立即解决您的性能问题。我用它打开了一个 100K+ 行的 Linq to SQL 文件,没有太多问题。

于 2009-03-04T02:55:49.237 回答
0

拆分代码,以便每个类/文件/函数/等。只做一件事™。单一职责原则是将功能拆分为类的良好指南。

现在,我写的最大的类大约有 200 行,方法大多是 1-10 行。

于 2009-03-07T18:07:50.410 回答