0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TL;DR

ZLayerを使用すると、次のようなイメージで簡潔にDIすることができます。

擬似コード
ZIO.serviceWith[使用したいサービスクラス].provide(
  ZLayer.derive[サービスクラスの依存1],
  ZLayer.derive[サービスクラスの依存2],
  ZLayer.derive[サービスクラスの依存1の依存],
  ZLayer.derive[サービスクラスの依存1の依存の依存]
  ...
)

はじめに

Scala ZIOには、ZLayerという強力な機能があります。
ZLayerは、DIをシンプルかつ型安全に実現するための仕組みです。
本記事では、ZLayerを用いたDIについて説明します。

ZIOのZLayerとは?

ZLayerは、ZIOにおけるDIの中核を担う機能です。
ZLayerは、依存関係を解決するためのレシピのようなもので、必要な依存関係をどのように生成し、組み合わせるかを定義します。
ZIOは、これらのZLayerを組み合わせて、最終的に必要なオブジェクトのインスタンスを生成します。

ZLayerによるDIの例

以下のコードでは、ServiceクラスがDependencyADependencyBに依存しており、さらにDependencyADependencyAAに依存しています。
各クラスに対応するZLayerを定義し、provide関数でこれらのZLayerを組み合わせています。これにより、Serviceのインスタンスが生成され、fooメソッドが実行されます。

import zio.{Scope, ZIO, ZIOAppArgs, ZIOAppDefault, ZLayer}

object Main extends ZIOAppDefault {
  class Service(dependencyA: DependencyA, dependencyB: DependencyB) {
    def foo(): Unit = println("foo")
  }

  class DependencyA(dependencyAA: DependencyAA)
  class DependencyAA
  class DependencyB

  // 各モジュール
  val dependencyA = ZLayer.derive[DependencyA]
  val dependencyAA = ZLayer.derive[DependencyAA]
  val dependencyB = ZLayer.derive[DependencyB]
  val service = ZLayer.derive[Service]

  override def run: ZIO[ZIOAppArgs, Any, Unit] =
    ZIO.serviceWith[Service](_.foo()).provide(
      service,
      dependencyA,
      dependencyAA,
      dependencyB
    ) // 実行結果: 「foo」という文字列が標準出力される
}

もし依存関係の定義に誤りがあったら、コンパイルエラーに

Serviceが依存する対象はDependencyA, DependencyAA, DependencyBの3つです。
ここでもし仮にDependencyAAをDIし忘れたらどうなるでしょうか?

  override def run: ZIO[ZIOAppArgs, Any, Unit] =
    ZIO.serviceWith[Service](_.foo()).provide(
      service,
      dependencyA,
      dependencyB
    )

結果、以下のようにコンパイルの段階でエラーが検知されます。

コンパイルエラー内容
/Users/tobita/work/ScalaPlayground/src/main/scala/Main.scala:19:46


──── ZLAYER ERROR ────────────────────────────────────────────────────

 Please provide a layer for the following type:

   Required by dependencyA
   1. Main.DependencyAA
      
──────────────────────────────────────────────────────────────────────


    ZIO.serviceWith[Service](_.foo()).provide(

型安全で凄いですね👍

おわりに

この記事では、ScalaのZIOライブラリにおけるZLayerの基本的な使い方と、その型安全性について触れました。
ZLayerを利用することで、依存関係を明示的かつ安全に管理できるため、複雑なアプリケーションの開発が容易になりそうですね!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?