I have been mulling over config files and their relationship to code for a while now and depending on the day and direction of the wind my opinions seem to change. More and mor
I tend to agree with the premise of this question. I avoid getting myself into trouble by predicting early that this is going to happen, and therefore never roll my own config system.
And resign myself to live with whatever decision I made, or if i cant, refactor to use one of the above choices that better suits the application.
Point is, there's not really any reason to use a home-grown config solution. For one thing, it's harder on your users to have to learn a new, application specific config format. For another, You benefit from all the many bug-fixes and updates that come free when using an off-the-shelf solution. Finally, Feature creep is put to rest, because, well, you actually can't just add one more feature without really doing a major overhaul cause the config system isn't really in your hands in the first place.
I believe your question is very relevant given the move to "fluent interfaces". Many developers have "seen the light" with respect to XML configured applications. Using XML can be very verbose and difficult to edit correctly (especially if no schema is provided). Having a fluent interface allows the developer to configure the application in a domain-specific language with the assistance of some key-value pairs from a plain text configuration file (or perhaps command-line parameters). It also makes it very easy to setup and configure new instances of the application for testing or whatever.
Here are my answers to your question:
A config file is a way to allow the user to customize the behavior of their program at run-time.
Ideally, I would think that config files should at least be supplemented by a fluent interface to configure the program (this is useful in many respects). If you do require a config file then it should be kept very simple, nothing other than key-value pairs.
I think the answer to this depends on your organization. It should be the responsibility of the person deploying the software to ensure that it is properly configured.
I will steal this answer from someone else :) I like the idea of storing a template configuration in source control and modifying it for each local user's needs. Chances are one developer's config file is another developer's nightmare so it is best to leave things that vary by user out of source control. Having a template is also a nice way to let the person deploying the application (or other developers) see exactly what values are valid for the config file.
The code of our applications becomes less important... There is scripting, there are all kind of attributes that define the behaviour of classes, methods, method arguments and properties. Users can define database triggers and database constraints. There can be very complicated config files. Sometimes the user can define XSLT stylsheets to manipulate input and output because our systems need to be open (SOA). And there is stuff like BizzTalk that needs complex configuration too. Users can define complex workflows.
We have to write better code to deal with this complex environment, so the code of our applications becomes more important...
Here's my thoughts:
To allow the runtime behavior of an application to be modified easily. This can be by programmers or non programmers, depending on the needs. This can be during development, but I often view configuration files as a way to help make a program more flexible at any point.
Yes. I think config files should be as simple as possible, given the constraint that you may need various options to control different behaviors of your runtime. I prefer grouping configuration settings, and simplifying them as much as possible.
Depends on what and why the change is being made. If users are going to be changing it, a front-end should be made to hide them from the details. The same is often true of non-developers in general.
I often source control the "default" configuration, but have a way to override this per system for the actual runtime.
As for adding logic to the config file - I'd avoid this. I think it's better to just have the configuration file switch on the logic in your application. Behavior in config files leads to a lack of maintainability and understanding, in my experience. I strongly prefer keeping configuration files as simple as possible.
I'm a big fan of using python programs as config files, especially for daemons. I like to take the tack of making the daemon completely empty of configuration except for the "configuration port". The python program then connects to the daemon and proceeds to create objects in the daemon and wire them together to create the desired configuration. Once everything is set up, the daemon can then be left to run on it's own. The benefits, of course, are that you get a full fledged programming language to write your config files and since you already have a way to talk to the daemon from another program, you can use it for debugging and getting stats. The major downside is having to deal with messages from another program coming in at any time.
Recently I was working upon a project and I realised that I wanted to have conditionals inside my configuration file - which had previously just been a pretty simple one of the form:
key = val
key2 = val
name = `hostname`
I didn't want to write a mini-language, because unless I did it very carefully I couldn't allow the flexibility that would be useful.
Instead I decided that I'd have two forms:
If the file started with "#!" and was executable I'd parse the result of running it.
Otherwise I'd read it as-is
This means that I can now allow people to write "configuration files" that look like this:
#!/usr/bin/perl
if ( -x /bin/foo )
{
print <<EOF;
foo=me
bar=you
EOF
}
else
{
print <<EOF;
foo=bar
bar=foo
EOF
}
This way I get the power of a dynamic configuration file if the user wants to use it, and the simplicity of not having to write my own mini-language.