处理对象字段验证的最佳方法=>要么/尝试(scala 2.10)/ ValidationNEL(scalaz)

Mik*_*378 6 scala exception-handling builder-pattern scalaz7

让我们假设一个使用构建器模式构造的对象.

此构建器模式将包含一个build侧重于字段验证然后转换为目标类型的方法.

可以使用以下方式实现此验证:

  • Either[FailureObject, TargetObject] 类型
  • Try[TargetObject] (Scala 2.10的新功能)
  • Validation[FailureObject, TargetObject]或者ValidationNEL[FailureObject, TargetObject]来自scalaz图书馆

我读到Validation过度Either类型的一个主要优点是Validation可以"开箱即用"累积故障.

但那"新" Try方式呢?我注意到,Try有"一元"的方法开箱也是一样的map,flatMap等...什么是真正与任何一种类型的不帮助失踪Projection.

因此,我想象每个字段验证方法返回a Try[FieldType],更确切地说,在任何失败的情况下,a Try[SpecificFieldExceptionType]; 这个嵌套的包含String消息字段和rootCause字段,可以在整个build方法中累积.

使用Scala 2.10,可以或应该Try练习替换scalaz验证库以进行简单验证,例如构建器模式涉及吗?

**编辑****

通过阅读Try源代码,它听起来Try不能累积多个异常,因此面向失败快速.甚至Try.flatMap返回可能的先前失败,因此没有积累的概念:

def flatMap[U](f: T => Try[U]): Try[U] = this.asInstanceOf[Try[U]]
Run Code Online (Sandbox Code Playgroud)

相反ValidationNEL,处理累积功能.

任何确认?

mer*_*ict 11

有权衡:

  • scalaz.Validation能够累积E给定Semigroup[E]实例的类型错误.它的目的是用作Applicative:

    (fragileFoo |@| fragileBar) { case (foo, bar) => doSomething(foo, bar) }
    
    Run Code Online (Sandbox Code Playgroud)

    它确实有mapflatMap方法,对偏向Success一侧,这样你就可以在方便地使用它for-comprehension.但是,没有Monad为它定义实例,因此它不能用于任何高阶内容(例如,您不能将它与monad变换器一起使用).不过,这个缺点对你来说似乎不是一个问题.

  • scalaz.\/,你没有提到,确实形成了一个Monad(再次偏向Right一边).但是当用作Applicative它时,它不会像过滤那样累积失败Validation.

  • util.Try类似于scalaz.\/,专门用于Throwable.虽然它再次缺乏错误累积,但它确实具有错误恢复的概念.但是,对于"构建器模式"用例,似乎这可能不是非常有用.

  • 最后,util.Either与其他三个选项相比,不值得考虑:因为它不偏向于一方或另一方,所以每次想要做一些monadic时,你必须明确而一致地要求leftright投射.

我最好的猜测是,对于你的情况,scalaz.Validation是最合适的选择.