Created
July 16, 2022 07:53
-
-
Save makiftutuncu/da7866d2b43dbb217c69ac4ffbd0354c to your computer and use it in GitHub Desktop.
Sharing Builder Code by Some Scala Tricks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class BarDBConfig(connectionString: String) extends DBConfig | |
object BarDBConfig extends DBConfig.Builder[BarDBConfig]("bar") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait DBConfig(val connectionString: String) | |
object DBConfig { | |
// 1. `Builder` extends `Function` type `String => C` | |
abstract class Builder[C <: DBConfig](val prefix: String) extends (String => C) { | |
// Some generic build logic | |
def build(map: Map[String, String]): Option[C] = | |
map.get(prefix) match { | |
case Some(connectionString) => | |
// Calling `apply` because it exists due to `Builder` extending `Function` type | |
Some(apply(connectionString)) | |
case None => None | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 2. This is a case class so it generates an `apply` method conforming to `String => FooDBConfig` type. | |
case class FooDBConfig(connectionString: String) extends DBConfig | |
// 3. Generated `apply` happens to match the `apply` method defined in `Function` type `Builder` extends. | |
// That's why the `apply` that `Function` defines is implemented by the `apply` that case class generates. | |
object FooDBConfig extends DBConfig.Builder[FooDBConfig]("foo") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
val dbConfigMap: Map[String, String] = Map( | |
"foo" -> "fooConnectionString", | |
"bar" -> "barConnectionString" | |
) | |
// 4. Since correct implementation of `apply` is provided by case class, this works! | |
val fooDBConfig: Option[FooDBConfig] = FooDBConfig.build(dbConfigMap) | |
val barDBConfig: Option[BarDBConfig] = BarDBConfig.build(dbConfigMap) | |
fooDBConfig.isDefined // true | |
barDBConfig.isDefined // true | |
val printConfigs: ZIO[FooDBConfig & BarDBConfig, Nothing, Unit] = | |
for { | |
fooDBConfig <- ZIO.environment[FooDBConfig] | |
barDBConfig <- ZIO.environment[BarDBConfig] | |
} yield { | |
println(fooDBConfig) | |
println(barDBConfig) | |
} | |
// 5. This makes it easy to work in some `ZIO` environment that needs both DB configurations | |
// because they are different types but built the same way easily! | |
printConfigs.provide(fooDBConfig.get, barDBConfig.get) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment