2017-07-26 9 views
0

私は私のコードをさらに抽象化できると感じていますが、私はちょっと立ち往生しています。私はこれを挑戦としてもっとやっているので、時期尚早の最適化については心配しないでください。私のオープンソースライブラリ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) } 

これらの2つの機能の違いは、単純に返されるタイプです。これについてどうやって行きますか?おそらくより高い 種類を使用していますか?

答えて

1

一つの方法は、ResponseOrderResponseを統一するために、次のようになります。

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

抽象化しなければ、あなたはまだあなたのコードを因数分解することができます

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)}) 
関連する問題