问题
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.flatMapreturns 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.Validationis able to accumulate errors of typeEgiven aSemigroup[E]instance. It's intended for use as anApplicative, like:(fragileFoo |@| fragileBar) { case (foo, bar) => doSomething(foo, bar) }It does have
mapandflatMapmethods, biased towards theSuccessside, so you can use it conveniently in afor-comprehension. However, there is noMonadinstance 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 theRightside). But when used as anApplicative, it doesn't accumulate failures asValidationdoes.util.Tryis 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.Eitherisn'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 theleftorrightprojection 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