当前位置:  开发笔记 > 编程语言 > 正文

业务对象,验证和例外

如何解决《业务对象,验证和例外》经验,为你挑选了4个好方法。

我一直在阅读有关例外及其使用的一些问题和答案.似乎是一种强烈的观点,即只应针对异常,未处理的案例提出例外.这让我想知道验证如何与业务对象一起工作.

假设我有一个业务对象,其中包含对象属性的getter/setter.假设我需要验证该值是否介于10和20之间.这是一个业务规则,因此它属于我的业务对象.所以这似乎意味着我的验证码在我的二传手中.现在我将UI数据绑定到数据对象的属性.用户输入5,因此规则需要失败,并且不允许用户移出文本框..UI被数据绑定到属性,因此将调用setter,规则检查并失败.如果我从业务对象中引发异常以说规则失败,则UI会选择该规则.但这似乎违背了例外的首选用法.鉴于它是一个制定者,你实际上并不会对setter产生"结果".

那么验证应该如何运作呢?

编辑:我可能在这里使用了一个过于简化的例子.上面的范围检查之类的东西可以通过UI轻松处理,但是如果valdation更复杂,例如业务对象根据输入计算数字,如果计算出的数字超出范围,则应该重新注入.这是更复杂的逻辑,不应该在UI中.

还可以考虑根据已输入的字段输入的其他数据.例如,我必须在订单上输入一个项目以获得某些信息,例如库存,当前成本等.用户可能要求此信息做出进一步进入的决定(请说明订购了多少个单位)或者可能需要订购进一步验证.如果该项目无效,用户是否应该能够输入其他字段?重点是什么?



1> Mac..:

您想深入了解Paul Stovell关于数据验证的出色工作.他在本文中一次总结了他的想法.我碰巧在这个问题上分享了他的观点,我在自己的库中实现了这个观点.

用Paul的话来说,这就是在setter中抛出异常的缺点(基于一个Name属性不应为空的样本):

有时您可能需要一个空名称.例如,作为"创建帐户"表单的默认值.

如果您在保存之前依赖于此来验证任何数据,那么您将错过数据已经无效的情况.我的意思是,如果您使用空名称从数据库加载帐户并且不更改它,您可能永远不会知道它是无效的.

如果您不使用数据绑定,则必须使用try/catch块编写大量代码以向用户显示这些错误.当用户填写表单时,尝试在表单上显示错误变得非常困难.

我不喜欢为非特殊事物抛出异常.将帐户名称设置为"Supercalafragilisticexpialadocious"的用户也不例外,这是一个错误.当然,这是个人的事情.

这使得很难获得所有已经破坏的规则的列表.例如,在某些网站上,您将看到验证消息,例如"必须输入名称.必须输入地址.必须输入电子邮件".要显示它,你将需要很多try/catch块.

以下是替代解决方案的基本规则:

    拥有无效的业务对象没有任何问题,只要您不尝试持久化它.

    应该可以从业务对象中检索任何和所有损坏的规则,以便数据绑定以及您自己的代码可以查看是否存在错误并适当地处理它们.


对于支持`IDataErrorInfo`进行自动验证的复杂(无异常)验证方法的特定代码解决方案,请尝试以下方法:http://stackoverflow.com/questions/1721327/validate-object-based-on-external-factors - 即,数据存储唯一性/ 1741831#1741831

2> Mike Thompso..:

假设您有单独的验证和持久化(即保存到数据库)代码,我会执行以下操作:

    UI应该执行验证.不要在这里抛出异常.您可以提醒用户注意错误并阻止保存记录.

    您的数据库保存代码应该为坏数据抛出无效的参数异常.这样做是有道理的,因为此时您无法继续进行数据库写入.理想情况下,这应该永远不会发生,因为UI应该阻止用户保存,但您仍然需要它来确保数据库的一致性.此外,您可能从UI以外的其他内容(例如批量更新)调用此代码,其中没有UI数据验证.


好点子.用户界面不应该将其视为例外,因为用户只是一个无害的错误,但数据访问层*应该*,因为它应该永远不会那么远.

3> jeremcc..:

我一直是Rocky Lhotka在CSLA框架中的方法的粉丝(正如查尔斯所提到的).通常,无论是由setter驱动还是通过调用显式Validate方法,BrokenRule对象的集合都由业务对象在内部维护.UI只需要检查对象上的IsValid方法,然后检查BrokenRules的数量,并适当地处理它.或者,您可以轻松地使用Validate方法引发UI可以处理的事件(可能是更干净的方法).您还可以使用BrokenRules列表以摘要形式或相应字段旁边显示错误消息.尽管CSLA框架是用.NET编写的,但整体方法可以用于任何语言.

在这种情况下,我不认为抛出异常是最好的主意.我绝对遵循思想学派的观点,即异常应该是针对特殊情况,而简单的验证错误则不然.在我看来,提升OnValidationFailed事件将是更清洁的选择.

顺便说一句,我从来不喜欢在用户处于无效状态时不让用户离开的想法.在返回并修复无效字段之前,有许多情况可能需要暂时离开现场(可能先设置其他字段).我认为这只是一种不必要的不​​便.



4> Charles Grah..:

您可能希望在getter和setter之外移动验证.您可以拥有一个名为IsValid的函数或属性来运行所有验证规则.t将使用所有"Broken Rules"填充字典或散列表.此字典将暴露给外部世界,您可以使用它来填充错误消息.

这是CSLA.Net采用的方法.

推荐阅读
低调pasta_730
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有