February 28, 2012 Leave a comment
Where I am working right now, there is a need for framework configurations that are different from application configurations. I should alter that to say, it is not a need, but a desire. The main endpoint here is there are certain configuration elements only people who are very well trained in framework should edit, so a separate set of configs hides this from the end user developer. I am not sure I personally agree with this, but it is what it is. This comprises the first part of the “equation” that prompts this entry.
The second part of the “equation” is the use of IoC containers, in particular StructureMap, so different implementations of an interface can be spun up at run time. In the latest versions of many IoC Container projects, the container is populated using registries coded in a .NET language. You then discover the many “registries” and spin them up at run time.
Let’s look at the two issues separately and I will try not to go ADHD and find too many shiny things to add to the entry.
In .NET today, you have the ability to set up multiple configurations for an web application without any work on the part of the developer, other than adding the specifics to configuration. Out of the box, you have a configuration for debug and release, as in this web application:
It is a bit too bad you don’t automagically get this for all project types, but it is a foundation that can be built on. And, you can add additional specific configurations by simply adding new configuration definitions. Unfortunately, this has to be done at the global level, prior to creating the project, as there is no automagic “oh you have a new configuration and I need a specific config file” type of functionality. If you have just started a new project, you can delete the web config, create new configurations (Build >> ConfigurationManager) and adding:
If I then add a web configuration file, I see the new configurations:
Beyond the small bits above, the how of setting up new types, extending to other project types, etc., is beyond the scope of what I am talking about in this post. Just know that there is a system in place, at least for web application, and you can manually add to this system.
NOTE: The bits behind the multiple build configurations has more bells and whistles than this simple example. If you need this type of functionality, Google and you will find many examples.
On the current project I am working on, there are two concepts this does not solve.
- Hiding internal (framework) configurations from the end user developer
- Allowing customization of configuration at more than 2 levels
The end game looks something like this.
For the record, I am not fond of hiding configuration bits from end user developers. Sure, someone whacking configuration can cause problems that fall back on the team, but when the config is in the open, it is easy enough to say “didn’t I tell you NOT to do this?” … as long as you have it documented, that is. I don’t believe in using obfuscation through obscurity or hiding as a means of controlling “bad” behavior (was: technology does not solve process problems). As an analogy, is it better to hide a gun from your user, knowing a clever user might still find it, or send the user to a gun safety course? I vote for the later (neither will save you from someone “going postal” in their code, of course, but that is another story).
I am also not convinced that customization at multiple levels is a need. It is a nice thought exercise, but the actual use cases where it is NEEDED are very small, perhaps even non-existent. I am separating wants from needs, as there are probably others who WANT a multiple level “configuration conglomerator” piece. Assuming you actually NEED something like this, I can offer a few suggestions:
- Consider moving the configuration processor to build time, so the combined configuration file appears in the /bin folder. If you want to obfuscate through obscurity, to hide elements from the developer, you can’t use this, but I have stated my feeling about hiding the gun, where he can still find it, over sending the user to a gun safety course.
- Write out the end configuration, even if the configuration is completely pulled from memory at run time. if you have the file dumped, you have the ability to read through it and discover where the problem lies without searching or debugging. In fact, if you make a tool that creates config for all enviroments you can check before you deploy (defensive deployment – what a freaking concept!).
On the project, IoC containers are also used. For those not familiar with IoC containers, they are essentially a property bag of concrete implementations for an interface, with a factory to produce the concrete implementation. The general scenario is configure a variety of concrete implementations for your interfaces as the application bootstraps which are then used at runtime. Every IoC Container I know allows the developer to either explicitly implement a concrete implementation (by name, for example) or have it automatically get the correct instance based on configuration and rules.
We are using StructureMap currently, and it has the idea of a coded “registry” to set up the IoC Container “property bag”. Essentially, this means the bits you would normally have in a configuration file are now coded and included in your library.
The positive side of coded registries is you can offer multiple implementations out of the box, so the developer simply calls the correct one (based on how you have set up, so perhaps by name, but perhaps by another means – not important for now).
The negative side is when they have to be overwritten at the application level. It is not a big deal if you have one framework coded implementation that is overridden by a single application, but it can be overly complex once you start stacking different layers, as the config files were in an earlier picture. If anything is loaded in the wrong order, you can end up with a disaster. And catching these types of mistakes involves setting up your own instrumentation.
I am not fond of complex systems. I am less fond of adding multiple complex systems on top of each other. That leads to …
Code Versus Configuration Files
I was not going to jump on this when I initially jumped into this entry, but code versus configuration files is an age old question. In UNIX, files are the norm, even beyond configuration. In MS-DOS and early windows, you had the .ini file. As we started into the NT age, the idea of registry came about for configuration and in the COM age, the registry helped facilitate DLL hell. When we moved to .NET, we went back to configuration files. Now, many of the projects are going to coded configurations (like the registries in StructureMap).
ADHD moment: I personally can see an argument for both types of methodologies, but you have to set some rules around their use. In my world, a good delineation would be to use the registry to offer instances and then configure with a file in your application. Or perhaps, you are releasing a library as a product (internally or for sale) that contains multiple implementations. This is especially true if you don’t see the average user extending the system. If so, I would likely argue for configuration files again. NOTE: The specific examples above are unimportant to the post beyond giving a mental picture.
Back to our regularly scheduled show: What is dangerous is when you end up with part of your configuration in a configuration file and the rest in some coded construct. If you have to add a lot of flexibility to your configuration, then it is probably best to leave everything in configuration, with the shipped library as product being a possible exception. A single multiple file/step process is better than 2, especially if the processes are complex.
Disagree? I accept that may be true where you are, but I see this in practice where I am today. An application is working fine in staging and it goes to production and something goes to hell in a hand basket. If I have a domain expert, he might be able to say “that is config” or “that is IoC”, but a non-expert will have to step through things. And, when you have multiple complex systems you either force rollback or increase downtime. Ouch!
Actually, I will punch the baby for a bit. I am not sure I agree that going back to coded configuration is a good idea, except perhaps as packaged software. But, even with the packaged bits, I see Microsoft stating “if you add this, you have to add this to configuration”, so the precedence is “allow the user to customize configuration and guide them”. And, you can create VS tools or templates to add the bits, so it is not a huge deal.
I also find that hiding all of the bits to solve the package problem, but creating a huge extensibility and perhaps maintainability problem is a big mistake. And, I find many who move away from this direction do it simply because they don’t like to write documentation and guide users/developers. Is this really wise?
Note I am not against the registry concept completely, I just don’t see value in most of the scenarios I see it being used in. I see it adding more complexity for very little benefit, at best.
I probably sidelined a bit and this ends up more as a rant, but let me see if I can make some points that you might be able to take home.
- If you find you are using multiple systems to configure an application, consider refactoring to one. In fact, seriously consider it.
- If you are packaging a utility library with multiple implementations (perhaps a SQL versus Oracle versus MySQL), you can considering moving this out of the registry. Consider the extensibility likelihood in the mix, however, as you may make your software hard to extend in the process of making “use it out of the box” an easy scenario.
- In everything in software, consider all of the needs before firmly committing to a direction, especially a direction that adds complexity.
Feel free to comment, as I would love other points of view. This is a random post and I am going into more of the “Core as Application” direction in the next series I will start shortly.
Peace and Grace,