在 Scala 中使用混合核心库的特征



我正在Scala中从事多SBT项目。我将核心内容提取到单独的 SBT 项目中。这包括处理配置、第三方库(初始化 RMQ 客户端、初始化 Redis 客户端等(和一些模型。

所以我组织了一些东西,比如在 trait 中加载 config,然后在我需要的地方混合这个特征,只使用Configurationtrait 中定义config方法,该方法为特定环境加载配置(基于环境变量(。我对数据库做了同样的事情,所以我加载PostgreSQL,打开连接,然后在我需要的地方混合该特征,只使用database可用于执行查询和其他的方法。

您认为这是好方法吗?优点是我不必在每个项目中处理数据库连接和初始化,而且代码也短得多。但是,关闭连接存在一个问题。在数据库混合的特质中在哪里关闭连接?

感谢有关该主题的任何帮助。谢谢

阿米尔

关于连接,您应该在完成连接时关闭它们(返回到池(,这与混合实现是正交的。

至于配置之类的,我喜欢这种方法,但它的问题在于,大多数时候你希望像加载config这样的东西是单例的,但如果你只是做一些类似的事情

trait Configuration { 
val config = loadConfig
}
class Foo with Configuration
class Bar with Configuration
val f1 = new Foo
val f2 = new Foo
val b1 = new Bar
val b2 = new Bar

然后,您最终将加载配置的四个不同副本。 解决此问题的一种方法是将loadConfig委托给单一实例对象:

object Configuration {
val config = loadConfig
}
trait Configuration { 
def config = Configration.config
}

这有效,但使单元测试和覆盖功能变得更加困难(如果有时我想从数据库加载我的配置怎么办?

另一种可能性是代理类:

trait Configuration {
def loadConfig: Config
lazy val config: Config = loadConfig
}
class ConfigurationProxy(cfg: Configuration) extends Configuration {
def loadConfig = cfg.config
}
object Main extends App with Configuration {
def loadConfig = ??? // executed only one per application 
...
}
class Foo extends ConfigurationProxy(Main)
class Bar extends ConfigurationProxy(Main)
val f1 = new Foo
val f2 = new Foo
val b1 = new Bar
val b2 = new Bar

现在,所有四个变量都在查看同一个Config实例。 但是如果你在某个地方有一个函数需要Configuration,你仍然可以传递这些中的任何一个:

def connectToDB(cfg: Configuration) = ???
connectToDB(Main)
connectToDB(f1)
connectToDB(b2)

等。

最新更新