我应该验证构造函数中的参数吗?

时间:2013-03-03 13:33:59

标签: java model-view-controller design-patterns

我正在创建一个遵循MVC模式的Web应用程序。

在有效的Java中,作者提到在创建新对象时验证类的构造函数中的参数。

但是我没有创建一些将由第三方使用的API。我的类只接受表单输入字段中的参数,这些参数在提交给服务器之前已经过验证。

所以在这种情况下,我应该按照作者在有效java中提到的方式创建我的类,还是没用?

4 个答案:

答案 0 :(得分:9)

它并不像读书和实现它所说的那样清晰。您需要根据具体情况思考并应用知识。

这实际上取决于您如何在类中初始化变量并在对象构造后立即使用它们:

一些指示:

  • 如果变量将由类中的某些方法使用,或者对象将在构造之后立即重新使用(在大多数情况下将会重复使用),则应验证所需的值不为空或为空,以避免出现令人讨厌的异常。

  • 第二次验证输入参数是指您希望将正确的值设置为特定的内部变量。如果您要求将参数约束到特定值范围,则验证非常重要。

示例:

假设我们在对象中有工资上限:

int salary = 0;
int salaryCap = 1000;

在创建过程中,您可以验证传入的工资金额:

public Employee(int salary) {
 if(salary >= this.salaryCap)
  this.salary = salary;
}
  • 类关系还决定了您是否要验证值。如果参数将传递给继承链,例如,我会花时间来验证它们,特别是如果它们会影响继承链中其他对象的状态。

示例:

每当我必须调用超级构造函数时,我很想验证输入:

public Employee(int salary) {
 super(salary); //validate salary against known constraints
}
  • 变量来自哪里?如果你不信任源(比如sql参数等),那么你应该验证它们并可能在执行更多代码之前清理输入。这可以防止安全攻击。

  • 我总是厌倦在构造函数中进行验证和参数检查。我更喜欢让getter和setter来验证输入。这样,如果在创建对象时发生了某些事情,至少我得到了半工作对象的保证,而不是完全不一致的对象,其状态不容易确定。当然这取决于你的上下文,如果你的约束是严格的,你可以停止创建对象并提示客户端(用户,调用对象等)获取有效的输入参数。

使用getter / setter提供给我的优点是,对象实际上是通过调用对象提供的外部接口来逐步构造的,而不是在创建期间约束验证,当发生异常时,渲染对象不可用/不稳定。

所以不要这样:

public Employee(int salary) {
 if(salary >= this.salaryCap)
  this.salary = salary;
}

我更喜欢这个:

public class Employee {
 public void setSalary(int salary) {
  if(salary >= this.salaryCap)
      this.salary = salary;
 }
}

后者使我能够干净地退出调用者的有效异常,这不会影响对象的创建(我不喜欢在构造函数中抛出异常)。

简而言之,你的变量有约束吗?如果是,请在将这些约束设置为内部数据属性之前验证这些约束。

答案 1 :(得分:4)

我建议您验证域中的数据,并在未正确填写字段时返回(自定义)异常。这样您就可以实现不同的UI,而无需再次进行整个验证过程,最好尽可能地将其分开。

答案 2 :(得分:1)

乍一看,没有必要验证参数,因为验证是在之前完成的。但是你应该考虑到你的类将在其他情况下使用,你不能确定每次构造函数的输入是否有效。

答案 3 :(得分:-6)

听起来您正在验证之前已经过验证的字段。 在这种情况下,这只是浪费时间(写作和运行时)。如果您的表单(客户端javascript)尚未验证字段,那么它将是有意义的。否则你可以跳过它。