With DevOps bringing source control to configuration files and publishing to production servers being automated – bringing both code and configuration over on the same time, the difference between code and config has become less than ever (if it even exists).
A few weeks ago I reread Mike Hadlow’s brilliant post The Configuration Complexity Clock. As I’m also in the middle of setting up publishing routines for a web application I started to think about the difference between configuration and code. The more I think about it, the less clear the difference is.
A simple attempt to differentiate them would be to look at where they are stored.
- Everything in source files that are consumed by the compiler is code.
- Everything in configuration files that are read at runtime is configuration.
Unfortunately that is not the entire truth. For example the route config in an ASP.NET MVC application is a kind of configuration – but it is done in code. The same is true for the Entity Framework Code First mappings – it is done in code (either through attributes or a fluent API), but is a kind of mapping configuration. An example of the other way around is startup configuration scripts (think of *nix
.bashrc or the old
autoexec.bat on DOS systems). It is configuration, but is run as a script.
There are definitely cases where it is not that simple to define what is configuration and what is code.
And does it really matter?
For web applications that are deployed in single copies I’d say that it doesn’t. With DevOps becoming stronger and introducing proper handling (read: version control) for configuration files both config and code are handled in the same way. They are both handled in a source control repository, subject to code reviewpractices and uploaded to the server through an automated publish pipeline.
With that kind of process (which in my opinion is mandatory for any professional shop), there is no longer any cowboy style config updates on live environments. Both config and code are updated in exactly the same way through the same process.Using Code or Config
That leads to the next question: What’s proper to put where?
I might be a bit radical, but here’s my take on it (that I haven’t yet implemented in any project):
Put anything you can into code that is checked at compile time.
That doesn’t mean that values should be hard coded all over the place. That’s not DRY. Put the values in a well known location that can be accessed through a simple to use façade. If you later find out that you want to move some stuff from being compile time constants to be stored in a config file, it is easy to do that by modifying the façade.Difference Between Environments
The one case where I think that it makes sense to use config files is for values that are different in different environments. For anything where your development and production environment should differ, or where the production and the user test environments should be different you have to use config files. You don’t want the code littered with conditionally compiled stuff. The compiled code deployed to different environments should be identical (except for optimization levels for debug/release builds).
The ASP.NET way to deal with different configurations for different environments is through config files transforms, which is really powerful and simple to use on the same time. It finally got the configuration hell of all our different environments under control. (Some stuff can also be changed in the publish process, but I prefer using config transforms as they are more powerful and easier to persist in source control.)Flamebait
First thing I’ll do tomorrow when I get to the office is to start moving things out of
web.config and into configuration classes in the code.
What do you think – is that the right thing to do, or are there other pros with config files that I have missed? Please leave a comment and explain why I’m wrong to get the discussion going!