Java 设计一个错误报告实用程序

Java 设计一个错误报告实用程序,java,Java,我很难找到一个相关的标题,因为这不是一个简单的问题。我会尽力解释的。我有一个负责错误报告的类,其方法基本上包含了报告错误的多种方法。 例如,我有一个方法失败测试: public static void failTest(Logger log, Exception e, String message, boolean reportToES, String esTestPath, String esTestSet, String esTestInstance) { log.error(e, mess

我很难找到一个相关的标题,因为这不是一个简单的问题。我会尽力解释的。我有一个负责错误报告的类,其方法基本上包含了报告错误的多种方法。 例如,我有一个方法失败测试:

public static void failTest(Logger log, Exception e, String message, boolean reportToES, String esTestPath, String esTestSet, String esTestInstance)
{
log.error(e, message);
someExternalErrorReportingService(reportToES, esTestPath,esTestSet,esTestInstance);
Assert.fail(e,message);
}
我在很多地方都称这种错误报告方法,每次都用es*参数调用它似乎不是一种好的做法(参数太多,很难遵循它们的顺序等等),因为它们不会经常更改,所以可以设置一次,然后重新使用。 我想出了这个版本

public static void failTest(Logger log, Exception e, String message)
{//same body
}
And then added method to set up es* parameters
setES(boolean reportToES, String esTestPath, String esTestSet, String esTestInstance)
{
this.reportToES = reportToES; 
this.esTestPath = esTestPath; 
this.esTestSet = esTestSet; 
this.esTestInstance=esTestInstance;
}
当然,上面添加了这些实例变量。 只有现在我才能阐明这个问题: 现在,如果我想使用这个错误报告类,我需要首先实例化它并设置es*字段。问题是,我经常需要在一个可能是静态的实用程序类中使用错误报告,但是现在,通过上面的更改,我必须实例化它并设置错误报告类,以便在调用failTest()之前设置es*字段。 总之,我也不喜欢这个解决方案,因为我不能再使用静态实用程序类,而且一些实用程序类已经以静态方式使用,因此无法重构为非静态,最终将被使用,有时是静态的,有时是实例化的。 所以问题是,为了简化实用程序类中failTest()的调用,您是否看到了更好的解决方案? 举个例子,我们有一个客户 设置错误报告类并设置其es*字段 此客户端调用实用程序方法utility.doSomething

public static doSomething(reportToES, esTestPath, esTestSet, esTestInstance)
{
try{
 methodThatThrowsFatalException()
}
catch(Exception e){
failTest(log, e, "Some smart message",reportToES, esTestPath, esTestSet, esTestInstance);
}
}   
现在,为了减少参数数量,我们只需将setErrorReportingInstance添加到实用程序类中, 然后在客户端实例化该实用程序,然后是utilityInstance。setErrorReportingInstance(配置ErrorReportingInstance)。而doSomething变成:

public static doSomethingRefactored()
{
try{
 methodThatThrowsFatalException()
}
catch(Exception e){
errorReportingInstance.failTest(log, e, "Some smart message");
}
}   
在我看来,不好的是: 1.我把实用程序的使用复杂化了。现在,在使用它之前,我必须确保它是实例化的。当有很多实用类的时候,这很不方便。 2.如果必须在实现中进行错误报告,则无法在实用程序中生成静态方法。 3.已经用作静态的方法将保留其签名中的es*参数(由于向后兼容性)。因此,我将在同一个类中使用像doSomething这样的方法,以及像doSomethingRefactored这样的方法。 4.我在实用程序类和错误报告之间创建了一个依赖关系,因此当我需要测试实用程序方法时,我遇到了一个问题

问题是,如何保持实用程序类的简单设计为静态实用程序方法的简单集合,但同时使用错误报告类,但不传递太多参数,因为这是一种不好的做法

更多详情: 实际上,客户机是许多TestNG测试用例: 所以首先我有:

class TestClass1
{
static final boolean REPORT_TO_ES="true", 
static final String ES_TEST_PATH="somePath", //and so on for the others 
@Test
{
Utility1.doSomething(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility2.doSomethingElse(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility3.doSomethingMoreUseful(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
Utility4.doSomethingSomething(REPORT_TO_ES,ES_TEST_PATH,ES_TEST_SET,...
}
然后我会尽量避免用ES*值调用doSomethings 通过在ErrorReporter实例上设置它们一次(因此我还将使ErrorReporter成为非静态的)


你的问题的标题应该是“静态混乱”

看看真正的伐木工人是如何工作的,你可能会有一些想法。Log4J和Slf4j是受人尊敬的。您需要控制所有静态变量。您可以创建一个Logger类来封装ES数据并执行真正的日志工作:

// Does the real work of logging.
class Logger {
   public Logger(all of your es data)
   public fail(String msg) // Logs msg
}
然后您需要一个由名称引用的这些记录器的静态集合(我假设您有多组es数据)。这为你找到伐木工人提供了一个中心位置。如果使用静态方法或其他方法,则该方法有效。静态集合位于LogFactory对象内部

class LogFactory {
   private static Map<String, Logger> loggers ...
   public static Logger get(String name) ...
}
我将向LogFactory添加一个clear或reset方法,这样您就有机会为代码编写JUnit测试。出于同样的原因,我将编写一个NullLogger(在这种情况下,您可能希望拉出一个NullLogger和EsLogger都可以实现的接口)

您需要决定如何将记录器添加到LogFactory。我建议您在主类中执行此操作。请抵制在静态初始值设定项中执行此操作的诱惑

还可以编写LogFactory,使其保存一个集合而不是静态集合。然后只保留对它的静态引用(单例)。请记住,您需要一种清除单例的方法,以使单元测试成为可能


祝您好运。

谢谢您的回答。您的解决方案的问题在于实用程序类(具有doSomething()方法)不知道要检索哪个记录器(例如“Util”)。只有客户端知道哪些es值是合适的,因此实用程序类仍然需要实例化,以便了解记录器名称或es值集。很抱歉,我以前没有提到此限制。请帮助我理解。在调用doSomething()之前,您需要设置一些全局数据,以便进行故障测试()要正确工作?本质上,您是在使用堆来绕过堆栈?将所有Es参数组合到一个Es对象中。您可以将其传递到doSomething()。如果该实用程序仅用于测试(您的最后一条评论建议这样做)然后将实用程序设置为Es对象本身。不清楚在这种情况下为什么您喜欢静态方法。我必须承认,我很难理解全局。为什么不发布完整的源代码?Es变量是遗留代码。我们现在不知道是否要保留它们。这就是为什么我想将它们保留在中心位置,以便它们如果我们决定永远不需要它们,它们将被完全移除。但我们总是不能拥有所有这些,所以将Es参数组合到Es对象中似乎是一个更好的解决方案,即有4个值
class LogFactory {
   private static Map<String, Logger> loggers ...
   public static Logger get(String name) ...
}
public static doSomething() {
   try {
     methodThatThrowsFatalException()
  }
  catch(Exception e){
    LogFactory.get("Util").failTest(e, "Some smart message");
  }
}