2013-02-27 21 views
6

Giả sử một đối tượng được xây dựng bằng cách sử dụng một mẫu trình xây dựng.Cách tốt nhất để xử lý các trường của đối tượng xác nhận => Hoặc/Thử (scala 2.10)/ValidationNEL (scalaz)

Mẫu trình xây dựng này sẽ chứa phương pháp build tập trung vào xác thực trường và sau đó chuyển sang loại được nhắm mục tiêu.

xác nhận này có thể được thực hiện bằng:

  • Either[FailureObject, TargetObject] loại
  • Try[TargetObject] (Tính năng mới từ Scala 2,10)
  • Validation[FailureObject, TargetObject] hoặc ValidationNEL[FailureObject, TargetObject] từ thư viện scalaz

tôi đọc rằng một trong những những lợi thế chính của Validation trên Either loại là Validation có thể tích lũy thất bại "ngoài hộp".

Nhưng còn cách "mới" Try thì sao? Tôi nhận thấy rằng Try có các phương pháp "đơn thuần" ra khỏi hộp cũng như map, flatMap v.v ... những gì đã thực sự bị thiếu với cả hai loại mà không có sự trợ giúp của Projection.

Vì vậy, tôi muốn hình dung từng phương thức xác thực trường trả về Try[FieldType] và chính xác hơn, trong trường hợp có lỗi, Try[SpecificFieldExceptionType]; cái lồng nhau này chứa trường thông báo String và trường gốcCó thể được tích lũy trong phương thức build.

Sử dụng Scala 2.10, có thể hoặc nên Try thực hành thay thế thư viện xác thực scalaz để xác thực đơn giản như mẫu trình xây dựng liên quan?

** EDIT * ***

Bằng cách đọc Try mã nguồn, nó có vẻ rằng Try không thể tích lũy nhiều trường hợp ngoại lệ và do đó được định hướng thất bại nhanh. Thậm chí Try.flatMap trả về thất bại trước potentential và do đó không có khái niệm về sự tích lũy:

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

Trên trái của ValidationNEL để xử lý tính năng tích lũy.

Mọi xác nhận?

Trả lời

11

Có cân bằng:

  • scalaz.Validation có khả năng tích lũy lỗi kiểu E được đưa ra một ví dụ Semigroup[E]. Nó dành cho sử dụng như một Applicative, như:

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

    Nó có mapflatMap phương pháp, thiên vị về phía Success bên, vì vậy bạn có thể sử dụng thuận tiện trong một -comprehension for.Tuy nhiên, không có trường hợp Monad được xác định cho nó, vì vậy nó không thể được sử dụng trong bất kỳ thứ gì cao hơn (ví dụ, bạn không thể sử dụng nó với máy biến áp đơn nguyên). Sự thiếu sót này dường như không phải là vấn đề đối với bạn.

  • scalaz.\/, mà bạn không đề cập, tạo thành một Monad (một lần nữa, thiên vị về phía Right). Nhưng khi được sử dụng như là một Applicative, nó không tích lũy thất bại như Validation.

  • util.Try tương tự như scalaz.\/, chuyên Throwable. Mặc dù một lần nữa thiếu sự tích tụ của các lỗi, nó có khái niệm phục hồi lỗi. Tuy nhiên, đối với trường hợp sử dụng "mẫu xây dựng" của bạn, có vẻ như điều này có thể không hữu ích khủng khiếp.

  • Cuối cùng, util.Either là không đáng kể, so với ba lựa chọn khác: vì nó không thiên về một bên này hay cách khác, bạn phải rõ ràng và nhất quán yêu cầu chiếu left hoặc right mỗi khi bạn muốn làm một cái gì đó monadic.

Tôi đoán tốt nhất là trong trường hợp của bạn, scalaz.Validation là lựa chọn thích hợp nhất.

+0

Không thể tưởng tượng ra câu trả lời hay hơn => được giải thích rất tốt! Cảm ơn rất nhiều :) Thật vậy, tôi đã chọn Validation để làm việc với Builder của tôi. – Mik378

+0

@ Mik378 cảm ơn bạn! – mergeconflict

Các vấn đề liên quan