11

Many times I have been in a situation where an application is apparently broken, only to find that an external configuration file has been at fault. Typically this is because the wrong file is there, or that it contains incorrect data.

Is there a better way to allow an external user/process to modify the runtime characteristics of an application, or is this the best known solution to the problem?

I'd like to see discussion on the general case rather than focusing on, say, Unix /etc or Java JNDI and so on.

12
  • 2
    how else can you configure test/dev/live/different live environments ? My point is its the only option - there will always be an external dependcy. Commented May 23, 2012 at 11:32
  • 5
    Whatever you have will be external. The problem you are having is not that the configuration is external, but that it is badly managed and understood.
    – Oded
    Commented May 23, 2012 at 11:36
  • 2
    But that's the thing - config files tend to be badly managed or understood.
    – Telastyn
    Commented May 23, 2012 at 12:01
  • 4
    As for the "wrong file" - there is a nice Unixish technique: use a script wrapper to start your binary, setting all the configuration environment variables locally. This way it is always crystal clear which configuration you've picked up.
    – SK-logic
    Commented May 23, 2012 at 12:53
  • 1
    The "alternative" is for 99% of configuration parameters to be optional. There should be sensible default values. When configuration needs its own dedicated file and becomes longer than the executable code, that tells me that the configurability goes beyond usefulness. Imagine if you needed 35 parameters to be specified before you could run curl. Commented Feb 11, 2019 at 22:49

6 Answers 6

14

Most applications will require some external configuration; you can hide this by making it dependent on magic variables, or by saving it to some internal location, but that won't remove the need. The goal is to recognize what should be external, and what can be internal. Only the internal parts can be tested.

An application should not trust an external configuration file to be correct. It should check the correctness, and report errors. If it is not possible for the application to check the configuration file, you are probably doing too much with it. If the configuration file changes the behavior of the application, it shouldn't be external in my opinion.

For example, a database username/password can be easily verified by the application by trying to connect to the database. If this fails, it can report it, and it is obviously not a bug in the application code. Similarly, for a file path the existence and access rights can be checked.

Now, if you were to put SQL queries in the configuration file, then the application cannot easily check the correctness of those queries. The same goes for a full dependency-injection specification (a la Java-Spring XML) file. Those should not be in external configuration files.

But if the specified configuration describes something external, and you can quickly check its correctness, I don't think there is anything wrong with external configuration files.

Edit: also make sure your error reports show which configuration file is used. Nothing is more frustrating than finding out you were looking at the wrong file after hours of trying to find out what's wrong with it.

1
  • 4
    +1 for the internal validation recommendation - definitely a must to complete the pattern
    – Gary
    Commented May 23, 2012 at 12:40
7

I would classify them more as a "known problem area" than an antipattern. Unless you are going to deploy a fixed configuration, you'll have to store configuration information somewhere. I usually like to store most of my configuration information in the database, but you still have to store the database connection information somewhere. I do prefer the Java/Spring approach of storing the configuration information in the application structure itself, rather than (say) in the user's home directory or the Windows registry, but that's just personal preference.

5

External configuration files are NOT an anti-pattern. Like everything else they can be used well or poorly depending on the system in question.

You seem to have run into some apps where the external config can break the app without telling the user what's going on. That's bad, but it's not the fault of the config files, it's the fault of whoever decided which parts are in the config files and which parts are in the app, and how to handle errors among them.

5

If anything, moving configuration from logic to data is preferred. It allows you to make the application more flexible without the need to rework your code. Missing data files is more a case of too little documentation or sloppy work when installing than a bad practice in terms of coding IMHO.

1
  • I agree that declarative statements are a more direct, easier to understand way of specifying properties and (to an extent) behavior. +1. Commented May 23, 2012 at 16:45
4

On my opinion: NO, external configuration files are not an antipattern.

It is just a technique an architectual pattern to manage software complexity.

In the age of SOLID design principles you have moved software complexity from Monolithic_application to more independent modules that have to be plugged together.

the alternative to "external configuration files" would be to configure modules directly by code.

1
  • Patterns are not confined to code - an external configuration file is an architectural pattern rather than merely a technique.
    – Gary
    Commented May 23, 2012 at 12:42
3

Make your favorite SCM tool do double-duty as a CM tool: Put your config files in the repository. To change the config, commit the changes and let your automated deployment tools push them out to production (after running a range of automated tests, of course!)

Et Voila! you have a record of all configuration changes, plus the additional safety net of an automated CI/test system!

As has been pointed out before, architecture & design patterns are not limited to the product-system itself, but also extend to the team/process/systems that help to produce it.

3
  • 1
    +1 for a useful implementation strategy - pretty much how Heroku does it with GitHub projects.
    – Gary
    Commented May 23, 2012 at 17:07
  • You have to make sure your configs are not in the same repo as your code because of the effects on branching and tagging for releases.
    – snakehiss
    Commented May 23, 2012 at 20:46
  • 1
    I disagree. The configs really should be in the same repo as the code. I believe that a production change to a config file is a valid reason to make a commit to (for example) a Svn tag branch. The key benefit is that you can look in one place (the repository) to see everything (as much as is possible) that could be affecting production. Much easier to chase down gremlins and bugs if you know where to find everything. (Particularly if you are using something like Graphite to chart commits against performance metrics & alerts) Commented May 23, 2012 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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