开发者

How do I implement configurations and settings?

开发者 https://www.devze.com 2023-02-08 14:10 出处:网络
I\'m writing a system that is deployed in several places and each site needs its own configurations and settings开发者_运维问答.A \"configuration\" is a named value that is necessary to a particular s

I'm writing a system that is deployed in several places and each site needs its own configurations and settings开发者_运维问答. A "configuration" is a named value that is necessary to a particular site (e.g., the database URL, S3 bucket name); every configuration is necessary, there is not usually a default, and it's typically string-valued. A setting is a named value but it just tweaks the behavior of the system; it's often numeric or Boolean, and there's usually some default.

So far, I've been using property files or thing like them, but it's a terrible solution. Several times, a developer has added a requirement for a configuration but not added the value to file for the live configuration, so the new release passed all the tests, then failed when released to live.

Better, of course, for every file to be compiled — so if there's a missing configuration, or one of the wrong type, it won't get past the compiler — and inject the site-specific class into the build for each site. As a bones, a Scala file can easy model more complex values, especially lists, but also maps and tuples.

The downside is, the files are sometimes maintained by people who aren't developers, so it has to be pretty self-explanatory, which was the advantage of property files. (Someone explain XML configurations to me: all the complexity of a compilable file but the run-time risk of a property file.)

What I'm looking for is an easy pattern for defining a group required names and allowable values. Any suggestions?


How about using Mixin composition? Since traits are applied from right to left we can:

Define traits:

default property:

trait PropertyA {   
   val userName = "default"
   def useUserName() : Unit = {
     println(userName)
   }
}

some other property:

trait SomePropertyA extends PropertyA {   
   val userName = "non-default"
   def useUserName() : Unit = {
     println(userName)
   }
}

Define an abstract class with default property:

trait HasPropertyA {
   val prop : PropertyA = new PropertyA
}

Define an abstract class with non - default property:

trait HasSomeOtherPropertyA extends HasPropertyA {
       override val prop:PropertyA   = new SomePropertyA {}
}

In your class use default one:

trait MyClass extends PropertyA {
   doSomethingWith(prop.userName)
}

or in the other situation mix it with some other property:

if(env.isSome) {
   val otherProps = MyClass with HasSomeOtherPropertyA
   doSomethingWith(prop.userName)// userName == non-default! 
}

Read in more detail in the paper Scalable Component Abstractions


Although Lift is a web framework in its essence, it has some utilities as well. One of them is Dependency Injection, see : http://simply.liftweb.net/index-8.2.html#toc-Section-8.2. So you can for example create a base trait with default values and then subclass the Runtime, Development, Test... environment values. And I think that it's easy for someone without knowledge of scala to put some override def defaultValue = "new value" in a file.

0

精彩评论

暂无评论...
验证码 换一张
取 消