公用事业班..好还是坏?

时间:2009-11-04 01:48:05

标签: c# class static utility

我一直在阅读通过在代码中使用静态类/单例来创建依赖项,这是一种糟糕的形式,并且会产生问题,即。紧耦合和单元测试。

我遇到一种情况,我有一组url解析方法没有与之关联的状态,并且仅使用方法的输入参数执行操作。我相信你熟悉这种方法。

过去我会继续创建一个类并添加这些方法并直接从我的代码中调用它们,例如。

UrlParser.ParseUrl(url);

但是等一下,就是将依赖引入另一个类。我不确定这些“实用”类是否是坏的,因为它们是无状态的,这最小化了所述静态类和单例的一些问题。有人可以澄清这个吗?

我是否应该将方法移动到调用类,即只有调用类才会使用该方法。这可能违反了“单一责任原则”。

8 个答案:

答案 0 :(得分:7)

从理论设计的角度来看,我觉得在可能的情况下应该避免使用效用类。它们基本上与静态类没什么不同(虽然稍微好一点,因为它们没有状态)。

但是,从实际的角度来看,我确实创建了这些,并鼓励他们在适当的时候使用 。试图避免实用程序类通常很麻烦,并导致代码维护较少。但是,我确实鼓励我的开发人员在可能的情况下在公共API中避免这些。

例如,在您的情况下,我觉得UrlParser.ParseUrl(...)可能更好地作为一个类来处理。查看BCL中的System.Uri - 这为统一资源标识符提供了一个干净,易于使用的界面,该界面运行良好,并保持实际状态。我更喜欢这种方法,用于对字符串起作用的实用程序方法,并强制用户传递字符串,记得验证它等等。

答案 1 :(得分:2)

实用程序类是可以的.....只要它们不违反设计原则。在使用核心框架类时,请愉快地使用它们。

这些类应该有良好的命名和逻辑。实际上,它们不是那么“实用”,而是本土课程不提供的新兴框架的一部分。

使用诸如扩展方法之类的东西也很有用,可以将功能与“正确”类对齐。但是,它们可能会引起一些混淆,因为扩展程序没有与它们通常扩展的类一起打包,这不是理想的,但仍然可以非常有用并产生更清晰的代码。

答案 2 :(得分:2)

你总是可以创建一个接口,并使用依赖注入与实现该接口而不是静态类的类的实例。

问题在于,真的值得付出努力吗?在某些系统中,答案是肯定的,但在其他系统中,特别是较小的答案,答案可能是否定的。

答案 3 :(得分:1)

我真的,真的试图避开它们,但是我们在开玩笑......它们会蔓延到每个系统中。然而,在给出的示例中,我将使用URL对象,然后该URL对象将公开URL的各种属性(协议,域,路径和查询字符串参数)。 几乎每次我想创建一个静态实用程序类时,我都可以通过创建一个执行此类工作的对象来获得更多价值。

以类似的方式,我创建了许多自定义控件,这些控件已经内置了百分比,货币,电话号码等内容的验证。在此之前,我有一个Parser实用程序类,它具有所有这些规则,但它使得在已经知道基本规则的页面上删除控件(因此只需要业务逻辑)就更清晰了em>要添加的验证。)

我仍保留解析器实用程序类,并且这些控件隐藏该静态类,但广泛使用它(将所有解析保存在一个易于查找的位置)。在这方面,我认为使用实用程序类是可以接受的,因为它允许我应用“不要重复自己”,而我从控件或其他使用实用程序的对象获得实例类的好处。

答案 4 :(得分:1)

我同意这里的一些其他回应,它是经典的单例,它维护一个有状态对象的单个实例,这个实例是要避免的,而不一定是没有状态恶意的实用类。我也同意里德的意见,如果可能的话,将这些实用程序方法放在一个有意义的类中,并且逻辑上怀疑这些方法会驻留在哪里。我想补充一点,通常这些静态实用程序方法可能是扩展方法的良好候选者。

答案 5 :(得分:1)

这实际上取决于背景以及我们如何使用它。

实用程序类本身也不错。但是,如果我们以糟糕的方式使用它会变得很糟糕。每个设计模式(特别是Singleton模式)都可以很容易地变成反模式,对于Utility类也是如此。

在软件设计中,我们需要在灵活性与安全性之间取得平衡。简单。如果我们要创建一个只负责字符串操作的StringUtils:

  • 是否违反了SRP(单一责任原则)? - >不,是开发人员对违反SRP的实用程序类承担了太多责任。
  • "它不能使用DI框架注入" - > StringUtils的实现会有所不同吗?我们要在运行时切换它的实现吗?我们要嘲笑它吗?当然不是。

=>公用事业课程也不错。它是开发人员和他们的对象。故障使它变坏。

这一切都取决于具体情况。如果您要创建一个仅包含单一职责的实用程序类,并且仅在模块或层中私有使用。然后你仍然很擅长。

答案 6 :(得分:0)

只要你设计好它们就很好(也就是说,你不必不时改变它们的签名)。

这些实用程序方法通常不会改变,因为它们只做一件事。当您想要将更复杂的对象紧密到另一个时,问题就来了。如果其中一个需要更换或更换,如果你让它们高度耦合则更难。

由于这些实用方法不会改变,我常说这不是什么大问题。

我认为如果一遍又一遍地复制/粘贴相同的实用方法,那将是最糟糕的。

Joshua Bloch撰写的这段视频How to design a good API and why it matters解释了设计API时要考虑的几个概念(即您的实用程序库)。虽然他是公认的Java架构师,但内容适用于所有编程语言。

答案 7 :(得分:0)

谨慎使用它们,您希望尽可能多地将逻辑放入类中,这样它们就不会成为数据容器。

但是,与此同时,你无法真正避免使用它们,有时它们是必需的。

在这种情况下,我认为没关系。

仅供我们使用system.web.httputility类,其中包含许多常用的http实用程序,您可能会觉得它们很有用。