1

尽管这是一个相当普遍的问题,但我正在努力寻找解决它的最佳方法(如果在这种情况下需要解决它)。

我继承了一个网站(ASP.NET,C#),其中一部分包含一个充满静态方法的类(老实说,这是一个非常大的类)。特别是一种方法是发送电子邮件。它有我能想到的所有可能的参数,而且效果很好。然而,该特定方法的内部结构管理和理解起来相当麻烦,因为所有东西都被塞进了内部——尤其是在大多数参数没有被使用的情况下。此外,由于这一方法的所有参数,处理错误有些困难。

当您想发送电子邮件时,实际拥有一个实例化的 EMail 类会更有意义吗?这对我来说“感觉”更合适,尽管我无法完全解释原因。在这种特殊情况下,您对前进的道路有何看法?一般情况如何?

谢谢。

4

5 回答 5

5

你所描述的听起来像是格言的一个例子,“你可以用任何语言写 FORTRAN。”

一个充满静态方法的大型类通常(并不总是)表明有人只是没有“获得” OOP,陷入了过程编程的思维方式,并试图扭曲语言来做他想做的事。

经验法则:如果任何方法(静态或实例)接受超过 5 个参数,这通常表明该方法试图一次做太多事情,并且是重构为一个或多个类的良好候选者.

此外,如果静态方法不是真正相关的,那么它们至少应该被拆分为实现相关功能的类。

我实际上想知道为什么你会有一个“发送电子邮件”方法,因为System.Net.Mail命名空间几乎可以处理所有情况,并且可以通过 app.config/web.config 文件进行配置,所以你不需要需要传递一个服务器名称或端口。这可能是一种“通知”方法 - 个别页面应该调用的东西,以便根据填充了各种值的模板发送几个“标准”消息之一,并自动添加某些页眉/页脚?如果是这样,那么对于这种类型的交互,有许多设计比您似乎继承的更容易使用。(即MailDefinition

更新:现在看到您的评论,这被用于异常处理,我认为最合适的解决方案是实际的异常处理程序。这方面有大量的资源。对于 ASP.NET WebForms,我实际上采用了 Jeff Atwood 多年前写的那个,将它移植到 C# 并进行了一些更改(比如忽略 404 错误)。上一个问题中有许多很好的链接。

这些天我的偏好只是将异常处理(以及随后的异常报告的电子邮件)视为日志记录的一个子集。 log4net有一个非常强大的SmtpAppender,您可以将其配置为仅用于“致命”错误(即未处理的异常 - 在您的处理程序中,您只需LogFatal拨打电话)。

重要的是,您无疑会从上面的 SO 链接和任何引用的链接中了解到,这里实际上有两个反模式——“杂项”静态类,以及捕获您不知道如何处理的异常处理。这在 .NET 中是一种不好的做法——在大多数情况下,您应该只捕获可以从中恢复的特定于应用程序的异常,并让所有其他异常冒泡,必要时安装全局异常处理程序。

于 2010-01-08T18:42:14.200 回答
4

以下是关于何时使用静态类型的 Microsoft 指南

我个人想补充几点:

  • 必须使用静态类型来编写扩展方法。
  • 静态类型会使单元测试变得困难,因为它们难以/不可能模拟。
  • 静态类型强制执行不变性和引用透明的函数,这可能是一个很好的设计。因此,将它们用于设计为不可变且没有外部依赖关系的事物。例如,System.Math
  • 有些人认为(例如)单例模式是个坏主意。无论如何,将静态类型视为单例是错误的。它们比这更广泛。

这种特殊情况有副作用(发送电子邮件)并且似乎不需要扩展方法。所以它不适合我认为静态类型的有用案例。另一方面,使用对象将允许模拟电子邮件,这将有助于单元测试。所以我认为你说静态类型在这里不合适是正确的。

于 2010-01-08T18:17:53.487 回答
3

哦,天哪,是的。

这听起来像是一个移植的旧经典 ASP 应用程序。

它违反了单一责任原则。如果您可以重构该类。对该函数使用重载。

于 2010-01-08T18:13:07.880 回答
2

这是Utils 反模式的一个例子。

根据它们的职责将这些方法分开总是一个好主意。创建一个电子邮件类绝对是一个好主意™。它会给你一个更好的界面来使用,它允许你在测试中模拟出电子邮件。

于 2010-01-08T18:40:19.040 回答
0

请参阅The Little Manual of API Design,其中描述了具有最少构造函数和大量 getter/setter 的类的好处,而不是使用具有许多参数的构造函数/方法的替代方法。

由于您提到的方法的大多数参数都没有使用,因此更好的方法是使用简单的构造函数,该构造函数假定内部变量的合理默认设置。拥有 setter 方法后,您可以设置需要非默认值的少数参数(并且仅是那些参数)。

于 2010-01-08T18:59:51.623 回答