我正在编写一个部署在多个地方的系统,每个站点都需要自己的配置和设置。 “配置”是特定站点所需的命名值(例如,数据库URL,S3桶名称);每个配置都是必需的,通常没有默认值,而且通常是字符串值。设置是一个命名值,但它只是调整系统的行为;它通常是数字或布尔值,通常有一些默认值。
到目前为止,我一直在使用属性文件或类似的东西,但这是一个糟糕的解决方案。有几次,开发人员已经添加了配置要求,但没有将值添加到实时配置的文件中,因此新版本通过了所有测试,然后在发布时失败。
当然,对于要编译的每个文件都更好 - 所以如果缺少配置或者错误类型之一,它将无法通过编译器 - 并将特定于站点的类注入到每个构建中现场。作为一个骨骼,Scala文件可以轻松地模拟更复杂的值,尤其是列表,还有地图和元组。
缺点是,文件有时由非开发人员维护,因此必须非常明确,这是属性文件的优势。 (有人向我解释XML配置:可编译文件的所有复杂性,但属性文件的运行时风险。)
我正在寻找的是一个简单的模式,用于定义组所需的名称和允许的值。有什么建议吗?
答案 0 :(得分:1)
使用Mixin成分怎么样?由于特征从右到左应用,我们可以:
定义特征:
默认属性:
trait PropertyA {
val userName = "default"
def useUserName() : Unit = {
println(userName)
}
}
其他一些财产:
trait SomePropertyA extends PropertyA {
val userName = "non-default"
def useUserName() : Unit = {
println(userName)
}
}
使用默认属性定义一个抽象类:
trait HasPropertyA {
val prop : PropertyA = new PropertyA
}
使用非默认属性定义抽象类:
trait HasSomeOtherPropertyA extends HasPropertyA {
override val prop:PropertyA = new SomePropertyA {}
}
在你的课堂上使用默认的:
trait MyClass extends PropertyA {
doSomethingWith(prop.userName)
}
或在其他情况下将其与其他财产混合:
if(env.isSome) {
val otherProps = MyClass with HasSomeOtherPropertyA
doSomethingWith(prop.userName)// userName == non-default!
}
中详细阅读
答案 1 :(得分:0)
虽然Lift
本质上是一个Web框架,但它也有一些实用程序。其中之一是依赖注入,请参阅:http://simply.liftweb.net/index-8.2.html#toc-Section-8.2。因此,您可以使用默认值创建基础trait
,然后将Runtime,Development,Test ...子类化为子类。而且我认为没有scala知识的人很容易在文件中加入override def defaultValue = "new value"
。