Immutable settings make settings updates easy
Sounds strange - huh? Here is the deal: Imagine you have a service running. It is happily processing incoming requests returning whatever it is supposed to return. Now imagine that in doing so it has to take into account certain global settings. The usual way to implement the settings is to put every value into a dictionary keyed by the setting name. The dictionary is owned by the service and every time some part of the service needs a setting value it pulls it from the dictionary.
In my case the service is the NDjango rendering engine. And to give you an example of a setting: an error string, a string to be inserted into the rendering result every time a django variable fails to resolve.
Now, what if you need to change a setting while the engine is running? The first thing which comes to mind is just go and stick a new value into the dictionary. Well... there are a few complications which may or may not be a real issue depending on what is the nature of the setting and how it is implemented. What if the change hits right in the middle of a request processing? Depending on the setting the impact can be anywhere from inconsistent response all the way through to the service crash. There is a number of ways to prevent such problems. You can clone the settings for every request. You can suspend processing, wait till all active request complete processing and only then apply changes. Or you can write your code so that every setting is accessed only once. All these remedies are difficult to implement and easy to break. Some of them can also have negative performance impact.
So how immutability can help here? Or better yet how can you change settings if they are immutable?
Here is something I picked up from my F# coding: instead of trying to change the values owned by existing service, create a new instance of service with updated values. Then leave the old instance deal with the existing requests and make sure that the new ones are directed to the new instance. This is a design pattern which certainly can be implemented in any language. Implementing it in F# provides additional safety of ensuring on the language level that the values are read only.
This design pattern can be used for any number of things - not just settings. In NDjango this pattern gave me a way to implement system - wide template caching with no global locks for templates already in the cache. Global locks are only involved when templates are loaded and parsed.