0

I have a Java app with three classes: Foo, Bar and Baz. All three depend on a bunch of what are currently constants defined in each class in order to determine how to run. On top of that, Baz interacts with a number of builder classes that need to be set up in various ways.

I'd like to refactor out all of the configuration info in to a .properties file so that I don't have to recompile every time I change a constant.

But I'm not sure how to structure it:

Do I have a ConfigInfoSingleton that holds all of the parameters of the application in static properties, and have other classes ask it for information when they need it? That seems wrong, as it introduces global state.

Do I pass around a ConfigInfoMap as a parameter to all of the classes that need that info? Then I need to have Foo, Bar, and Baz parsing strings in order to decide what they're going to do, and that seems very wrong. Especially in the case of Baz, where I can't just pass around values, but I need to use switch statements on configuration info to determine builder method calls.

Do I parse the info in a different class, and have that class tell the others how to set themselves up? Then I have a class that needs to know about everyone else's implementation details, which seems wrong, but less so than the other options.

This seems like a really basic question but I'm not sure how to proceed in terms of good software design, and I haven't had much luck Googling. Whats the "right" thing to do?

  • "Then I need to have Foo, Bar, and Baz parsing strings in order to decide what they're going to do, and that seems very wrong." Parsing strings? Why? You can do all the parsing up front. – Doval Jul 31 '14 at 19:36
  • @Doval And then pass around enums or something like that? – Patrick Collins Jul 31 '14 at 19:42
  • Right. Parse the file, then create an object that represents the configuration file. The object's fields can be enums for config properties that only have a small set of choices. – Doval Jul 31 '14 at 19:45
  • Okay -- I was vaguely uncomfortable with this idea because it seemed like that would be leaking everyone's implementation details to the configuration file object. But maybe that's not so much of a big deal? – Patrick Collins Jul 31 '14 at 19:48
  • Constructor arguments aren't implementation details. Otherwise, every object leaks its implementation. – Doval Jul 31 '14 at 19:52
2

As Doval mentions you could parse your *.properties file and create a class that represents your properties and then pass it along to your classes.

A different approach is also to look into a framework that can handle this for you. Spring does not only inject your dependencies but also handles properties very well. This questions gives a good example on how to use Spring together with *.properties files.

There is also less intrusive libraries available such as Owner that supports live reloading of your properties amongst other things.

  • Upvote for mentioning the Spring approach to the configuration topic. – mhaller Jul 31 '14 at 22:02
1

Parse the config file and create an object representing the config file's values. Then you can decide how to construct Foo, Bar, and Baz based on the the values of the object's fields.

1

Been there. Done that.

What I did when I had a similar situation was:

Regarding the configuration:

  • Created a wrapper around a Properties class, I called that wrapper Context
  • That wrapper reads and parses the property file
  • I created a ContextDependand interface with a setContext(Context c) method
  • I have Foo, Bar and Baz implement that interface
  • I inject that Context object into my Foo, Bar and Baz classes so they can acces it without it being a Singleton

Regarding the creation problem:

  • I used the Builder pattern
  • I created a Builder interface with just a build method
  • Created a FooBuilder, a BarBuilder, a BazBuilder, etc. that implement Builder and return an object which is a superclass of my other classes or an interface they implements
  • I added each builder to a HashMap with a key, like map.put('FOOBUILDER',new FooBuilder())
  • Then, instead of a long case structure, I just look up the builder in the HashMap and get it build the object for me, or I traverse the hash and build all of them
  • That way I tell in the properties files what objects of a collection to build and that can be done without recompiling

If the Builder part is not want you were asking for, at least try the property wrapper / context injection part.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.