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
クラスがDependencyA
とDependencyB
に依存しており、さらにDependencyA
がDependencyAA
に依存しています。
各クラスに対応する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を利用することで、依存関係を明示的かつ安全に管理できるため、複雑なアプリケーションの開発が容易になりそうですね!