In cases like these, I personally use a custom class called Tri
which works like both Try
and Either
:
sealed trait Tri [+Value, +Problem] { ... }
final case class Good[+Value](v: Value) extends Tri[Value, Nothing] { ... }
final case class Bad[+Problem](p: Problem) extends Tri[Nothing, Problem] { ... }
final case class Ugly(th: Throwable) extends Tri[Nothing, Nothing] { ... }
with appropriate methods to handle the most common operations one wants. In this case, I'd simply return to the client
Tri[CarDTO, List[CarCreationFailure]]
and have the exceptions wrapped into a custom exception class as needed. This both is up-front about what may or may not happen when the code itself is working normally, and leaves unstated--as usual--exceptional conditions that need to be handled sooner or later, including things like database errors. Then you just e.g.:
create(car, buyer) match {
case Good(dto) => // Yay
case Bad(xs) => // Handle list of car creation failures
case Ugly(th) => // Handle exceptions
}
I am not aware of any similar functionality in Scalaz7, though you can build the pieces (as you have, though why not use \/
?) more easily than in Scalazless Scala, so you might be less motivated to create this kind of tripartite error handling class.