【发布时间】:2020-11-19 14:25:58
【问题描述】:
我正在尝试为使用 ActorSystem 作为 Http 调用的主干的程序重构一些代码。
我的具体目标是让我的代码更加模块化,这样我就可以编写函数库,这些函数库使用 ActorSystem 进行 http 调用,而 ActorSystem 稍后将由应用程序提供。
这是一个普遍的问题,因为我倾向于在合理的范围内遇到这个问题。
我有两个目标:
- 尽量减少我创建的 ActorSystem 的数量以简化对它们的跟踪(目标是每个顶级应用程序一个)
- 避免在需要的任何地方显式传递 ActorSystem 和上下文。
从概念上讲 - 下面的代码说明了我的想法(当然,这段代码不会编译)。
import akka.actor.ActorSystem
import intermediateModule._
import scala.concurrent.ExecutionContextExecutor
object MyApp extends App {
// Create the actorsystem and place into scope
implicit val system = ActorSystem()
implicit val context = system.dispatcher
intermediateFunc1(300)
}
// Elsewhere in the intermediate module
object intermediateModule {
import expectsActorSystemModule._
def intermediateFunc1(x: Int) = {
// Relies on ActorSystem and Execution context,
// but won't compile because, of course the application ActorSystem and
// ec is not in scope
usesActorSystem(x)
}
}
// In this modiule, usesActorSystem needs an ActorSystem
object expectsActorSystemModule {
def usesActorSystem(x: Int)
(implicit system: ActorSystem, context: ExecutionContextExecutor) = ???
//... does some stuff like sending http requests with ActorSystem
}
有没有办法通过子模块“涓涓细流”隐式,以实现顶级应用程序提供所需隐式的目标?
这是否可以通过模块导入的“深度”无关紧要的方式来完成(例如,如果我在顶级应用程序和需要 ActorSystem 的模块之间添加了一些中间库)?
【问题讨论】:
-
我建议只将隐式作为函数参数传递到层次结构中。这种方法在我工作的生产系统中效果很好
-
谢谢@YikSanChan 我尝试采用这种方法并且我已经让它工作了,尽管我遇到了一个条件,如果我将隐式值作为隐式放入,例如
implicit val myImplicit=...我收到一个编译错误,因为隐含含糊不清。如果我在顶级范围内直接使用val myImplicit,一切正常 - 我需要通过一些案例来了解导致歧义的原因 -
请阅读docs.scala-lang.org/tutorials/FAQ/finding-implicits.html 了解可以导入哪些隐式。一旦你发现额外的隐含,你可以删除它。另外,如果使用intellij,可以看到implicits,有助于理解流程:jetbrains.com/help/idea/edit-scala-code.html#scala_hints