N层系统中的例外情况

时间:2012-07-06 06:56:16

标签: java exception-handling

我有一个4层系统(数据库,持久性,业务,演示)。后三层都在一个JVM中运行。

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

public void process(String label) throws ValidationException {

    if(label == null) {
        // this is a custom exception that means that one of the arguments invalid
        throw new ValidationException("The label can not be null.");
     }

    if(label.length() != 8) {
        throw new ValidationException("The label has to be 8 letters long."); 
    }

    ... process ...
}

这里的问题是商业轮胎不知道无效的参数是演示文稿还是用户的错误。

  • 如果标签是由用户提供的,那么这就是用户的错误,并且演示文稿必须显示带有验证异常消息的“验证失败”消息。
  • 另一方面,如果标签是由用户演示文稿生成的,那么演示文稿的错误(可能是错误),演示文稿必须显示“内部错误”消息。
  • 此外,如果标签为空,则这是演示文稿的100%错误。

当传递用户生成的参数和表示生成的参数的混合时,问题就出现了。在这种情况下,演示文稿无法知道导致异常的原因。它唯一得到的是向用户显示详细消息(因为如果是用户的错,则用户必须知道原因)。但是,向用户显示详细的错误消息是不可接受的,而这是演示文稿的错误,因为它只会让用户感到困惑。

在这种情况下我该如何处理异常?有什么模式可以使用吗?

2 个答案:

答案 0 :(得分:4)

从OOP哲学来看,数据知道自己的行为。

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

这是一个想法:

  1. 针对用户生成和非用户生成的错误抛出不同的异常。如果是用户生成的,表示层会捕获它并显示消息。如果不是,表示层将显示通用消息“内部错误”或“抱歉”等。
  2. 业务层不是哪一个。所以,数据必须知道。在您的示例中,label不能是字符串。它可以是一个班级。
  3. 将所有参数包装在某个类

    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;
    }
    

    现在,您可以为标签(LabelValidator implements Validator)等内容设置特殊验证器,并为其他人设置简单的验证器,例如NotNullValidator。这些将在创建时关联。

    在业务逻辑层,你得到

    void process(Argument<String> label) {
        if (label != null ) label.getValidator().validate();
        //continue.
    }
    

    在演示层

    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");
    }
    

答案 1 :(得分:0)

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

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

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

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

例如:

  • !@_的Java
  • !@_的Python

所以这个“!@_”表示应用程序生成标签,然后您可以设计一个解决方案,相应地处理任何与验证相关的问题。

如果标签通过了验证步骤,您可以随时删除“!@_”部分。

请注意,所有标签生成仅来自特定代码(最好是静态实用方法)。

相关问题