My application uses a properties-file to load several properties.
Every instance of the application has 3 environment-related parameters - one of them is a property, the other two are computed based on it.
class Environment(val properties: Properties) {
val dbUrl = valueOrError("db.url")
val host = valueOrError("host")
//...
val environmentFlag = valueOrError("env.flag")
val environmentToken = environmentFlag match {
case "live" => "L"
case "staging" => "S"
case "test" => "T"
val environmentUrlPrefix = environmentFlag match {
case "live" => ""
case "staging" => "staging-"
case "test" => "test"
}
}
It seems to me that the 3 environment* properties should be somehow encapsulated.
I called the sought abstraction Discriminator
, since it's used to distinguish between the 3 (for now) environment types. Since in one running application, there is only one set of such environment* properties, I implemented it as an object
:
class Environment(val properties: Properties) {
val dbUrl ...
object Discriminator {
val flag = valueOrError("env.flag")
val token = flag match {
case "live" => "L"
case "staging" => "S"
case "test" => "T"
val urlPrefix = flag match {
case "live" => ""
case "staging"=> "staging-"
case "test" => "test-"
}
}
}
I can call: environment.Discriminator.urlPrefix
, which is fine, but how can I improve the code? How do I get rid of the duplicated match
?
Now it feels like the values of token
and urlPrefix
of live
should live together (as should the ones for staging
and so on) - kinda like as part of one instance of a Discriminator class.
abstract class Discriminator(val flag = valueOrError("env.flag"),
val token: String
val urlPrefix: String)
Since I still want to use environment.Discriminator.urlPrefix
, I still need the Discriminator
(now) companion object.
But I'm stuck here - I don't know how to combine the concepts.
I clearly have to create myself 3 instances of Discriminator - based on the concrete flag
field, but how? How do I call the constructor - passing it the last two parameters based on the first one (which is common to all instances)?
And once I have this, how do I connect the three instances with the Discriminator companion object, so that I can use environment.Discriminator.urlPrefix
?
You can initialize both token
and urlPrefix
at the same time like this:
val (token, urlPrefix) = flag match {
case "live" => ("L", "")
case "staging" => ("S", "staging-")
case "test" => ("T", "test-")
}