3

在我的工作场所,目前似乎正在反对静态课程。我可以理解其中的一部分,它们确实破坏了整个单元测试的模块化。但是,我看到大量代码审查要求删除静态类。

一个常见的情况是一个实用程序类,它与一些在编译时“已知”的其他对象一起被弹簧注入。它没有其他成员变量。如果 M 类调用这个静态类,我总是看到建议使这个实用程序类非静态并将其注入到 M 类中。

这对我来说没有意义。除了它似乎浪费时间并且使实用程序类不太容易使用之外,我没有特别看到它有什么问题。据我所知,理由通常是用于单元测试,但我不喜欢必须更改有效代码以符合测试范式的想法。不可否认地模拟一个简单的静态实用程序类可能是矫枉过正。

静态类在这个用例中是合适的,还是最好避免?

4

6 回答 6

2

我认为这两种方法的差异很小,但只要类不包含状态,将其设为静态会稍微好一些。假设我在 A 类中有这段代码:

StaticClass.utilMethod()

如果我想在 BI 类中使用此代码,可以复制和粘贴。而已。不用添加成员变量,注入等 cmd -c cmd -v。

考虑到您现有的代码使用静态类并且需要进行修改,因此最好继续使用静态类。

于 2012-08-10T18:58:40.300 回答
1

If you pretend for a moment that your static class did not belong to you, that it was, say, part of the .NET framework, how would your team handle it? Their answer would be my answer. In other words, if their answer to that question is inconsistent with what they're asking you to do, then they should probably either change how they work with .NET static classes or with how they work with yours.

于 2012-08-10T18:59:51.830 回答
1

取决于,自然。

  • 您想如何测试使用静态类的代码?
  • 静态类是否封装了您需要经常模拟的行为?
  • 是否有人需要修改这些静态类的行为?

最后:

  • 是否有注入 Spring 管理的单例 bean 的令人信服的理由?
于 2012-08-10T19:10:25.570 回答
1

我投票赞成使用静态类...即仅具有静态方法的类,用于纯粹的实用程序目的。甚至 java 也为我们提供了这样的类,比如java.util.Collectionsjava.util.Arrays

于 2012-08-10T18:55:06.037 回答
1

不可否认地模拟一个简单的静态实用程序类可能是矫枉过正。

你在这点上是完全正确的。静态类只能用于极其简单的实用程序类,在这些类中模拟这样的类没有任何好处。如果您将它们用于任何其他目的,您应该重新考虑您的设计。

如果该类不包含状态,那么使用非静态类是否合理?

这真的与国家无关。例如,策略对象通常不包含状态,但它们不是静态的;它们通常实现一个通用接口,并且需要可互换/可模拟。

于 2012-08-11T23:12:30.883 回答
1

我避免使用静态类(假设我们实际上是在谈论包含静态方法的类),我这样做是为了可测试性。

如果您使用静态方法,您将很难模拟/存根代码中使用所述静态方法进行单元测试的部分。

考虑一下:

public String myMethod() {
    String complicatedStringOutput = MyUtility.createComplicatedStringOutput();
    //do some more complicated work on this String
}

要为此方法编写单元测试,您将如何使其成为“真正的单元测试”而无需同时测试 的创建complicatedStringOutput?在我的单元测试中,我更喜欢只测试作为单元测试重点的方法。

将其更改为:

public String myMethod(MyNonStaticUtility util) {
    String complicatedStringOutput = util.createComplicatedStringOutput();
    //do some more complicated work on this String
}

突然之间,为这个类编写“真正的单元测试”要容易得多。MyNonStaticUtility您可以通过使用存根或模拟来控制 的行为。

综上所述,这完全取决于您(或您的业务部门)。如果您重视单元测试并认为对复杂代码进行良好的测试覆盖很重要,那么这是首选方法。如果您没有时间/金钱来投资“修复”您的代码,那么它就不会发生。

于 2012-08-10T19:05:21.527 回答