Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * My application is splitted in several modules, possibly independently built and
- * distributed.
- * I have a Base error trait for the whole application.
- *
- * Each module has its own business error defined by a module base error trait which
- * extends BaseError.
- *
- * I want to have a common framework to manage bridging errors between modules so
- * that a module can use the other ones and subsume error type to its own, especially
- * in the canonical exemple:
- *
- * ```
- * for {
- * a <- module1
- * b <- module2
- * } yield {
- * ...
- * } : error of kind module 3
- * ```
- *
- * The bridging could be done with a "chain" error kind that encapsulated one error module
- * in an other: `ErrorModule2.Chain("some explanation", errorModule1)`
- *
- * Finally, I want minimum boilerplate for that. How is it usually done?
- */
- object errors {
- trait BaseError {
- def msg: String
- }
- trait BaseChainError[E <: BaseError] extends BaseError {
- def cause: E
- def hint: String
- def msg = s"${hint}; cause was: ${cause.getClass.getSimpleName}: ${cause.msg}"
- }
- }
- object TestImplicits {
- import scalaz.zio._
- import scalaz.zio.syntax._
- object module1 {
- import com.normation.errors._
- sealed trait M_1_Error extends BaseError
- object M_1_Error {
- final case class BusinessError1(msg: String) extends M_1_Error
- final case class Chained[E <: BaseError](hint: String, cause: E) extends M_1_Error with BaseChainError[E]
- }
- object M_1_Result {
- // implicits ?
- }
- object service1 {
- def doStuff(param: String): IO[M_1_Error, String] = param.succeed
- }
- }
- object module2 {
- import com.normation.errors._
- sealed trait M_2_Error extends BaseError
- object M_2_Error {
- final case class MissingImportantStuff(msg: String) extends M_2_Error
- final case class Chained[E <: BaseError](hint: String, cause: E) extends M_2_Error with BaseChainError[E]
- }
- object M_2_Result {
- // implicits
- }
- object service2 {
- def doStuff(param: Int): IO[M_2_Error, Int] = param.succeed
- }
- }
- object testModule {
- import module1._
- import module2._
- import com.normation.errors._
- sealed trait M_3_Error extends BaseError
- object M_3_Error {
- final case class Oups(msg: String) extends M_3_Error
- final case class Chained[E <: BaseError](hint: String, cause: E) extends M_3_Error with BaseChainError[E]
- }
- object M_3_Result {
- // implicits ?
- }
- import module1.M_1_Result._
- import module2.M_2_Result._
- import M_3_Result._
- /*
- * I would like all of that to be possible, with the minimum boilerplate,
- * and the maximum homogeneity between modules
- */
- object service {
- // need error adpatation 1 toward 2
- def test0(a: String): IO[M_2_Error, Int] = service1.doStuff(a)
- // need error adpatation 1 toward 3
- def test1(a: String): IO[M_3_Error, Int] = service1.doStuff(a)
- // need error adpatation 1 and 2 toward 3
- def test2(a: String, b: Int): IO[M_3_Error, (String, Int)] = {
- for {
- x <- service1.doStuff(a)
- y <- service2.doStuff(b)
- } yield {
- (x, y)
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement