Scala Cats를 활용하여 데이터베이스 액세스 코드 개선

익숙한 것부터 시작하겠습니다. 한동안 scala로 작업했다면 아마도 scala.concurrent.Future#sequencescala.concurrent.Future#traverse 를 접했을 것입니다.

다음은 이 두 메서드의 간소화된 메서드 시그니처입니다.

def traverse[A, B](items: Seq[A])(f: A => Future[B]): Future[Seq[B]]
def sequence[A](items: Seq[Future[A]]): Future[Seq[A]]

cats.Traverse는 연산scala.concurrent.Future#traverse을 구현하는 추상화이지만 더 일반적입니다. 함수 인수 유형A 및 반환 유형B 외에도 SeqFuture의 컨텍스트 유형이 더 일반화되었습니다.

trait Traverse[F[_]] {
  def traverse[G[_], A, B](fa: F[A])(f: A => G[B]): G[F[B]]
}


데이터베이스 액세스를 위해 slick 의 최신 버전을 사용하는 경우 DBIO 에 익숙할 것입니다. 일종의 컬렉션이 있고 컬렉션의 각 요소에 대해 데이터베이스 작업을 실행하려는 경우가 종종 있습니다.DBIOFuture와 다소 유사하므로 다음과 같이 작성할 수 있습니다.

def f[A](a:A): DBIO[B] = ???

val b: DBIO[Seq[B]] = DBIO.sequence(items.map(f))


또는 문서 인식이 부족하면 결국 다음과 같이 작성하게 될 수 있습니다.

items.foldLeft(DBIO.successful(Seq()) {
  (acc, next) => acc.flatMap(a => f(next).map(i => acc :+ i)
}


그러나 slickcats를 활용하면 다음과 같이 간단하게 작성할 수 있습니다.

items.traverse(f)


그러나 적절한 종속성 없이 이 접근 방식을 사용하려고 하면 컴파일러에서 DBIO 에 대한 암시적 인스턴스 누락에 대해 불평하는 것을 볼 수 있습니다.

이를 수정하려면 다음 종속성을 추가해야 합니다.
https://github.com/RMSone/slick-cats
클래스에 다음 가져오기를 추가합니다.

import com.rms.miu.slickcats.DBIOInstances._


함수형 프로그래밍 여정에서 얼마나 멀리 있는지에 따라 cats.Traverse가 단일 유형 인수가 있는 유형 생성자를 필요로 하는 특별한 종류의 functor라는 것을 알게 될 것입니다.
slickcats와 함께 사용하려는 메서드가 DBIOAction[+R, +S <: NoStream, -E <: Effect] 또는 둘 이상의 유형 매개 변수가 있는 다른 관련 유형을 반환하는 경우 컴파일러에서 불평합니다. 이러한 상황에서는 메서드 시그니처를 DBIO로 변경하거나 명시적으로 DBIO로 캐스팅하여 컴파일러를 약간 도와야 합니다.

이것은 단지 예일 뿐입니다. slickcats에는 더 읽기 쉬운 데이터베이스 액세스 코드를 작성하는 데 도움이 되는 typeclass 인스턴스가 있습니다.

좋은 웹페이지 즐겨찾기