公用事业班是邪恶的?

hvg*_*des 83 design-patterns software-design

我看到了这个帖子

如果"Utilities"类是邪恶的,我在哪里放置我的通用代码?

并且想到为什么实用类邪恶?

可以说我有一个很多类的域模型.我需要能够xml-ify实例.我是否在父级上创建了一个toXml方法?我是否制作了MyDomainXmlUtility.toXml助手类?这是业务需求跨越整个域模型的情况 - 它真的属于实例方法吗?如果应用程序的xml功能上有一堆辅助方法怎么办?

Tho*_*ens 111

实用类并不完全是邪恶的,但它们可能违反构成良好的面向对象设计的原则.在良好的面向对象设计中,大多数类应该代表单个事物及其所有属性和操作.如果你正在操作某个东西,那么该方法应该是该东西的成员.

但是,有时您可以使用实用程序类将多个方法组合在一起 - 例如,java.util.Collections该类提供了许多可以在任何Java Collection上使用的实用程序.这些并非特定于一种特定类型的Collection,而是实现可在任何Collection上使用的算法.

实际上,您需要做的是考虑您的设计并确定最适合放置方法的位置.通常,它是一个类内的操作.但是,有时,它确实是一个实用类.但是,当您使用实用程序类时,不要只是将随机方法放入其中,而是按用途和功能组织方法.

  • 如果该语言不提供除类之外的任何命名空间机制,则您别无选择,只能滥用命名空间可以执行的类.在C++中,您可以将与其他函数无关的独立函数放入命名空间.在Java中,您必须将其作为静态(类)成员放入类中. (7认同)

Ste*_*n C 53

我认为普遍的共识是效用类本身并不是邪恶的.你只需要明智地使用它们:

  • 将静态实用程序方法设计为通用和可重用的.确保他们是无国籍的; 即没有静态变量.

  • 如果您有许多实用程序方法,请将它们分区为类,以便开发人员可以轻松找到它们.

  • 不要使用实用程序类,其中域类中的静态或实例方法将是更好的解决方案.例如,考虑抽象基类中的方法或可实例化的帮助程序类是否是更好的解决方案.

  • 对于Java 8以上,接口中的"默认方法"可能是比实用程序类更好的选择.


另一种看待这个问题的方法是观察在引用的问题中,"如果实用类别是"邪恶的",那就是一个稻草人的论点.它像我一样问:

"如果猪可以飞,我应该带伞吗?"

在上面的问题中,我实际上并不是说猪可以飞......或者我同意他们可以飞的命题.

典型的"xyz是邪恶的"陈述是修辞手段,旨在通过提出一个极端的观点让你思考.他们很少(如果有的话)打算作为字面事实的陈述.


Ala*_*Dea 15

实用程序类是有问题的,因为它们无法将责任与支持它们的数据分组.

然而,它们非常有用,我将它们作为永久性结构或在更彻底的重构过程中作为垫脚石一直构建.

清洁代码的角度来看,实用程序类违反了单一责任和开放封闭原则.他们有很多改变的理由,而且设计不可扩展.它们实际上只应该在重构期间作为中间残余存在.

  • 实际上,现实世界中的大多数功能最好表现为静态,无状态,数学函数.Math.PI是一个应该变异的对象吗?我是否真的需要实例化一个实现IAbstractRealOperation的AbstractSineCalculator来获取数字的正弦值? (3认同)
  • 我认为这是一个实际问题,因为例如在Java中你不能创建任何不是类中方法的函数.在这样的语言中,"没有变量且只有静态方法的类"是一个代表实用函数命名空间的成语......当面对Java中的这样一个类时,它是恕我直言并且无意义地说一个类,即使使用`class`关键字.它像命名空间一样嘎嘎叫,它像命名空间一样走路 - 它就是一个...... (2认同)
  • 我很抱歉直言不讳,但"OOP系统中的无状态静态方法[...]哲学问题"极其错误.如果您可以避免使用状态,那就太棒了,因为这样可以很容易地编写正确的代码.当我必须编写`x.equals(y)`时,它是BROKEN因为1)这个实际上不应该修改任何状态的事实没有传达(我不能依赖它不知道实现)2)与"y"相比,我从未打算将"x"置于"偏好"或"行动"的位置3)我不想考虑"x"或"y"的"身份"但我只是对他们感兴趣值. (2认同)
  • @JoSo 我完全同意无状态和直接计算的价值。Naive OO 在哲学上反对这一点,我认为这使得它存在严重缺陷。它鼓励对不需要它的事物进行抽象(正如您所演示的),并且无法为实际计算提供有意义的抽象。然而,使用面向对象语言的平衡方法倾向于不变性和无状态性,因为它们促进了模块化和可维护性。 (2认同)
  • @AlainO'Dea:我意识到我误读了您的评论,因为它反对无状态功能。我为我的语气道歉——我目前正在参与我的第一个 Java 项目(在我 10 年编程的大部分时间都避免了 OOP 之后)并且被层层抽象的事物所掩盖,状态和含义不清楚。我只需要一些新鲜空气:-)。 (2认同)

Enn*_*oji 8

我想它开始变得邪恶了

1)它太大了(在这种情况下只将它们分成有意义的类别).
2)存在不应该是静态方法的方法

但只要不满足这些条件,我认为它们非常有用.


Mar*_*zak 7

经验法则

你可以从两个角度来看这个问题:

  • 整体*Util方法通常是糟糕的代码设计或懒惰的命名约定的建议。
  • 它是可重用的跨域无状态功能的合法设计解决方案。请注意,对于几乎所有常见问题,都有现有的解决方案。

示例 1. 正确使用util类/模块。外部库示例

假设您正在编写管理贷款和信用卡的应用程序。来自这些模块的数据通过 Web 服务以json格式公开。理论上,您可以手动将对象转换为将在 中的字符串json,但这会重新发明轮子。正确的解决方案是在两个模块中都包含用于将 java 对象转换为所需格式的外部库。(在示例图像中,我已经展示了gson

在此处输入图片说明


示例 2. 正确使用util类/模块。写你自己的,util没有借口给其他团队成员

作为一个用例,假设我们需要在应用程序的两个模块中执行一些计算,但它们都需要知道波兰何时有公共假期。理论上您可以在模块内进行这些计算,但最好将此功能提取到单独的模块中。

这是一个很小但很重要的细节。您编写的类/模块不是称为HolidayUtil,而是PolishHolidayCalculator. 从功能上讲,它是一个util类,但我们已设法避免使用通用词。

在此处输入图片说明


Lar*_*abe 5

实用程序类很糟糕,因为它们意味着您懒得想出更好的类名称:)

话虽这么说,我很懒。有时您只需要完成工作,而您的大脑一片空白……这就是“实用程序”类开始蔓延的时候。