【问题标题】:Tips for avoiding Static Method Overuse避免静态方法过度使用的提示
【发布时间】:2010-01-29 22:20:35
【问题描述】:

我正在重构一些代码,并且正在查看一个名为 HFile 的类。 HFile 具有所有私有构造函数,因此您实际上无法创建它的实例。而不是创建 HFiles 的实例如下:

var file = new HFile('filename')
file.Save()

所有 HFile 交互都是通过静态方法处理的。所以如果我想保存一个文件,我会调用:

HFile.save('filename')

然后在内部创建并保存一个 HFile 实例。显然,不了解整个故事的任何读者都必须保留判断力,但在我的工作场所,使用静态方法似乎变得非常流行。所以我想知道是否有使用静态方法的良好原则/最佳实践可以帮助一群人坐下来回顾他们对静态方法的使用情况。

【问题讨论】:

  • 将语言或平台放入标签是个好主意。

标签: language-agnostic static-methods


【解决方案1】:

大量的静态方法/静态类是程序化的症状——用面向对象的语言编写程序代码。我所知道的消除这种思维的最好方法是彻底理解面向对象的原则和实践。使用测试驱动开发并强制代码可测试会有所帮助,因为为静态类编写测试要困难得多。最终,如果您使用 TDD,您自然会倾向于更加解耦的 OO 架构,即使只是为了减轻测试的痛苦。

【讨论】:

  • 静态方法的测试是最容易编写的,前提是您没有保持任何静态状态。
  • @RobertHarvey 如果它是一个没有副作用且没有依赖关系的纯函数(或者如果所有依赖关系都作为参数给出),那是真的。老实说,我没有看到很多这样的课程。此外,如果您需要消除对它们使用的依赖,那么在其他类中使用它们可能会非常困难——这可能是我没有看到很多它们的原因,因为我强调可测试性。
  • 这些是我编写的唯一一种静态方法。查看 .NET 框架中的 Math 类以获得代表性示例。
  • @RobertHarvey 当然,我也写了一些类似的东西,但它们并不是我工作的很大一部分。那是我唯一的观点。通常,可测试性问题会阻止我编写那种代码。
【解决方案2】:

一般来说,如果您的情况需要封装状态或组织结构,那么您将使用类。

另一方面,如果您有一些横切关注点,并且可以在您的应用程序中广泛使用,您可能会考虑使用静态实用程序类中的方法。 .NET 框架(和 Java)中的 System.Math 就是一个例子。

在你的例子中,HFile 可能是一个有状态的对象,所以我一般不会使用静态方法来保存它。只需对特定的 HFile 对象进行方法调用就更简单了,而不必将整个对象传递给静态方法进行保存。这在您的特定应用程序中是否有意义取决于您的应用程序的范例是将 HFile 对象视为要传递并由外部方法执行的东西,还是视为能够自我保存的独立对象。

【讨论】:

    【解决方案3】:

    静态方法很难测试,因为您无法模拟它们。出于这个原因,我们倾向于在我的工作地点避开它们。虽然我们确实将它们用于工厂方法。

    【讨论】:

    • 我想补充一点,静态工厂方法可以在实例化所有依赖项的类中使用(例如 Guice @Provides 方法),但是在常规代码中使用静态工厂方法会损害可测试性,因为,就像使用普通的静态方法一样,它们将您的代码锁定为使用特定的实现并阻止您模拟依赖项。
    【解决方案4】:

    我不会担心静态方法的数量,而是担心这些方法在做什么。返回值或修改作为参数传递的对象的静态方法?没什么大不了的。修改私有静态字段的静态方法?我担心。修改属于其他类的公共静态字段的静态方法?我需要躺在一个黑暗的房间里,额头上沾着一块湿毛巾。

    【讨论】:

    • 我同意。我个人从来不需要使用静态方法来修改私有静态变量或更糟糕的静态变量来自另一个类!
    【解决方案5】:

    这不是非常面向对象的,是吗。现在,也许您所在的地方并不真正喜欢 OO 代码,这很好。但是如果你想封装数据和方法,那么你需要实例方法来处理这些数据。

    大量的静态方法可能与大量的全局变量相关联。例如。如果您要调用静态 HFile.save('filename'),您尝试保存到文件名中的信息必须是全局的。通常,我们会尝试减少全局变量以使事情更易于管理。

    但如果你想写程序代码,那也没关系。

    【讨论】:

    • 静态方法是很好的加载器(一种工厂方法)。我还发现在资源锁周围使用它们以避免阻塞其他进程非常有成效。
    【解决方案6】:

    IMO 静态方法对于您所描述的在您的工作场所很常见的目的没有用处。 这种方法的缺点:
    - 创建一个代表文件的对象以本质上只是在其上调用一种方法有什么意义?
    - 不能使用基于接口的多态性

    为了回答您的问题,以下是一些我会使用静态方法的情况:
    - 一种实用方法,它与类的功能相关,但与任何一个对象无关。也许它需要一组对象并比较它们。也许它会进行一些通用的数据操作(转换等)。
    - 你需要用类变量做与类相关的事情
    - 你想在哪里实现单例设计模式

    【讨论】:

      猜你喜欢
      • 2014-12-19
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2013-06-27
      • 2014-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多