我们应该避免在java代码中编写静态方法以获得更好的可测试性吗?

Fre*_*ind 11 java static

我更喜欢在我的java代码中使用静态方法,因为我认为它们是"功能性的" "无状态"并且副作用较小.所以可能有一些辅助类和方法如下:

public class MyHelper {
    public static Set<String> array2set(String[] items) { ... }
    public static List<String> array2list(String[] items) { ...}
    public static String getContentOfUrl(String url) {
        // visit the url, and return the content of response
    }
}

public class MyApp {
    public void doSomething() {
        String[] myarray = new String[]{ "aa","bb"};
        Set<String> set = MyHelper.array2set(myarray);
        String content = MyHelper.getContentOfUrl("http://google.com");
    }
}
Run Code Online (Sandbox Code Playgroud)

但我的朋友说我们应该避免定义这样的静态实用程序方法,因为我们直接在我们的代码中调用它们,如果它们具有外部依赖性,则很难模拟它们或测试它们.他认为代码应该是:

public class ArrayHelper {
    public Set<String> array2set(String[] items) { ... }
    public List<String> array2list(String[] items) { ...}
}
public class UrlHelper {
    public String getContentOfUrl(String url) {
        // visit the url, and return the content of response
    }
}

public class MyApp {
    private final ArrayHelper arrayHelper;
    private final UrlHelper urlHelper;
    public MyApp(ArrayHelper arrayHelper, UrlHelper urlHelper) {
        this.arrayHelper = arrayHelper;
        this.urlHelper = urlHelper;
    }
    public void doSomething() {
        String[] myarray = new String[]{ "aa","bb"};
        Set<String> set = arrayHelper.array2set(myarray);
        String content = urlHelper.getContentOfUrl("http://google.com");
    }
}
Run Code Online (Sandbox Code Playgroud)

这样一来,如果我们想编写单元测试MyApp,我们就可以嘲笑ArrayHelperUrlHelper并传递给的构造函数MyApp.

我完全同意UrlHelper他的意见部分,因为原始静态代码MyApp不可测试.

但是我对这个ArrayHelper部分有点困惑,因为它不依赖于任何外部资源,而且逻辑非常简单.在这种情况下我们应该避免使用静态方法吗?

什么时候使用静态方法?或者只是尽量避免使用它?


更新:

我们在开发中使用"TDD",因此课程的可测试性通常是我们最关心的问题.

我只是在第一句中用"无状态"替换"功能性"这个词,因为那是真实的意思.

JB *_*zet 13

您可能永远不会想要模拟将数组转换为列表(或集合)的方法,并且此方法不需要任何状态且不依赖于任何环境,因此静态方法对我来说很好.

就像标准Arrays.asList()(你应该使用它).

另一方面,访问外部URL通常是您希望能够轻松模拟的东西,因为不会嘲笑它

  • 使测试成为集成测试
  • 要求在每次运行测试时都使用此外部URL,这可能无法保证
  • 要求让此外部URL返回您希望它在测试中返回的内容(如果您要测试错误事件,则包括错误).


Mar*_*nik 6

请注意 Java“专家”中非常常见的一种疾病:过度设计

在您的具体示例中,您没有可模拟性问题。如果你有问题,你不会问一般问题,因此我得出结论你目前没有问题。

一般的论点是static,只要有选择,方法就更简单,因此是首选。一个可能的实例方法必须首先证明自己需要是一个实例方法。

如果这是我的项目,我会推迟对实例方法的任何改造,直到对它的需求变得清晰和存在的那一刻。