使用全局对象或参数传递配置数据,Scala中哪一个更好?
我是Scala的新手,我有多年的Java编程经验 通常有两种模式传递一些配置:使用全局对象或参数传递配置数据,Scala中哪一个更好?,scala,Scala,我是Scala的新手,我有多年的Java编程经验 通常有两种模式传递一些配置: 使用全局对象听起来像“ConfigManager”。每次我 我需要一个直接从中获取的配置 通过参数传递配置。配置参数可能存在于中 程序中有许多层 我选择一种模式取决于在编写Java时如何使用配置 但在Scala,许多人谈论消除副作用。这让我怀疑是否应该不惜任何代价使用第二种模式 Scala中哪种模式更好?使用全局对象(此对象仅存储只读不可变数据,因此没有问题),它可以同时加载配置对象和配置变量。这比在代码深处加载
- 使用全局对象听起来像“ConfigManager”。每次我 我需要一个直接从中获取的配置
- 通过参数传递配置。配置参数可能存在于中 程序中有许多层
object ConfigParams {
val config = ConfigFactory.load()
val timeInterval = config.getInt("time_interval")
....
}
好处:
object ConfigParams {
val config = ConfigFactory.load()
val timeInterval = config.getInt("time_interval")
....
}
// centralize the parsing of configuration
case class AppConfig (config: Config) {
val timeInterval = config.getInt("type_interval")
val someOtherSetting = config.getString("some_other_setting")
}
...
// don't depend on global objects
class SomeComponent (timeInterval: Int) {
...
}
object SomeApplication extends App {
val config = AppConfig(ConfigFactory.load())
val component = new SomeComponent(config.timeInterval)
}
我怀疑使用companion object会解决很多问题:作为参考:
Reader
monad(由Cats或Scalaz提供)可以简化第二种模式,但如果您刚开始使用Scala,这可能有点高级。有几个Reader
,免费
,@Inject
通过guice或类似工具,@PeterNeyens感谢您的建议!在我看到你的评论后,我读了一些关于读者monad的帖子。我想我现在知道怎么用了。但我也认为使用它来传递包含不同方面的值的全局配置可能不是一个好主意。这可能会导致在程序的较低级别中携带太多的配置,或者我应该以使编程更加复杂的方式削减配置。无论如何,我将使用Reader monad编写一些代码,看看发生了什么。@AndrewLi大多数Reader
实现都有某种local
函数,它允许您从全局配置转到本地配置,例如参见(Reader[a,B]
等于Kleisli[Id,a,B]中的最后一个示例
)。这不会很快失败,因为对象初始化是在对象第一次请求字段时发生的,这可能不是在实际启动时发生的(例如,如果您在Play中使用Guice DI,则可能会在第一次请求时失败,如果需要该值的话)。此外,对象初始化可能会失败,将来的引用将无法找到该类。通过将可能出现故障的字段定义设置为lazy val
,可以稍微改善这种极端故障模式。此外,这是不可避免的单例状态,它是不灵活的(例如,测试时很难使用)。