2013-02-27 10 views
6

Assumiamo un oggetto costruito utilizzando un modello di builder.Il modo migliore per gestire la convalida dei campi dell'oggetto => O/Prova (scala 2.10)/ValidationNEL (scalaz)

Questo modello di builder conterrà un metodo build che si concentra sulla convalida dei campi e quindi sulla conversione nel tipo di destinazione.

La convalida potrebbe essere implementato usando:

  • Either[FailureObject, TargetObject] tipo
  • Try[TargetObject] (nuova funzione da Scala 2.10)
  • Validation[FailureObject, TargetObject] o ValidationNEL[FailureObject, TargetObject] dalla libreria scalaz

ho letto che uno dei i principali vantaggi del tipo Validation su è quello Validation può accumulare guasti "out of the box".

Ma che dire del "nuovo" modo Try? Ho notato che Try dispone anche di metodi "monadici", come map, flatMap ecc., Cosa mancava davvero in entrambi i casi senza l'aiuto di Projection.

Pertanto, immagino che ciascun metodo di convalida dei campi restituisca un valore Try[FieldType] e, più precisamente, in caso di errore, uno Try[SpecificFieldExceptionType]; questo campo nidificato contenente un campo di messaggio String e un campo rootCause che è possibile accumulare in tutto il metodo build.

Utilizzare Scala 2.10, potrebbe o dovrebbe Try sostituire la libreria di convalida scalaz per la convalida semplice come il modello di builder comporta?

** EDIT * ***

Leggendo Try codice sorgente, suona che Try non possono accumulare diverse eccezioni e quindi è orientato fail-fast. Anche Try.flatMap restituisce il potentential fallimento precedente e quindi non ha il concetto di accumulo:

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

Al contrario di ValidationNEL che gestisce funzione di accumulo.

Qualche conferma?

risposta

11

Non ci sono compromessi:

  • scalaz.Validation è in grado di accumulare errori di tipo E dato un esempio Semigroup[E]. E 'destinato ad essere utilizzato come Applicative, come:

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

    Essa ha ancora map e flatMap metodi, sbilanciato verso il lato Success, in modo da poter utilizzare convenientemente in un for -comprehension.Tuttavia, non esiste un'istanza Monad definita per esso, quindi non può essere utilizzata in alcun materiale di ordine superiore (ad esempio, non è possibile utilizzarlo con i trasformatori monad). Questa lacuna non sembra che sarebbe un problema per te, però.

  • scalaz.\/, che lei non ha citato, si forma un Monad (ancora una volta, polarizzato verso il lato Right). Ma quando viene utilizzato come Applicative, non accumula errori come fa Validation.

  • util.Try è simile a scalaz.\/, specializzato in Throwable. Sebbene manchi nuovamente l'accumulo di errori, ha la nozione di recupero degli errori. Tuttavia, per il tuo caso di utilizzo del "builder pattern", sembra che questo potrebbe non essere terribilmente utile.

  • Infine, util.Either non è da prendere in considerazione, rispetto alle altre tre opzioni: perché non è sbilanciata verso una parte o dall'altra, è necessario in modo esplicito e coerente chiedere per la proiezione left o right ogni volta che si desidera fai qualcosa di monadico.

La mia ipotesi migliore è che per la vostra situazione, scalaz.Validation è la scelta più appropriata.

+0

Impossibile immaginare una risposta migliore => molto ben spiegato! Grazie mille :) Effettivamente, ho scelto Validation per lavorare con il mio Builder. – Mik378

+0

@ Mik378 grazie! – mergeconflict

Problemi correlati