Search code examples
javaconfigurationconfigconfiguration-files

Best way to manage a Configuration File?


A colleague and I were discussing best practices for managing a Configuration file, and we wanted to get some further feedback from others.

Our goal is for the configuration-file to specify what action should be taken, when certain events occur.

The 2 options that we are debating:

  1. In the config-file, specify the class-path of the class, which implements the action to be taken (eg: "ActionToTake" : "com.company.publish.SendEveryoneAnEmailClass"). Inside the code, when this event is encountered, we can then do Class.forName(config.ActionToTake).newInstance().run() in order to invoke the specified action.

  2. In the config-file, specify in a human-readable-phrase, the action that should be taken (eg: "ActionToTake" : "SendEveryoneAnEmail"). Inside the code, when this event is encountered, we can then parse config.ActionToTake, and perform a mapping that translates this to action implementation (eg: new SendEveryoneAnEmailClass().run())

We are currently a very small team, and the only people reading/using this config file currently, is our team of software devs. But it's unclear if this will continue to be true in future.

Reasoning behind option 1: Anyone reading the config file will explicitly and immediately know what class will get invoked, and where it's implemented. This also allows for the action-class to be implemented/imported from a completely separate JAR file, without recompiling/changing our code.

Reasoning behind option 2: The config file should be a high level description of user-intent, and should not contain implementation details such as specific class names & package paths. Refactoring of class/package names can also be done without having to make config file changes.

Thoughts on which of these 2 design philosophies is preferred for configuration files?


Solution

  • 1st option's advantage is, as jas noticed, the ability to 'link' code in the future. It's a real advantage only if you sell/distribute your software as a closed sourced package or if you plan to hot-swap behavior on production. You've already pointed out the cons - refactoring

    2nd option:

    • It won't help you with refactoring. If you change your action from SendEmail to BringBeer but you leave the string send email then you failed.
    • Readability. send-everyone-an-email is as good as SendEveryoneAnEmail. Every developer will know what will happen. It can't be confused with LaunchRockets. Your code can find class based on some text, not necessarily the full qualified name. Your code can assume that Actions are in some specific package unless explicitly provided. And that is a way to combine both options.

    Consider also another possibility: do the configuration in code. If you don't want to recompile the package, you can use scripting language (groovy). It lets you create very readable dsl, and you will have refactoring.