Java N层系统中的异常

Java N层系统中的异常,java,exception-handling,Java,Exception Handling,我有一个4层系统数据库、持久性、业务和演示。后3层都在一个JVM中运行 我在业务层和表示层之间遇到了一些异常处理问题。将下面的代码视为一个非常简化的例子: 这里的问题是,业务人员不知道无效参数是演示文稿的错误还是用户的错误 假设标签是由用户提供的,那么这是用户的错误,演示文稿必须显示验证失败消息和验证异常消息。 另一方面,如果标签是由演示文稿为用户生成的,那么这可能是演示文稿的错误,可能是一个bug,演示文稿必须显示一条内部错误消息。 此外,如果标签为空,这100%是演示文稿的错误。 当用户生成

我有一个4层系统数据库、持久性、业务和演示。后3层都在一个JVM中运行

我在业务层和表示层之间遇到了一些异常处理问题。将下面的代码视为一个非常简化的例子:

这里的问题是,业务人员不知道无效参数是演示文稿的错误还是用户的错误

假设标签是由用户提供的,那么这是用户的错误,演示文稿必须显示验证失败消息和验证异常消息。 另一方面,如果标签是由演示文稿为用户生成的,那么这可能是演示文稿的错误,可能是一个bug,演示文稿必须显示一条内部错误消息。 此外,如果标签为空,这100%是演示文稿的错误。 当用户生成的参数和表示生成的参数混合传递时,问题就出现了。在这种情况下,演示文稿无法知道是什么导致了异常。它唯一能做的就是向用户显示详细的消息,因为如果是用户的错误,用户就可以知道原因。然而,当这是演示文稿的错误时,向用户显示详细的错误消息是不可接受的,因为这只会让用户感到困惑


在这种情况下,我应该如何处理异常?是否有任何模式可供使用?

一旦应用程序生成的标签代码稳定并符合您的规范,则验证检查不应失败。 必须有更多的用例未包含在问题中

我能想到的一个可能的解决方案是:

如何区分用户生成的标签和应用程序生成的标签

如果您没有任何机制来区分,我建议您在应用程序生成的标签上附加一些特殊的字符序列

例如:

!@_JAVA !@_python 那么这个!将指示应用程序生成的标签,然后您可以设计相应地处理任何验证相关问题的解决方案

如果标签通过了验证步骤,您可以随时剥离!@部分


请注意,您的所有标签生成都是从特定代码段(最好是静态实用程序方法)生成的。

一旦您的应用程序生成的标签代码稳定并符合您的规范,则验证检查不应失败。 必须有更多的用例未包含在问题中

我能想到的一个可能的解决方案是:

如何区分用户生成的标签和应用程序生成的标签

如果您没有任何机制来区分,我建议您在应用程序生成的标签上附加一些特殊的字符序列

例如:

!@_JAVA !@_python 那么这个!将指示应用程序生成的标签,然后您可以设计相应地处理任何验证相关问题的解决方案

如果标签通过了验证步骤,您可以随时剥离!@部分


请注意,所有标签的生成都是从一段特定的代码(最好是静态实用程序方法)生成的。

从OOP原理来看,数据知道自己的行为

有很多方法可以解决这个问题

这里有一个想法:

为用户生成的错误和非用户生成的错误引发不同的异常。如果它是用户生成的,表示层将捕获它并显示消息。如果不是,表示层将显示一条通用消息“内部错误”或“对不起”之类的消息。 业务层不知道哪个是哪个。所以,数据必须知道。在您的示例中,标签不能是字符串。它可以是一门课。 将所有参数包装到某个类中

class Label implements Validatable {
    String label;
    @Override
    public void validate() throws BaseValidationException {
         //Check conditions and throw the proper exceptions.
         //Label class should know which validations are user and 
         //Which are presentation and throw appropriate exceptions.
    }
}
为所有参数创建一个单独的类将是乏味的。你可以有这样的东西:

class Argument<E>  {
    E realArgument;
    Validator validator;
    public Argument(E value, Validator validator) {
        //implement
    }

}
interface Validator {
    public void validate() throws BaseValidationException;
}
在表示层

try {
    process(....)
} catch (UserException ex) (
   showMessage(ex.getMessage());
) catch (PresentationError ex) {
  log.fatal(ex.getMessage());
  showMessage("Pre-formatted internal error message");
} catch (Exception ex) { //Unknown exception
  log.fatal(ex.getMessage());
  showMessage("Pre-formatted internal error message");
}

从OOP理念来看,数据知道自己的行为

有很多方法可以解决这个问题

这里有一个想法:

为用户生成的错误和非用户生成的错误引发不同的异常。如果它是用户生成的,表示层将捕获它并显示消息。如果不是,表示层将显示一条通用消息“内部错误”或“对不起”之类的消息。 业务层不知道哪个是哪个。所以,数据必须知道。在您的示例中,标签不能是字符串。它可以是一门课。 将所有参数包装到某个类中

class Label implements Validatable {
    String label;
    @Override
    public void validate() throws BaseValidationException {
         //Check conditions and throw the proper exceptions.
         //Label class should know which validations are user and 
         //Which are presentation and throw appropriate exceptions.
    }
}
为所有参数创建一个单独的类将是乏味的。你可以有这样的东西:

class Argument<E>  {
    E realArgument;
    Validator validator;
    public Argument(E value, Validator validator) {
        //implement
    }

}
interface Validator {
    public void validate() throws BaseValidationException;
}
在表示层

try {
    process(....)
} catch (UserException ex) (
   showMessage(ex.getMessage());
) catch (PresentationError ex) {
  log.fatal(ex.getMessage());
  showMessage("Pre-formatted internal error message");
} catch (Exception ex) { //Unknown exception
  log.fatal(ex.getMessage());
  showMessage("Pre-formatted internal error message");
}

通常,用户输入的简单验证被认为是一个表示级的关注点,所以如果有任何信息通过,您可以安全地将其视为一个系统级错误。通常情况下,验证不能通过演示来完成。通常是这样的
简单地验证用户输入被认为是一个表示级别的关注点,因此如果有任何信息通过,您可以安全地将其视为一个系统级错误。通常情况下,演示文稿无法完成验证。其他数据类型如何?整数布尔值?自定义对象?我只考虑了您的示例代码。对于其他数据类型,包装器类和泛型将是一个不错的选择。Ahh@chips解决方案应该是一个不错的选择,示例代码为+1。其他数据类型呢?整数布尔值?自定义对象?我只考虑了您的示例代码。对于其他数据类型,一个包装类和泛型将是一种方法。Ahh@chips解决方案应该是一种方法,示例代码为+1。