3

我有关于表单验证和业务验证的问题。我看到很多框架使用某种形式的验证库。您提交一些值,库会验证表单中的值。如果不正常,它会在您的屏幕上显示一些错误。如果一切按计划进行,这些值将被设置到域对象中。在这里,这些值将被验证,或者更好地说,应该(再次)验证。验证库中很可能是相同的验证。我知道 2 个 PHP 框架具有这种构造 Zend/Kohana。

当我查看编程和一些原则时,例如不要重复自己(DRY) 和单一职责原则(SRP),这不是一个好方法。如您所见,它验证了两次。为什么不创建进行实际验证的域对象。

示例:提交带有用户名和电子邮件表单的表单。用户名字段和电子邮件字段的值将填充到 2 个不同的域对象中:用户名和电子邮件

class Username {}
class Email {}

这些对象验证它们的数据,如果无效则抛出异常。你同意?您如何看待这种方法?有没有更好的方法来实现验证?我对很多处理这些东西的框架/开发人员感到困惑。他们都是错的还是我错过了一点?

编辑:我知道还应该有客户端类型的验证。在我看来,这是一个不同的球赛。如果您对此有一些意见以及处理此类事情的方法,请提供。

4

6 回答 6

6
  • 表单验证(客户端)实际上只是为了可用性
  • 业务验证才是真正的验证

您的应用程序可能会在没有您所谓的表单验证的情况下工作,它只会让用户看起来不太好。然而,需要业务验证以防止数据损坏。

于 2009-12-23T12:23:20.117 回答
3

虽然看起来违反了 DRY 原则,但实际上您是在两个不同的层中验证数据——表示层和业务层;这两层之间的验证问题可能不同。在表示层中,您可能关心与视图相关的特定元素,即在 Web 应用程序中,您可能需要返回包含 html div 的特定验证消息,以便正确呈现 ajax 响应。

此外,表单通常包含与持久性相关的约束,例如没有某个表单字段为空或限制字段大小,而业务约束可能更广泛,即通过验证个人在电子商务 web 应用程序中的购买是否可以被允许过去的成功购买。

也就是说,有一些框架,如 hibernate 验证器(在 java 上),允许您在业务实体中包含验证元数据,这些元数据在持久化之前或在您调用其 API 以手动执行此操作时进行检查。有了它,您可以在一个地方验证所有约束。

于 2009-12-23T14:19:39.010 回答
1

您描述的方法对我来说看起来有点过度设计。我可以看到它在理论上是整洁和干净的,但在我看来,在实际情况下映射到数据会有点过于细化,从而产生不必要的开销和一大堆在宏伟计划中做的很少的类事物。当我遇到这样的事情时,它往往会开始闻到一点解决方案蔓延的味道。此外,如果您有很多围绕原语的每个字段包装器,那么您的“AddressLine1”类和“AddressLine2”类之间的 DRY 违规的可能性很大,等等,或者避免它们所必需的过于复杂的继承层次结构。

就像第六范式一样——理论上很有趣,但是如果你用这种方式编写代码,你需要很长时间才能完成任何事情,维护将是一场噩梦。

于 2009-12-23T12:51:56.113 回答
1

如果您也使用业务领域对象来验证表单,这可以使用相当简单的工具来实现,这消除了大多数基于验证器的解决方案的麻烦。在某种程度上,您希望将部分行为从业务域外推到表单域;这应该以一些额外的布线为代价来减少代码并改善维护。我同意罗伯特。我觉得这种方法比 Zend/Cake/Ci 等更好。它似乎朝着裸对象哲学的方向发展;只需转储 V 和 C,只选择模型:http ://en.wikipedia.org/wiki/Naked_objects

于 2009-12-23T13:54:34.013 回答
0

在 Web 上,您可能希望某种客户端验证作为“第一道门”——检查所需值和其他简单的验证规则,而不需要用户执行 Web 请求只是为了查看数据无效。最重要的是,您需要一个执行对象属性和其他业务规则的实际验证的服务器端验证层(内置在您的域对象中、服务层或其他地方)。
但是请注意,依赖于域的验证规则(例如 aName具有所需的属性FirstNameLastName)和纯业务规则(例如,如果 aState已提供,则Country必须是USA)不一定必须位于同一位置。

于 2009-12-23T10:38:13.813 回答
0

在这两个地方进行验证多余但必要的。您需要在客户端上进行验证,以便您的用户获得更好的 UI 体验。它还可以减少服务器上的负载。您还必须在服务器端进行验证,因为您的应用程序不应信任任何通过网络传输的内容。

于 2009-12-23T14:05:24.643 回答