我的目标是在创建一个有效实例之前验证'方法User
中的字段:object
apply
User
case class User(String userName, String password)
object User {
def apply(userValidator: UserValidator): ValidationNel[UserCreationFailure, User] = {
//call UserValidator's validate() method here and initialize effective User instance.
}
}
我选择使用Validation
from Scalaz7来积累潜在的非法参数/错误。
以下代码中的一个缺点是 Scalaz7 API 强制我让验证器自己创建实例。但是,通过遵循单一责任原则,这显然不是它的作用。它的作用只是验证字段并返回一些错误列表。
让我们首先展示我的实际代码(作为参考,Empty****
对象只是一些case object
扩展UserCreationFailure
):
class UserValidator(val userName: String, val password: String)
extends CommonValidator[UserCreationFailure] {
def validate(): ValidationNel[UserCreationFailure, User] = {
(checkForUserName ⊛
checkForPassword)((userName, password) => new User(userName, password)
}
private def checkForUserName: ValidationNel[UserCreationFailure, String] = {
checkForNonEmptyString(userName) {
EmptyUserName
}
}
def checkForPassword: ValidationNel[UserCreationFailure, String] = {
checkForNonEmptyString(password) {
EmptyPassword
}
}
}
我所期望的只是返回这个片段代码:
(checkForUserName ⊛ checkForPassword)
并将适当的结果带入我的User
班级,允许通过执行以下操作创建有效的实例:
def apply(userValidator: UserValidator): ValidationNel[UserCreationFailure, User] = {
userValidator(username, password).validate()((userName, password)(new User(userName, password))
}
事实上,它对 SRP 会更友好。
但(checkForUserName ⊛ checkForPassword)
返回一个完全private
类型的类型:
private[scalaz] trait ApplicativeBuilder[M[_], A, B]
,
因此我不知道class
返回的类型。
因此,我被迫直接将用户的创建与它相关联。
我怎样才能保留 SRP 并保留此验证机制?
-----更新----
class
正如@Travis Brown 所提到的,为我使用外部设备的意图UserValidator
可能看起来很奇怪。实际上,我希望验证器是可模拟的,因此,我不得不在trait
/上使用组合abstract class
。