2013-02-27 21 views
6

Załóżmy obiekt skonstruowany przy użyciu wzorca budowniczego.Najlepszy sposób na sprawdzanie poprawności pól obiektu => Albo/Try (scala 2.10)/ValidationNEL (scalaz)

Ten wzorzec budowniczy zawierałby metodę build skupiającą się na walidacji pól, a następnie na konwersji na typ docelowy.

Walidacja ta może być realizowana za pomocą:

  • Either[FailureObject, TargetObject] type
  • Try[TargetObject] (nową funkcję od Scala 2.10)
  • Validation[FailureObject, TargetObject] lub ValidationNEL[FailureObject, TargetObject] z biblioteki scalaz

czytałem, że jeden z głównymi zaletami Validation w stosunku do typu Either jest to, że Validation może akumulować awarie "po wyjęciu z pudełka".

Ale co z "nowym" sposobem na Try? Zauważyłem, że Try ma również "monadyczne" metody, takie jak: map, flatMap itp ... tego, czego naprawdę brakowało w każdym typie bez pomocy Projection.

Tak więc, wyobrażam sobie, że każda metoda walidacji pola zwraca Try[FieldType], a dokładniej, w przypadku jakiejkolwiek awarii, Try[SpecificFieldExceptionType]; to pole zagnieżdżone zawierające pole komunikatu String i pole rootCause, które może być nagromadzone w metodzie build.

Korzystanie z Scala 2.10, może lub powinno być Try Praktyka zastąpić biblioteki sprawdzania poprawności skalaz do prostego sprawdzania poprawności, jak wzór konstruktora obejmuje?

** EDIT * ***

Czytając Try kodu źródłowego, to brzmi, że Try nie mogą gromadzić liczne wyjątki, a zatem nie jest zorientowany szybki. Nawet Try.flatMap zwraca potentential poprzednią porażkę i tak nie mają pojęcia Akumulacja:

def flatMap[U](f: T => Try[U]): Try[U] = this.asInstanceOf[Try[U]] 

przeciwnie do ValidationNEL, który obsługuje funkcję akumulacji.

Jakieś potwierdzenie?

Odpowiedz

11

Są kompromisy:

  • scalaz.Validation jest w stanie zgromadzić błędy typu E dana instancja Semigroup[E]. Jest on przeznaczony do stosowania jako Applicative, jak:

    (fragileFoo |@| fragileBar) { case (foo, bar) => doSomething(foo, bar) } 
    

    to ma map i flatMap metod zorientowaną na stronie Success, więc można go używać wygodnie w for -comprehension.Jednak nie ma zdefiniowanej dla niego instancji Monad, więc nie można jej używać w żadnych obiektach wyższego rzędu (na przykład nie można jej używać z transformatorami monad). To niedociągnięcie nie wydaje się być dla ciebie problemem.

  • , o której nie wspomniałeś, tworzy się Monad (ponownie, stronniczy w stronę Right). Ale kiedy jest używany jako Applicative, nie kumuluje błędów jako Validation.

  • jest podobna do scalaz.\/, specjalizuje się w Throwable. Mimo, że znowu nie ma w nim nagromadzonych błędów, ma on pojęcie odzyskiwania po błędzie. Jednak w przypadku użycia wzorca "wzorca budowania" wydaje się, że może to nie być zbyt użyteczne.

  • Wreszcie util.Either nie warto zastanowić się, w porównaniu do pozostałych trzech opcji: bo nie jest stronniczy w kierunku jednej lub drugiej strony, trzeba wyraźnie i konsekwentnie prosić o projekcji left lub right każdym razem, gdy chcesz zrób coś monadycznego.

Zgaduję, że najodpowiedniejszym wyborem w tej sytuacji jest scalaz.Validation.

+0

Nie można sobie wyobrazić lepszej odpowiedzi => bardzo dobrze wyjaśnione! Wielkie dzięki :) Rzeczywiście, wybrałem walidację do pracy z moim konstruktorem. – Mik378

+0

@ Mik378 dziękuję! – mergeconflict