首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Scalaz 7在Scala中验证类的内聚方法

使用Scalaz 7在Scala中验证类的内聚方法
EN

Stack Overflow用户
提问于 2013-05-05 16:14:49
回答 1查看 724关注 0票数 3

我的目标是在创建一个有效的User实例之前,在objectapply方法中验证User的字段:

代码语言:javascript
复制
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):

代码语言:javascript
复制
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
    }
  }
}

我所期望的只是返回以下代码片段:

代码语言:javascript
复制
(checkForUserName ⊛ checkForPassword)

并将适当的结果引入到我的User类中,允许通过以下操作创建有效实例:

代码语言:javascript
复制
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和保持这种验证机制?

-----UPDATE

正如@Travis所提到的,为我的UserValidator使用外部class的意图可能看起来很奇怪。实际上,我希望验证器是可模拟的,因此,我不得不在trait/abstract class上使用组合。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-05 20:34:31

我不知道为什么首先需要一个专用的UserValidator类。在这种情况下,我更有可能将我所有的通用验证代码绑定到一个单独的特性中,并让我的User伙伴对象(或者我想要负责创建User实例的任何其他部分)扩展该特性。下面是一个简短的草图:

代码语言:javascript
复制
import scalaz._, Scalaz._

trait Validator[E] {
  def checkNonEmpty(error: E)(s: String): ValidationNel[E, String] =
    if (s.isEmpty) error.failNel else s.successNel
}

sealed trait UserCreationFailure
case object EmptyPassword extends UserCreationFailure
case object EmptyUsername extends UserCreationFailure

case class User(name: String, pass: String)

object User extends Validator[UserCreationFailure] {
  def validated(
    name: String,
    pass: String
  ): ValidationNel[UserCreationFailure, User] = (
    checkNonEmpty(EmptyUsername)(name) |@| checkNonEmpty(EmptyPassword)(pass)
  )(apply)
}

然后:

代码语言:javascript
复制
scala> println(User.validated("", ""))
Failure(NonEmptyList(EmptyUsername, EmptyPassword))

scala> println(User.validated("a", ""))
Failure(NonEmptyList(EmptyPassword))

scala> println(User.validated("", "b"))
Failure(NonEmptyList(EmptyUsername))

scala> println(User.validated("a", "b"))
Success(User(a,b))

如果您有大量的User-specific验证逻辑,并且不希望污染您的User对象,那么我想您可以将其分解为一个UserValidator特性,该特性将扩展您的通用Validator并由User扩展。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16386513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档