首先验证还是尝试捕获?

时间:2011-08-02 03:40:45

标签: java code-design

假设我有一个看起来像这样的函数:

public void saveBooking(/* some inputs */) {
    //save into database
}

在保存到数据库之前,我必须进行各种验证。我在主程序中可以做的是这样的:

//do all the validations and do any necessary handling. Then...
saveBooking(/*inputs*/);

有了这个,我确信在保存到数据库之前,所有数据都必须通过所需的所有验证。但是,这意味着函数saveBooking()非常依赖于验证方法。每次我想打电话给saveBooking()时,我都要确保不要忘记给他们打电话。

或者,我可以将所有验证放在函数本身中,这样我所要做的就是调用方法,一切都得到了解决。但是,为了独立处理所有错误,我必须使函数抛出异常并捕获主程序。看起来应该是这样的:

public void saveBooking(/* some inputs */) /* throws various exceptions */ {
    //various validations
    //save into database
}

//...and in the main program...
try{
    saveBooking(/*inputs*/);
}
catch(MyException1 e1){
    //do something
}
catch(MyException2 e2){
    //do something
}

这也意味着我必须自己创建多个例外。好消息是我不必担心我必须提供哪些验证。

有了这些,我不确定哪一个是最好的代码设计。我个人更喜欢第一种方法,它更具可读性,但它相互依赖太多而且当我需要在很多地方使用它时它会变得更糟。请指教!

5 个答案:

答案 0 :(得分:7)

绝对第二个选项的第一个选项。我认为第二个是滥用例外。例外情况适用于特殊情况,验证失败并非“例外”。

  

每次我想致电saveBooking()时,我都必须确保不要忘记致电验证。

将验证逻辑放入一个单独的方法中,让saveBooking()在执行任何其他操作之前调用验证方法。

public List<ValidationError> validateBooking(/* args */)
{
    // as @Jared Farrish suggests, return a list of validation errors
}

public boolean saveBooking(/* args */)
{
    List<ValidationError> errors = validateBooking(/* args */);

    if (errors.size() != 0) return false; // validation failed

    // save to the database

    return true;
}

答案 1 :(得分:2)

通常应在函数本身内执行检查,以便在没有首先验证数据的情况下 no 尝试保存数据的可能性。如果没有函数内的那些检查,你可以找到一个客户试图保存而不进行验证,这很少是一件好事。

但是您不限于使用异常,您只需返回某种类型的错误代码即可由调用者进行检查。虽然我通常不关心错误是由异常还是返回代码完成,但有些可能会将此视为滥用异常。

验证代码可能仍然作为单独的函数保留,因为您自己的代码可能希望在不进行保存的情况下调用它。像(伪代码):

def validateStuff():
    if stuff is not valid:
        return WTF
    return OK

def saveBookings():
    rc = validateStuff()
    if rc != OK:
        return rc;
    save the information
    return OK

如果只是为了处理I / O错误之类的话,你仍然可能会遇到saveBookings调用异常,但它不是绝对必要的:你可以捕获这些异常在函数中也将它们转换为返回码。

我倾向于喜欢每个函数的一种报告方法,所以我(例如)不必try/catch 检查返回代码。

答案 2 :(得分:1)

通过在插入之前验证所有内容,您确实做了正确的事情,您还应该验证您插入的所有内容是否适合或满足数据库中的约束,以避免意外的SQLException,这是您不会期望的,并且一路走到顶端。

我建议创建一个带有一些属性的自定义异常来描述错误的原因,这样你只需要担心捕获一种异常。

另外,我肯定会将验证放在方法中,因此它总是被调用。

答案 3 :(得分:0)

三层方法相当普遍,其中您有以下3层:

  • 客户端界面。这可以包括Web应用程序的JavaScript验证或GUI控件的一些基本SWT验证。
  • 业务层。该层知道业务规则。这是您通常希望进行服务器端验证的地方。应该保存,更改等任何内容都应该通过业务层完成(这样您总是可以验证并且不关心数据存储)。
  • 数据层。这层通常是“哑”。只需保存,删除,选择等;无论业务层请求这个层都是简单的。

这非常简化,但它为您提供了一种分离不同类型逻辑的方法,以便于维护。

答案 4 :(得分:0)

将大量代码放在一个地方并不是一个好主意。抛出已检查的异常也不是一个好主意。