表单验证和业务验证是否太多?
我有关于表单验证和业务验证的问题。 我看到很多框架都使用某种表单验证库。您提交一些值,图书馆会验证表单中的值。如果不正常,屏幕上会显示一些错误。如果一切按计划进行,这些值将被设置到域对象中。这里的值将被验证,或者更好地说,应该被验证(再次)。很可能在验证库中进行相同的验证。我知道有 2 个具有这种结构的 PHP 框架 Zend/Kohana。
当我研究编程和一些原则时,例如 不要重复自己(DRY)和单一职责原则 (SRP) 这不是一个好办法。正如您所看到的,它验证了两次。 为什么不创建执行实际验证的域对象。
示例:包含用户名和电子邮件的表单 表格已提交。用户名字段和电子邮件字段的值将填充在 2 个不同的域对象中:用户名和电子邮件
class Username {}
class Email {}
这些对象验证其数据,如果无效则抛出异常。 你同意?您对这种方法有何看法?有没有更好的方法来实现验证? 我对很多处理这些东西的框架/开发人员感到困惑。他们都错了还是我遗漏了一点?
编辑: 我知道还应该有客户端验证。在我看来,这是一场不同的比赛。如果您对此有什么意见以及处理此类事情的方法,请提供。
I've got this question about form validation and business validation.
I see a lot of frameworks that use some sort of form validation library. You submit some values and the library validates the values from the form. If not ok it will show some errors on you screen. If all goes to plan the values will be set into domain objects. Here the values will be or, better said, should validated (again). Most likely the same validation in the validation library. I know 2 PHP frameworks having this kind of construction Zend/Kohana.
When I look at programming and some principles like Don't Repeat Yourself (DRY) and single responsibility principle (SRP)
this isn't a good way. As you can see it validates twice.
Why not create domain objects that do the actual validation.
Example: Form with username and email
form is submitted. Values of the username field and the email field will be populated in 2 different Domain objects: Username and Email
class Username {}
class Email {}
These objects validate their data and if not valid throw an exception.
Do you agree? What do you think about this aproach? Is there a better way to implement validations?
I'm confused about a lot of frameworks/developers handling this stuff. Are they all wrong or am I missing a point?
Edit:
I know there should also be client side kind of validation. This is a different ballgame in my Opinion. If You have some comments on this and a way to deal with this kind of stuff, please provide.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您的应用程序可能会在没有所谓的表单验证的情况下工作,它只会对用户来说看起来不太好。然而,需要进行业务验证以防止数据损坏。
Your application would probably work without what you call form validation, it would only look less nice to the user. Business validation however is needed to prevent corrupted data.
虽然看起来违反了 DRY 原则,但实际上您是在两个不同的层(表示层和业务层)验证数据;这两层之间的验证问题可能有所不同。
在表示层中,您可能关心与视图相关的特定元素,即在 Web 应用程序中,您可能需要返回包含 html div 的特定验证消息,以便可以正确呈现 ajax 响应。
此外,表单通常包含与持久性相关的约束,例如不得将某个表单字段设置为空或限制字段大小,而业务约束可能更广泛,即通过验证个人在电子商务 Web 应用程序中的购买是否可以被允许过去的成功购买。
也就是说,有一些框架,例如 hibernate validator(在 java 上),允许您在业务实体中包含验证元数据,这些元数据在持久化之前或在您调用其 API 手动执行此操作时进行检查。有了它,您可以在一处验证所有约束。
While it seems the DRY principle is being violated, you are actually validating data in two different layers - presentation and business; validation concerns may differ between these two layers.
In your presentation layer you might be concerned with specific elements related to your view, i.e in a web app you might need to return a specific validation message containing a html div so you can properly render an ajax response.
Also forms usually contain persistence related constraints such as not having a certain form field as null or limiting field sizes, while business constraints might be broader, i.e validating if a purchase by an individual in a e-commerce webapp can be allowed by verifying the his past successful purchases.
That said, there are frameworks such as hibernate validator (on java) that allow you to include validation metadata in your business entities that is checked before it is persisted or when you invoke its API to do it so manually. With it you could validate all your constraints in one place.
您所描述的方法对我来说看起来有点过度设计。我可以看到它在理论上是整洁和干净的,但在我看来,在实际情况下映射到数据有点太细粒度,产生不必要的开销和大量的类,这些类在宏伟的方案中几乎没有什么作用事物。当我遇到类似的事情时,它往往会开始闻到一点解决方案蔓延的味道。此外,如果您有很多围绕原语的每个字段包装器,那么您的“AddressLine1”类和“AddressLine2”类等之间很有可能发生 DRY 冲突,或者避免它们所需的过于复杂的继承层次结构。
它就像第六范式——理论上很有趣,但如果你用这种方式编写代码,那么你将需要很长时间才能完成任何事情,并且维护将是一场噩梦。
The approach you are describing looks a little bit over-engineered to me. I can see it being theoretically neat and clean but it seems to me that it would be a bit too granular to map to the data in a practical situation, creating unnecessary overheads and a whole lot of classes that do very little in the grand scheme of things. When I run into things like that it tends to start to smell a little of Solution Sprawl. Also if you have a lot of per-field wrappers around primitives you've got some pretty good chances of DRY violations between your "AddressLine1" class and your "AddressLine2" class and so on or an overcomplicated inheritance heirarchy necessary to avoid them.
It's like the sixth normal form- it's theoretically interesting, but if you wrote your code that way it would take a very long time for you to get anything done and maintenance would be a nightmare.
如果您也使用业务域对象来验证表单(这可以使用相当简单的工具来实现),那么这就消除了大多数基于验证器的解决方案的弊端。在某种程度上,您希望将部分行为从业务域推断到表单域;这应该会减少代码并改善维护,但需要一些额外的接线。我同意罗伯特的观点。我觉得这种方法比Zend/Cake/Ci等更好。它似乎朝着裸对象哲学的方向发展;只需转储 V 和 C,仅选择模型: http://en.wikipedia.org/wiki /Naked_objects
If you use business domain objects to validate the form as well, which can be achieved using rather simple tools, this eliminates the cruft of most validator based solutions. In a way you want to extrapolate partial behaviour from the business domain to the form domain; this should reduce code and improve maintenance at the cost of some extra wiring. I agree with Robert. I feel this approach is better than Zend/Cake/Ci etc. It seems to go in the direction of the naked object philosophy; just dump the V and the C, go for models only: http://en.wikipedia.org/wiki/Naked_objects
在网络上,您可能需要某种客户端验证作为“第一道门” - 检查所需的值和其他简单的验证规则,而不要求用户执行网络请求只是为了查看数据无效。最重要的是,您需要一个服务器端验证层(内置于域对象中、服务层或其他位置)来执行对象属性和其他业务规则的实际验证。
但请注意,依赖于域的验证规则(例如
Name
具有必需的属性FirstName
和LastName
)和纯业务规则(例如例如,如果提供了State
,则Country
必须是USA
)不一定必须位于同一地点。On the web you probably want some kind of client-side validation as a "first gate" - check for required values and other simple validation rules, without requiring the user to perform a web request just to see that the data isn't valid. On top of that, you want a server side validation layer (either built into your domain objects, in a service layer or somewhere else) that performs the actual validation of the object properties, and other business rules.
Note, however, that domain dependent validation rules (for example that a
Name
has the required propertiesFirstName
andLastName
) and pure business rules (for example that if aState
has been provided,Country
must beUSA
) do not necessarily have to be in the same place.在这两个地方进行验证都是多余但必要的。您需要在客户端上进行验证,以便您的用户获得更好的 UI 体验。它还可以减少服务器的负载。您还必须在服务器端进行验证,因为您的应用程序不应信任通过网络传输的任何内容。
Validating in both place IS redundant but necessary. You'll want to validate on the client so that your user has a better UI experience. It also reduces the load on your server. You must also validate on the server side as nothing coming over the wire should be trusted by your app.