Reputation: 75
I have a class that gets created using data a
read from a .conf file. The class also contains a value b
which does not come from the conf file.
The class:
case class Configuration(a: String, b: String)
The sequence of calls to instantiate a Configuration looks like this:
User -> ConfigurationCompiler
-> ConfigurationReader
-> readConfig(): Configuration
(The user gets a Configuration object back)
Value a
gets read and set by the .conf file, but value b
is specified by the user. I don't want to pass value b
all the way down to readConfig() so it can be set on instantiation of Configuration
.
I have experimented with Option
, but to me it looks ugly because you first instantiate b
with None
, and then set it later. Also, the tests look weird because you must test Some(String)
instead of String
. Option also doesn't seem like it fits here because the field is actually not optional, it is just set at a later time.
The Option
class:
case class Configuration(a: String, var b: Option[String])
Upvotes: 1
Views: 264
Reputation: 5093
I would go for a builder
. Here's an example:
import cats.implicits._
import cats.data.ValidatedNel
case class ConfigBuilder(a: Option[String] = None, b: Option[String] = None) {
def withA(a: String): ConfigBuilder = copy(a = Some(a))
def withB(b: String): ConfigBuilder = copy(b = Some(b))
def build: ValidatedNel[String, Configuration] =
(a.toValidNel("'a' must be defined"), b.toValidNel("'b' must be defined"))
.mapN(Configuration)
}
Validating both fields:
ConfigurationBuilder()
.build
// Invalid(NonEmptyList('a' must be defined, 'b' must be defined))
Getting valid configuration:
ConfigurationBuilder()
.withA("test")
.withB("test2")
.build
// Valid(Configuration(test,test2))
Upvotes: 1
Reputation: 8227
You could create the original configuration object with a default value in the b
position. When you get the actual value of b
, then create a copy that is used by your program using:
val realConfig = originalConfig.copy( b = bValue )
The copy will have the field b
replaced with the desired value for actual use.
Upvotes: 1
Reputation: 15770
Some solution might be to use implicit
, but implicit String
doesn't look good - implicit types are resolved by type, so it should be something less general than String
.
What I can think of is something like PartialConfiguration
returned by readConfig()
. Then you can add it's values to the values provided by User
to create full Configuration
.
Upvotes: 1