问题
Let's assume an object constructed using a builder pattern.
This builder pattern would contain a build
method focusing on fields validation and then on conversion to the targeted type.
This validation could be implemented using:
Either[FailureObject, TargetObject]
typeTry[TargetObject]
(new feature from Scala 2.10)Validation[FailureObject, TargetObject]
orValidationNEL[FailureObject, TargetObject]
from scalaz library
I read that one of the main advantages of Validation
over Either
type is that Validation
can accumulate failures "out of the box".
But what about the "new" Try
way? I noticed that Try
has "monadic" methods out of the box also, like map
, flatMap
etc... what was really missing with Either type without help of Projection
.
Thus, I'd imagine each field validation method returning a Try[FieldType]
and more precisely, in case of any failure, a Try[SpecificFieldExceptionType]
; this nested one containing a String
message field and a rootCause field that could be accumulated throughout the build
method.
Using Scala 2.10, could or should Try
practice replace scalaz validation library for simple validation like builder pattern involves?
**EDIT ****
By reading Try
source code, it sounds that Try
can't accumulate several exceptions and thus is oriented fail-fast.
Even Try.flatMap
returns the potentential previous failure and so doesn't have the notion of accumulation:
def flatMap[U](f: T => Try[U]): Try[U] = this.asInstanceOf[Try[U]]
On the contrary of ValidationNEL
that handles accumulation feature.
Any confirmation?
回答1:
There are tradeoffs:
scalaz.Validation
is able to accumulate errors of typeE
given aSemigroup[E]
instance. It's intended for use as anApplicative
, like:(fragileFoo |@| fragileBar) { case (foo, bar) => doSomething(foo, bar) }
It does have
map
andflatMap
methods, biased towards theSuccess
side, so you can use it conveniently in afor
-comprehension. However, there is noMonad
instance defined for it, so it can't be used in any higher-order stuff (for example, you can't use it with monad transformers). This shortcoming doesn't seem like it would be a problem for you, though.scalaz.\/
, which you didn't mention, does form aMonad
(again, biased toward theRight
side). But when used as anApplicative
, it doesn't accumulate failures asValidation
does.util.Try
is similar toscalaz.\/
, specialized toThrowable
. Although it again lacks accumulation of errors, it does have the notion of error recovery. However, for your "builder pattern" use case, it seems like this might not be terribly useful.Finally,
util.Either
isn't worth considering, compared to the other three options: because it's not biased toward one side or the other, you have to explicitly and consistently ask for theleft
orright
projection every time you want to do something monadic.
My best guess is that for your situation, scalaz.Validation
is the most appropriate choice.
来源:https://stackoverflow.com/questions/15119821/best-way-to-handle-objects-fields-validation-either-try-scala-2-10-val