-
ZLayer module pattern 을 이용한 dependency injectionzio/zio1 2021. 8. 18. 17:44
문제
zio module pattern 1.0 은 쓸데없이 복잡해 차라리 constructor dependency injection 을 쓰는게 낫다고 생각해 왔다. zio module pattern 2.0 이 최근에 소개되었는데, zio magic 과 함께 쓰면 어느정도 쓸만한 것 같다.
코드
import zio.clock.Clock import zio.console.Console import zio.magic._ import zio.{ App, ExitCode, Has, Ref, UIO, URIO, URLayer, ZIO, ZLayer } object ZLayerTest extends App { trait Logging { def log(line: String): UIO[Unit] } object Logging { // URIO 가 아닌 ZStream 일 경우 ZIO.serviceWith 대신에 // ZStream.accessStream(_.get.XXX) 사용 def log(line: String): URIO[Has[Logging], Unit] = ZIO.serviceWith[Logging](_.log(line)) val refLayer: ZLayer[Any, Nothing, Has[Ref[Long]]] = Ref.make(0L).toLayer val fullLayer: URLayer[Has[Console.Service] with Has[Clock.Service] with Has[Ref[Long]], Has[Logging]] = LoggingLive.toLayer[Logging] val live: ZLayer[Has[Console.Service] with Has[Clock.Service], Nothing, Has[Logging]] = ZLayer.wireSome[Has[Console.Service] with Has[Clock.Service], Has[Logging]](refLayer, fullLayer) } case class LoggingLive(console: Console.Service, clock: Clock.Service, ref: Ref[Long]) extends Logging { override def log(line: String): UIO[Unit] = for { current <- clock.currentDateTime.orDie count <- ref.modify(x => (x + 1, x + 1)) _ <- console.putStrLn(current.toString + s": [$count] " + line).orDie } yield () } override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = { val program: URIO[Has[Logging], Unit] = Logging.log("Hi") *> Logging.log("Hello") program.injectSome[zio.ZEnv](Logging.live).exitCode } }
출력 결과 샘플
2021-08-19T01:10:28.234+09:00: [1] Hi 2021-08-19T01:10:28.257+09:00: [2] Hello
'zio > zio1' 카테고리의 다른 글
피보나치(fibonacci) 수열을 Scala Stream, ZStream 으로 각각 구현 (0) 2021.08.03 Task 타입을 Future 로 변환해 자연스럽게 사용하기 (0) 2021.07.23