我觉得我可以进一步抽象我的代码,但我有点卡住了。我这样做更像是一个挑战,所以不要担心过早优化。这是我的开源库Reactive Kraken。
如果你看一下这段代码,我相信你会理解我的意思。
case class Response[T](error: List[String], result: Option[Map[String, T]])
case class OrderResponse[T](error: List[String], result: Option[T])
def handleRequest[T: JsonFormat](request: HttpRequest): Future[Response[T]] =
fireRequest(request)
.map(_.parseJson.convertTo[Response[T]])
.recover { case t: Throwable => Response[T](List(t.getMessage), None) }
def handleOrderRequest[A: JsonFormat](request: HttpRequest): Future[OrderResponse[A]] =
fireRequest(request)
.map(_.parseJson.convertTo[OrderResponse[A]])
.recover { case t: Throwable => OrderResponse[A](List(t.getMessage), None) }
这两个函数之间的区别仅仅是它们返回的类型。你会怎么做?也许使用更高 kinded类型?
答案 0 :(得分:1)
一种方法是统一Response
和OrderResponse
:
case class Response[T] (error: List[String], result: Option[Map[String, T]])
case class OrderResponse[T](error: List[String], result: Option[T])
// ===
type Response[T] = OrderResponse[Map[String, T]]
case class OrderResponse[T](error: List[String], result: Option[T])
然后OrderResponse
上的函数也是Response
上的函数。但是,我不知道这些类型的语义。
如果不满意,类型类将会:
trait Recovering[T] {
def recover(error: Throwable): T
}
object Recovering {
def apply[T: Recovering] = implicitly[Recovering[T]]
}
implicit def requestsAreRecovering[T]: Recovering[Request[T]] = new Recovering[Request[T]] {
override def recover(error: Throwable) = Request[T](List(t.getMessage), None)
}
implicit def orderRequestsAreRecovering[T]: Recovering[OrderRequest[T]] = new Recovering[OrderRequest[T]] {
override def recover(error: Throwable) = OrderRequest[T](List(t.getMessage), None)
}
def handleRequest[T: JsonFormat: Recovering](request: HttpRequest): Future[T] =
fireRequest(request)
.map(_.parseJson.convertTo[T])
.recover(Recovering[T].recover)
答案 1 :(得分:1)
如果没有抽象,您仍然可以对代码进行分解:
case class Response[T](error: List[String], result: Option[Map[String, T]])
case class OrderResponse[T](error: List[String], result: Option[T])
private def handle[T: JsonFormat, U](request: HttpRequest, recovery: Throwable => U): Future[U] = {
fireRequest(request)
.map(_.parseJson.convertTo[U])
.recover { case t: Throwable => recovery(t) }
}
def handleRequest[T: JsonFormat](request: HttpRequest): Future[Response[T]] =
handle(request, {t: Throwable => Response[T](List(t.getMessage), None)})
def handleOrderRequest[T: JsonFormat](request: HttpRequest): Future[Response[T]] =
handle(request, {t: Throwable => OrderResponse[A](List(t.getMessage), None)})