有一个Misc Utilities课程是不好的形式?

时间:2010-08-20 14:02:41

标签: oop

我们公司保留一个MiscUtilities类,它只包含公共静态方法,这些方法通常执行不相关的任务,例如将日期从String转换为Calendar以及将ArrayLists写入文件。我们在其他类中引用它并发现它非常方便。但是,我已经看到了那种公用事业类嘲笑TheDailyWTF。我只是想知道这类课程是否有任何实际缺点,以及替代方案是什么。

14 个答案:

答案 0 :(得分:12)

我将引用Java社区中的权威来源,以及来自2个非常有信誉的第三方库的示例,而不是发表个人意见。

来自 Effective Java 2nd Edition的引用,第4项:使用私有构造函数强制执行非实例化

  

有时候您会想要编写一个只包含static种方法和static字段的类。 这些类已经获得了不好的声誉,因为有些人滥用它们以避免在对象方面进行思考,但它们确实具有有效用途。它们可用于以java.lang.Mathjava.util.Arrays的方式对原始值或数组的相关方法进行分组。它们还可以用于static方法,包括工厂方法,用于实现特定接口的对象,方式为java.util.Collections。最后,它们可用于对final类上的方法进行分组,而不是扩展类。

Java库有很多这样的实用程序类的例子。


简短摘要

  • 喜欢优秀的OOP设计,始终
  • static实用程序类对 group 相关方法的有效用途:
    • 原始(因为它们不是对象)
    • 接口(因为它们不能有任何具体的接口)
    • final个类(因为它们不可扩展)
  • 总是喜欢良好的组织
    • SomeType 实用程序方法添加到 SomeType Utils {{ 1}} SomeType
    • 避免使用包含不同类型/概念上的各种不相关任务的单个大型实用程序类

答案 1 :(得分:4)

方便,最有可能。

很有可能成长为一个可怕的,难以维持的瑞士 - 陆军 - 火箭 - 电锯和地板抛光机。

我建议将各种任务分成不同的类,除了“不适合其他任何地方”之外还有一些逻辑分组。

这里的风险是,班级成为一个混乱的混乱,没有人完全理解,没有人敢触摸 - 或替换。如果您认为在您的情况下这是可接受的风险和/或可以避免,那么没有什么能够阻止您使用它。

答案 2 :(得分:3)

我从未成为MiscUtilities课程的粉丝。我最大的问题是我永远不知道它里面有什么。在杂项下提交的任何内容都是不可发现的。相反,我更喜欢使用一个常见的dll,我可以导入到我的项目中,这些dll包含用于不同目的的命名良好的分隔类。差异是微妙的,但我发现它让我的生活更轻松。

答案 3 :(得分:2)

对于支持函数的语言,这种类无可否认是不好的形式。

对于那些没有的语言,这种类不是,并且可能优于使用随机实用方法扩展其他类。静态实用程序方法因为它们在其他类中,只能使用它们处理的对象的公共接口,这降低了某些类型的bug的可能性。而且这种方法还避免了随意抓取任何人在当时发现有用的东西时污染公共接口。

当然,涉及一定数量的个人风格。我并不是那些在阳光下提供一切的课程的忠实信徒(即使C ++的std::string对于我的品味而言过于夸张)并倾向于将辅助功能作为单独的功能。使类的维护更容易,强制公共接口有用和高效,并且通过鸭子类型样式机制,外部函数可以在各种类型中使用,而不必复制源文本或共享基类等。 (C ++标准库中经常使用的算法很好地证明了这一点,不完美和冗长。)

那就是说,我和许多抱怨过不知道如何将自己解释为文件名的字符串,或者将自己分成单词,或者你有什么,等等。 (我选择字符串是因为它们似乎是实用功能的主要目标......)我碰巧认为有类似大型课程的看不见的维护和可靠性成本,除了有一个名义上简单的类的丑陋之外这实际上是一个无关紧要的混乱的不合逻辑的混乱,其粗糙的手指最终将自己戳到每一个角落 - 因为你的自我标记字符串需要某种容器来放入令牌,对吧?! - 但这是一种平衡行为,即使我的措辞表明它比那更清晰。

我不是“OO教条”概念的忠实信徒,但也许偏执狂可能会在这里看到它。没有充分的理由将所有功能都附加到特定的类,以及为什么它不应该附加的许多好的理由。但是有些语言仍然不允许创建函数,它们不会消除对它们的需求,并且通过创建除静态方法之外的任何类来强制人们解决限制。这在我的脑海里,而不是以任何好的方式,都超出了阶级概念的含义。

因此,这是违反这种做法的一个很好的理由,但除非语言改变以适应人们需要做的事情,否则它是徒劳的。语言并非没有功能,除非他们的设计师有斧头,或者有技术原因,所以我认为在任何一种情况下都不太可能发生变化。

我认为执行摘要是:否。

答案 4 :(得分:1)

好吧,糟糕的实用程序类在TheDailyWTF上被嘲笑:)

为其他静态业务功能提供通用实用程序类确实没什么问题。我的意思是,您可以尝试将其全部用于更加面向对象的方法,但是在业务上花费多少时间和精力以及可维护性的权衡取舍?如果后者超过前者,那就去吧。

