是否有充分的理由在 Program.cs/main 中编写代码而不是使用类? [关闭]

Posted

技术标签:

【中文标题】是否有充分的理由在 Program.cs/main 中编写代码而不是使用类? [关闭]【英文标题】:Is there a good reason to write code in Program.cs/main as opposed to using classes? [closed] 【发布时间】:2012-10-05 23:08:20 【问题描述】:

我正在开发一个相当大的应用程序和我的技术主管,但我在某些事情上意见不一致。

其中之一是关于控制台应用程序。这些应用程序正在从 shell 脚本移植到 C#。其中一些脚本相当大(转换后的代码为 300-400 行),并执行 I/O、电子邮件和数据库访问等操作。

我为这些脚本中的每一个创建了一个类。每个类都有一个 Run 方法,该方法调用其中的任何方法/操作。在 Program.cs/main 中,我创建了一个该类的对象并调用 Run。 Program.cs 包含 4-5 行代码。干净简单。

我的技术主管想要摆脱脚本类,只将所有内容都放在 program.cs 的 main 方法中。他的理由是它的方式太混乱了。

这样做感觉很尴尬,因为类不再可重用/可打包到类库中,而不必摆弄 main 方法。

单元测试似乎不受影响,因为您可以实例化 Program.cs 本身,但同样......这感觉很笨拙。以我没有看到的方式这样做有什么好处吗?我的方式有什么好处吗?在您的 main 方法中处理大型应用程序和内容时,是否有一般做法?

感谢您的宝贵时间。

【问题讨论】:

他错了。 这个问题更适合程序员,IMO,因此投票结束。这真的完全取决于你的班级做什么,但总的来说,单一职责原则是一个很好的经验法则 - en.wikipedia.org/wiki/Single_responsibility_principle 我不确定“每个类都有一个调用其中的任何方法/操作的 Run 方法”是否足以改进,因为这看起来好像有人可以在不理解什么的情况下阅读 main程序确实如此。 这个问题不是题外话,可能不应该被关闭。诸如“在什么情况下您在代码中_____”之类的问题完全符合 SO 的适当问题指南。即使正确答案是“从不”。 @tylerl - 更适合programmers.stackexchange.com,仅仅因为这里的程序员达成共识并不意味着这个问题不是意见/讨论驱动的。我投票“离题”是因为我认为它应该是针对程序员的,如果我们没有这个选项,我会投票“不具建设性”。 【参考方案1】:

您知道控制台应用程序的入口点是可配置的,对吧?

我的首选方法是:

class MeaningfullyNamedProgram  
    public static void Main(string[] args) 
        var program = new MeaningfullyNamedProgram(args);
        program.Run();
    

    public MeaningfullyNamedProgram(string[] args)  
    

    public Run() 
        // well structured, broken-out code follows 
    

将项目的入口点指向 MeaningfullyNamedProgram.Main

注意:我将把它作为练习留给读者,但您可以使用泛型为此创建一个基类,并为自己节省一些输入。

【讨论】:

【参考方案2】:

老实说,我认为您是在为自己创作作品。我无法从您描述中的细节中看出 - 但如果 shell 脚本一直在工作,为什么要在显然不需要结构的地方构建它?

您说模块化和重新打包到外部库是您需要做的事情 - 我会反驳“为什么?” (这就是我所说的额外工作)。

如果您在单个文件中创建一组简单的方法 - 那就是一个文件!根据定义,它会更容易处理多个项目等。

也就是说,除非有更多细节,否则很难知道我们在说什么。如果它是“发送夜间报告并向这些人发送电子邮件” - 是的,这不需要类库和大量模块化。运行一个方法,就完成了。

【讨论】:

我猜这就是我提出问题的原因:)。所有的脚本都已经完成,单元测试已经写好了。它必须回去这样做,这让我感到困惑,因为我看不出一个明确的原因/好处。从头开始他的方式对我来说肯定会更容易......相信我。但是现在,真的有意义吗?【参考方案3】:

这样做感觉很尴尬,因为类不再可重用/可打包到类库中,而不必摆弄 main 方法。

必须是那样的。

例如,您的每个脚本仍然可以具有相同的结构,但有一个private static void Main(string[] args) 方法。 (如果您愿意,它可以是非私人的 - 这完全取决于您的需求。)

这样它是独立的(可以编译为单个输入到单个输出然后运行),偶尔可以很方便,但也可以用作类库的一部分。毕竟,Main 方法的存在绝不阻止该类被其他类使用。

不清楚您是否有 一个 Program.cs 文件或每个脚本一个。如果每个脚本都有一个,每个脚本只有 4-5 行,那似乎有点毫无意义。

