【问题标题】:Why not to use static methods for external resources?为什么不对外部资源使用静态方法?
【发布时间】:2017-10-11 19:13:24
【问题描述】:

我喜欢使用 java 中的静态方法,例如在 Util 类中。但是在一些同事中,我遇到了一些论点,即静态方法不应该使用外部资源。但没有人能解释为什么它应该是坏的甚至是危险的。我发现的唯一原因是在测试期间可能很难模拟该外部资源。但这真的是唯一的原因吗?

下面我有一个静态方法的例子。我很想了解为什么将它与静态一起使用应该是一种不好的方法。

public class JmsUtil {
    public static String sendBytesMessage(byte[] messageBytes) throws JMSException, NamingException {
        String jmsMessageID = null;
        Connection connection = null;
        try {
            Context context = new InitialContext();
            ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("ourfactory");
            Queue queue = (Queue) context.lookup("ourqueue");

            connection = connectionFactory.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer messageProducer = session.createProducer(queue);
            BytesMessage bytesMessage = session.createBytesMessage();
            bytesMessage.writeBytes(messageBytes);

            messageProducer.send(bytesMessage);
            jmsMessageID = bytesMessage.getJMSMessageID();    
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
        return jmsMessageID;
    }
}

最好的问候

【问题讨论】:

  • 静态方法没有错。这取决于你需要什么。有一些很棒的工具,比如 apache common,实际上是 StringUtils,它有很多静态方法。如果你想模拟静态的东西,你可以使用 Powermock。无论如何,这个问题对我来说似乎有点离题,因为这更像是一个基于意见的事情。
  • sendBytesMessage 在您的示例代码中未标记为 static
  • 静态方法使得在测试中模拟外部资源变得困难(或者不可能,如果你不想使用类似 PowerMockito 的话)。也许阅读Static methods are death to testability
  • “但这真的是唯一的理由吗?”这是一个相当大的原因。如果您无法在不访问外部资源的情况下测试您的代码,那么您的测试将不会被编写、不会运行,或者将取决于静态资源的状态。

标签: java static static-methods


【解决方案1】:

考虑两个类

class Foo extends Blob{

public void someMethod(){
byte[] message = createMessage(); 
JmsUtil.sendBytesMessage(message);
}

}

class Bar extends Blob{
Sender sender;

public void someMethod(){
byte[] message = createMessage(); 
sender.sendBytesMessage(message);
}

}

Foo 类使用实用程序类,而 Bar 类使用实现 Sender 接口的类。

首先,正如您在问题中提到的那样,为了测试目的而模拟发件人要容易得多。否则您需要创建可以接收消息以验证整个过程的基础架构。

第二件事,你正在失去抽象功能的可能性。想象一下您需要改变发送消息的方式的情况。在第一种情况下,您需要在处理系统逻辑的类中进行修改。其次,当您抽象出发送消息的过程时,您需要在负责引导您的应用程序的模块中进行更改。在某些情况下,更改可能在您的配置文件中完成并在实时系统上完成

【讨论】:

    【解决方案2】:

    静态方法的主要问题是您不能轻易更改实现。静态方法不能有接口。

    这很糟糕,原因有很多,但让我们专注于访问外部资源。

    使用静态方法,可测试性成为一个大问题。要么您需要外部资源进行测试,要么您“围绕”您的静态方法进行测试。如果你有一些 MessageSender 接口,你可以轻松地在测试中模拟它,只检查它是否按预期调用。

    那么你有时可能需要修饰对外部资源的访问。例如,如果您有一些查找 REST 客户端,您稍后可能会决定添加缓存以提高性能。使用接口更容易做到这一点。

    【讨论】:

      猜你喜欢
      • 2013-03-19
      • 1970-01-01
      • 1970-01-01
      • 2014-07-29
      • 2013-05-08
      • 2018-09-20
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      相关资源
      最近更新 更多