根据语言等,您可能采取的一种方法是将某些逻辑转移到现有对象的扩展上。例如,使用尝试将字符串解析为DateTime的方法扩展String类(在C#中思考)。内部扩展库只是通过您的企业自己的小DSL来增强语言。

答案 5 :(得分:1)

我工作的公司在其存储库中有类似的类。就个人而言,我觉得这很烦人,因为你必须真正与班级亲密,才能知道它对什么有用。因此,我发现自己正在重写本课程已经涵盖的方法!双重烦恼,因为我现在浪费了我的时间。

我更希望采用更加面向对象的方法来实现可扩展性。确实有一个Utilities类,但在其中放置了其他扩展到特定功能的类。与Utilities.XML,Utilities.DataFunctions,Utilities.WhateverYouWant一样。这样你就可以扩展并最终获得你的20个函数MiscUtilities类并将其转换为500个函数类库。

这样的类库可以被任何人使用,并由任何人(具有特权)以逻辑组织的方式添加。

答案 6 :(得分:1)

我认为这类课程的错误在于它违反Separation of concerns原则。我通常创建多个“Helpers”类来包含广泛使用的公共静态方法,例如ArrayHelpers将ArrayLists写入文件,DatesHelper将日期从String转换为Calendar。 此外,如果类确实包含复杂的方法,最好尝试使用更多面向对象的tecnique来重构它们。 您始终可以从“助手”类切换到使用各种OO模式,将旧的静态方法保留为Facade。 每当你能够做到这一点时,你会发现很多好处。

答案 7 :(得分:1)

我为每个项目保留一个单独的misc类,并根据需要从其他项目中复制/粘贴代码。也许不是最好的方法,但我更愿意避免跨项目依赖。

我的助手类中的事情示例:

  1. hex2,hex4和hex8(接受整数参数,除了具有整数和uinteger变量的hex8;所有版本忽略高阶位)
  2. byt(将8个lsb的参数转换为一个字节)
  3. getSI,getUI,getSL,getUL(每个都接受一个字节数组和一个偏移量,并返回小端符号字,无符号字,带符号的32位字或无符号32位字)抵消
  4. putSI,putUI,putSL,putUL(采用字节数组,偏移量和值以little-endian格式放置)
  5. hexArr(将字节数组或其中的一部分转换为十六进制字符串)
  6. hexToArr(将十六进制字符串转换为字节数组)
  7. Zap(T作为iDisposable)(采用byref iDisposable;如果不是Nothing,则将其处理并将其设置为Nothing)

其中许多仅在摆弄二进制数据时才有用,但它们都不是特定于域的。也许前六个可能会进入BinaryHelpers模块,但我不确定Zap应该去哪里,而不是在misc实用程序类中。

答案 8 :(得分:1)

实用程序类本身并不坏。它们有时可以(错误地)使用,但它们确实有它们的位置。如果您拥有自己的类型的实用程序方法,请考虑将静态方法移动到适当的类型。或者创建扩展方法。

尽量避免单一的实用程序类 - 它们可能是静态方法,但它们的内聚性很差。将大量不相关的函数分解为较小的相关功能组,就像您的“普通”类一样。将它们命名为* Helper或* Utils,或者您喜欢的任何名称。但要保持一致,并将它们组合在一起,也许在项目的文件夹中。

当按照描述分解实用程序类时,您可以创建用于处理特定类型的方法 - 基元或类,例如数组,字符串,日期和时间等。不可否认,这些不属于任何其他地方,因此可以使用实用程序类。

答案 9 :(得分:0)

就个人而言,我经常会找到这样一个方便的课程 - 即使只是在短期内。也就是说,我尽量不在项目之间分享它们。我不会保留一个全局版本,但是要为每个项目编写一个特定的版本 - 否则你会加入可能导致安全性或体系结构问题的死重。

答案 10 :(得分:0)

我为个人项目所做的是保留一个misc库,但不是在我的项目中添加引用,而是将相关的代码段粘贴到相关位置。它在技术上是重复的,但不是在单一的解决方案中,这是重要的事情。但是我认为这不会在更大范围内发挥作用,而且太混乱了。

答案 11 :(得分:0)

我一般对它们没有问题,但是,就像所有事情一样,它们可能被滥用:

  • 它们变得非常庞大,因此大多数使用该类的问题都没有使用99%的功能。
  • 它们变得非常庞大,因此任何程序仍未使用90%的功能。
  • 通常它们是特定于一个域的功能的倾倒场。它们应该仅仅通过该域中的程序来减少类似的类使用。通常,这些功能最好合并到适当的班级中。

答案 12 :(得分:0)

我曾经在每个项目中都有一个名为MiscStuffAndJunk的模块。这是一个容纳一切没有明确去处的地方的地方,要么是因为功能是一次性的,要么是因为我不想改变我的焦点,以便为功能做一个合适的设计这是我需要的,但与我目前所关注的内容相差无几。

但是,这些模块显然违反了OO设计原则。

所以现在,我将模块命名为StuffIHaventRefactoredYet,并且所有这些都与世界相符。

答案 13 :(得分:0)

根据您的静态实用程序功能实际执行和返回的内容,可能会导致单元测试出现问题。我在一个类中遇到一个方法,它在静态类上调用静态函数,返回我在单元测试中不需要的东西,使整个方法不可测试...