现在这当然不是我通常会如何构建大型应用程序的方式 - 但如果关键是要有几个“脚本”,每个 可以 独立运行,然后给每个类Main 方法似乎还不错。

事实上,我经常为 demo 做的就是在一个项目中拥有几个带有Main 方法的类,然后有一个单独的入口点(Program.cs) 中,它使用反射来查找所有其他人,然后允许用户/演示者选择运行哪一个。

如果您的所有代码都放在一个类中是有意义的,那么拥有一个微小的额外入口方法似乎不是什么问题。如果实际上是单个类的代码过多的情况不管入口点在哪里,那是另一回事。 (因此,如果您坚持使用单个 ScriptClass,而实际上您应该将不同的任务分配给不同的类,那也很糟糕。)同样,如果他真的坚持所有代码都在一个 方法中 em>,这绝对是测试和可维护性的问题。

我建议你暂时把切入点的分歧放在一边:找出最简洁的方法来构造所有关于代码的else,然后Main 方法是否真的无关紧要进入Program.cs 或其他班级。

【讨论】:

每个脚本都有一个 Program.cs 文件,因为每个脚本都是一个控制台应用程序。我拥有它的方式,我在 program.cs 中所做的只是在 main 内部调用 ScriptClass.Run() ......以及一些错误处理。这就是为什么它只有 4-5 行代码的原因。反过来说,每个 program.cs 将有 300 多行代码(因为它将获取 ScriptClass 的内容并将其放入 program.cs)。对不起,如果我不清楚。 @JohnnySaxx:查看我编辑的答案 - 我真的不认为入口点的位置值得担心。如果您的 ScriptClass.Run 方法仍然是一个巨大的 300 行方法,那么将 Main 方法移动到一个单独的文件中对您没有任何好处。同样,如果您能够重构 ScriptClass 以将其分解为可测试的位,那么 留下 Main 方法不会对您造成任何伤害。听起来每个脚本 project 无论你做什么都会有相同数量的代码(300 多行)——据我所知,你还没有提到任何可重用的东西跨度> ScriptClass 包含其他方法。所以在 Run 里面我有: Run method1(), method2()...methodn(); method1-n 仅对我测试每个项目的单元测试项目可见。 Run 是唯一公开暴露在类之外的方法。另外,感谢有关 main 的提示。本质上 ScriptClass 将 Program.cs 替换为入口类,此时不需要后者。在那种情况下,真的有任何理由为什么一个比另一个更好吗?你不是在做同样的事情吗? @JohnnySaxx:是的——这些方法在逻辑上都属于同一个类吗?如果是这样,那很好。只有一个文件的好处就是——你没有一个额外的文件挂在周围,没有任何实际的好处。这不是什么大问题,但在同一类型中包含Main 也不是什么大问题。【参考方案4】:

如果功能可以通过控制台程序以外的其他方式使用,当然您应该将它们保存在模型良好的类库中。考虑到关注点最初是分开的,通过使用封装的功能来处理命令行参数来节省几行代码是没有意义的。恕我直言,也许您的技术主管应该为您找到更有成效的任务。

【讨论】:

【参考方案5】:

您的技术主管错了。您提出的方法要合理得多——它允许轻松合并不同的脚本。每个脚本都有自己的 Main 方法可能会变得笨拙,特别是如果您计划拥有一个可以同时运行多个这些方法的应用程序。

【讨论】:

【参考方案6】:

嗯,他的方式在概念上更简单,因为它是在子程序被发明之前编写程序的方式......

您的方式更好:它支持可重用性,并且更易于修改和调试。

对于他的方式,我能想到的唯一其他理由是,如果你按照自己的方式做事比按照他的方式做事要花更长的时间。但这是他短期思考的一个例子。您的方式将更好地经受住时间的考验。

【讨论】:

【参考方案7】:

将逻辑拆分为一个单独的类(或多个类)是可行的方法。把它放在一个地方违反了 SOLID 和 DRY 设计的原则。您的方法绝对是正确的。

您的课程越专注于单一角色,您的维护和测试工作就越轻松。

【讨论】:

【参考方案8】:

您的技术主管需要好好谈谈!将所有内容都放入 Program.cs 不是前进的方向。

【讨论】:

以上是关于是否有充分的理由在 Program.cs/main 中编写代码而不是使用类? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

是否有充分的理由为 DialogFragments 使用子片段管理器?

是否有充分的理由在 C 中始终将定义括在括号中?

是否有充分的理由在单平台系统上使用 .proto 文件?

是否有充分的理由在打字稿项目中将编译器选项“声明”设置为 true

是否有充分的理由避免在 JS 中没有最终表达式的 FOR 循环?

是否有任何陷阱或充分的理由不使用 autosproc 进行存储过程调用?