Citing @mbore:
Actually I'm still not sure if we want to support no parameters constructors.
It may cause difficult to debug mistakes like "forgot to pass filled config", for example:
import cats.effect._
import cats.effect.unsafe.implicits.global
class MutableConfig() {
var port: Option[Int] = None
var host: Option[String] = None
}
class Service(cfg: MutableConfig) {
println(s"[${cfg.host}]:[${cfg.port}]")
}
object Main extends App {
def loadConfig(): Resource[IO, MutableConfig] = Resource.pure {
val mc = new MutableConfig()
mc.host = Some("xyz")
mc.port = Some(8080)
mc
}
val cfg = loadConfig()
val service = autowire[Service]()
service.allocated.unsafeRunSync()._1
}
it works and prints [None]:[None].
I see that it may reduce boilerplate in some cases, but I'm not sure if it's worth to risk.
Something to consider - I think no-arg implementations might be common, but the argument with configuration is also a valid one.
Maybe we could somehow make this configurable - either support no-arg constructors or not? Or better, maybe the configuration could include packages from which we want to autowire, or a blacklist of packages which should never be autowired?
However, it's challenging to provide such configuration at compile-time - I suppose it would need to be somehow available at the type level?
Citing @mbore:
Something to consider - I think no-arg implementations might be common, but the argument with configuration is also a valid one.
Maybe we could somehow make this configurable - either support no-arg constructors or not? Or better, maybe the configuration could include packages from which we want to autowire, or a blacklist of packages which should never be autowired?
However, it's challenging to provide such configuration at compile-time - I suppose it would need to be somehow available at the type level?