2

场景:我们收到一些关于对象的输入参数,例如课程

课程有导师姓名、学生人数、课程时间、房间号等。

我们需要验证(学生人数 > 0、上午 9 点 < 时间 < 晚上 9 点等)输入并创建对象。我们需要返回无效输入的错误源。

我可以想到两种方法

1) 使用静态方法创建一个单独的 Validator 类,

  • 验证输入,(验证方法返回 true,或一些枚举,如 VALID、INVALID_TIME、INVALID_STUDENT_NUMBER)。
  • 如果输入有效,则实例化 Bean。

缺点:

  • 如果我们必须在验证输入值之前处理它们,如果输入有效,上述模式会导致执行两次,一次在 Validator 类中,一次在 bean setter 之前。我们无法返回 Bean 对象,因为 validate 方法需要在无效的情况下返回错误源。

2) Bean 类本身有 validate 方法,输入无效返回异常。通过不同类型的异常追踪错误的来源。

缺点:

  • 需要创建多个自定义异常。
  • 在持有人对象本身中包含验证方法是否正确?

我探索了几种设计模式,但它们并不相关。

请帮助我了解上述方法的优缺点,以及更好的方法。

4

2 回答 2

2

其中一位评论员指出:“您最终会希望得到一系列验证错误。” 这很重要。

根据我的经验,模型对象内部的验证方法不起作用,因为验证逻辑经常更改,并且因为在一组情况下无效的东西在另一组情况下有效。例如,如果验证方法认为晚于晚上 9 点的任何时间都无效,则学校管理人员可以更改规则,以便夏季学期的课程可以运行到晚上 11 点。当这种事情发生时,您不希望在类中使用您的验证方法,因为它不可避免地会发生。

此外,在不了解系统中其他对象的状态的情况下,通常不可能验证一个对象。例如,如果您有一个 Loan 对象,超过 $100,000 的贷款价值可能是无效的,当 Customer 对象的类型是机构类型时除外。您需要了解 Loan 和 Customer 对象才能正确验证 Loan。

我见过的复杂验证的最佳实践是:

  1. 在接受对象之前有效的简单事物。这包括检查数字字段中的无效字符或非数字。

  2. 创建一个验证框架,一次验证一组依赖对象。不要在发现第一个错误时停止验证程序。相反,创建一个名为 ValidationError 的类并让您的框架创建这些对象的集合。这种方法让您考虑对象内和对象间的依赖关系。此外,您可以一次将所有错误呈现给用户,而不是强迫用户一次纠正一个错误。

  3. 不要硬编码像 minimumNumberOfStudents 或 latestClassTime 这样的值。相反,将这些值放在关系数据库表或配置文件中。让验证框架查找正确的值(然后缓存它们)。当值发生变化时(通常会发生变化),您只需要更新文件或数据库;无需重建和重新部署整个应用程序。当我做这项工作时,我正在使用 Smalltalk 进行编码。如果您使用的是像 Smalltalk 或 Ruby 这样的动态语言,实际上很容易将源代码作为“验证块”放入数据库并在运行时执行它。

验证框架可能会使用异常,但我建议不要这样做。应该为更难以恢复的更严重的错误保留异常。此外,异常可能会导致很大的性能损失,如果验证是在服务器上而不是在客户端上完成的,这一点很重要。更糟糕的是,一些平台的异常处理不稳定。

于 2011-11-30T18:52:30.520 回答
0

就像上面指出的那样,有很多方法可以做这样的事情。

如果我正在实现类似的东西,我会看看这篇文章 http://java.dzone.com/news/factories-builders-and-fluent- 关于流畅的接口与构建器模式相结合。

也许它适合您的需求。特别注意 bean 部分的验证。

希望能帮助到你。

于 2011-11-03T00:50:10.457 回答