我已经阅读了一些关于OOP DDD / PoEAA / Gang of Four的书籍,但似乎没有一本书涉及验证主题 - 似乎总是假设数据是有效的。
我从这篇文章(OOP Design Question - Validating properties)的答案中收集到客户端应该只尝试在域对象上设置有效属性值。
这个人提出了一个类似的问题,仍然没有答案:http://bytes.com/topic/php/answers/789086-php-oop-setters-getters-data-validation#post3136182
那么你如何确保它有效? 你是否有每个吸气剂和二传手的“验证方法”?
我似乎缺少一些关于OOP数据验证的关键基础知识 - 你能指点我一本详细介绍这个主题的书吗? - 即。涵盖不同类型的验证/不变量/处理反馈/使用例外与否等
答案 0 :(得分:8)
根据我的经验,验证发生在有人/用户输入的地方。这通常发生在你允许通过你的方法改变某些东西的地方。在你的例子中,我会去验证方法:
setName()
所以它发生在您允许输入值/设置值的地方,结果是 setter方法。
答案 1 :(得分:4)
区分域对象的不变量(必须始终满足)和某些人称之为“contextual validation."”的有效性非常重要。例如,具有负面银行帐户的客户“无效吗?”不,但他们可能无权执行某些类型的交易。这是上下文验证,与“每个客户实体必须具有非空ID”相反,这是完全不同类型的验证
强制不变量的一种有效方法是区分表示用户输入和域对象的类,并且不要在域对象上公开不受限制的mutator(例如简单的set访问器)。
例如,如果您有一个Student
域对象,请不要直接在用户界面中操作它。您的视图不会创建Student
个实例,而是创建StudentBuilder
个实例,这些实例可以模拟构建有效Student
域对象所需的内容。
接下来,您将拥有验证构建器实例符合域对象的不变量的类,以及具有接受构建器并可将其转换为有效域对象的工厂。 (您也可以在此步骤中引入上下文验证策略。)
答案 2 :(得分:2)
每个对象都应确保其内部状态是一致的,因此最好在修改内部状态之前进行验证 - 在对象的setter方法中。
答案 3 :(得分:2)
如果您控制使用您的类的代码,那么您应该在尝试操作对象的变量(通过公共属性)之前进行验证。如果您预计某个场景中您不知道如何使用您的课程,那么您应该在该属性内进行验证,这或多或少是它们的用途。显然,这假定“是有效名称”的定义是对象固有的静态业务规则。
在这两个级别上进行验证当然是最安全的选择。
答案 4 :(得分:2)
OOP的一个重要部分是始终将对象保持在有效状态。因此,应在可以修改对象的输入之后进行验证。
验证从属性/集合,参数到函数和构造函数的数据总是很好。
答案 5 :(得分:2)
这取决于你的编程风格,因为维基百科有更详细的解释,我将抓住表面并链接到维基百科。 (是的,我很懒。: - ))
注意:所有这些都不适用于用户输入。您必须以任何一种方式验证它。我只是在讨论不应该以任何方式与用户输入耦合的业务逻辑类。 : - )
正如其他人所说,您将强制执行每个属性。我经常抛出运行时异常(Java)来指示那些失败。
Wikipedia on Defensive Programming
您记录了代码的要求,并假设,例如,传递给您的setter的值对于定义的合同是有效的。这为您节省了大量的样板代码。但是,当给出非法值时,错误搜寻会更加困难。
答案 6 :(得分:1)
简而言之,始终要验证。总之,一次性完成所有验证,而不是“一路走来”。这将有助于您的代码保持简化并帮助调试混乱。