Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't autowire no-arg constructors, or make this configurable? #184

Open
adamw opened this issue Oct 17, 2021 · 1 comment
Open

Don't autowire no-arg constructors, or make this configurable? #184

adamw opened this issue Oct 17, 2021 · 1 comment
Labels

Comments

@adamw
Copy link
Member

adamw commented Oct 17, 2021

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?

@mbore
Copy link
Contributor

mbore commented Jan 11, 2022

Adding compile-time configuration might be also useful to define a default trait implementation that should be wired. To do so, we may introduce a tag useClass[A] or useImplementation[A] that would be passed in autowire dependencies list.

It would be worth considering additional parameters list for configuration tags, then we could use it as follows:

autowire[ServiceA](useImplementation[ServiceB], useEmptyConstructors)(serviceC, serviceD)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants