[I recently wrote this up for work, and thought it was worth re-posting here.]
These ideas come almost entirely from Udi Dahan and how he implemented nServiceBus, but unfortunately I can’t find where he said it. It may have been when I attended his class in Austin last October.
I define configuration as “stuff that needs to be easy to change.” Udi says there are two major categories of configuration, with very different characteristics. One category has to do with operational concerns, such as:
- The specifics of the physical deployment environment (URLs, machine names, connection strings, etc.)
- Monitoring and troubleshooting (logging verbosity and where log entries are stored, etc.)
- Scaling out (how many app instances or threads should be running, etc.)
These are things that administrators care about deeply. They want to be able to move things to different machines, spin up a new instance of your service, failover a database server, etc. And as a developer, you want them to be able to do all of those things without calling you. These “administrator config” settings have no effect on the semantics of your application. They change “physical” characteristics, not business-logical characteristics.
A second category of configuration does affect the semantics of your application. Udi calls this “developer config.” Changing it will have an effect on what the application does. These are things like:
- Using a different implementation of a interface (e.g., a gateway that talks to a database vs a remote web service)
- Whether a particular operation requires a transaction (e.g., the WCF settings for a specific service)
Changes to these often need to be one-line-of-code simple, which makes them “configuration” in my mind. But they also imply a requirement change because they change how the application works. (Yes, adding or removing a transaction is a semantic change.) Therefore you definitely don’t want administrators to go and change them on production servers. The best way to prevent them from changing these settings it to give them no way to do it!
The most common objection to putting the developer config in code is that you have to redeploy your application. Yep, exactly. Changing developer config alters the semantics of your application. Any such change should go through all of your testing and validation processes before being released.
Digging a little deeper, a lot of the resistance to putting developer config in code stems from fear of deployment. If deployment is hard, error-prone, and stressful then you try to avoid it by putting as many things in your config file as possible. (The same rationale is often given for putting business logic in stored procedures.) If you cross your fingers every time you deploy, you’re doing it wrong.
Deployments (and rollbacks) should be easy and reliable. That means largely automated. Once you have automated builds, lots of automated tests, and (mostly) automated deployment/rollback, “hard coded” is no longer a scary concept. See this and this. JFHCI.
Ever opened up a config file that looked really scary? How about a default WCF config with dozens and dozens of settings for a single service endpoint? How many of those things do you really want someone to change on the production servers? 5% of them? Once you’ve removed all of that developer config, the administrators will thank you for removing all that noise you told them to absolutely, positively never touch. They’re also a lot less likely to catastrophically fat-finger a random character that will be lost in a sea of angle brackets.