正如您在下面看到的,在构造函数中我实例化了一个验证对象,因此我可以在set方法中验证用户的电子邮件.这种架构是最佳实践还是有缺陷的?我可以避免让我的User类直接依赖于我的Validation类吗?
Class User { Private Email //constructor User() { Validation = new Validation } SetEmail(NewValue) { if (Validation.isEmail(NewValue)) { Email = NewValue } }
还有一个相关的问题:当set方法收到无效值时,什么是正确的响应?我看到2个选项
不要设置值并返回false
无论如何设置值,但为对象设置error属性.(如果设置了User.Error,我知道出了问题)
我怀疑#1是最佳实践,因为您可以确保任何对象属性的值始终有效.正确?
到目前为止,这些建议似乎都有点矫枉过正,特别是对于所有IOC和AOP的东西.
该User
类别需要一个电子邮件地址,以便创建一个EmailAddress
类,并有User
一流的接受通过属性和/或它的构造之一.该验证可以像输入EmailAddress
引用是否为空一样简单.
本EmailAddress
类可以是简单的,但一般可重用的实现(考虑基于此的RFC文档).它应该是不可变的,并且应该在无效输入上从其构造函数中抛出异常.
理想情况下,EmailAddress
类应该由一个EmailUserId
类(基于RFC?)和一个InternetDomain
类(基于RFC?)组成,因为电子邮件地址是一个复合数据结构.同样,这些类中的每一个都应该管理不可变实例,并且应该在构造中使用无效输入抛出异常.
"验证"对我来说不是一个"事物",而是一个通用的"行动".因此,它有助于成为一种方法而不是一种类.在这种情况下,我倾向于在每个类中实现验证,作为valid(input)
从构造函数调用的私有静态方法(),使用Java或C#等语言.通常,以问题(isValid(input)
)的形式公开该功能变得有用.
编辑:
您是否建议我需要验证的每种不同数据类型都应该拥有自己的类?
这是解决问题的一种可靠方法,通常称为价值类型(感谢提醒,弗兰克).其结果将是几个(打或两个)良好定义的,可重复使用的类,如也许EmailAddress
,PhoneNumber
,PersonName
等所提出的另一种方法是可能导致"神类"用的功能性的混合物,该混合物是不能重复使用,不容易测试,难以维护.
还有其他方法可以对解决方案进行分区,但我的建议确实具有成熟,易于理解和与大量可靠设计原则相一致的优势.我肯定会在尝试发明你自己之前尝试一下.