I am wondering if I can get advice on the best approach on working with user settings.
My current idea of how to work with user settings goes like this:
1. Create a class to hold all of the user settings.
2. Use that class to load/save/hold settings in memory.
3. Create an instance of that class once in the entry point of the program (int Main or whatever).
4. Pass, by reference this same class instance around to all of the other classes that need the user settings.
5. Once all other objects deleted, save and then delete the User Settings class.
I created a psuedo-code example below of this.
My question is if this is the best way or should I be doing something else.
In particular, I am wondering if somehow I can avoid passing the settings class by reference all of the time.
Would this be a good case scenario for a "Singleton" type class?
A non-singleton approach is certainly more modular and robust. Personally, I avoid singletons whenever possible in order to keep APIs as flexible as possible for future growth. Who's to say that you are never going to want to keep dual configurations in memory at the same time?
The snippet was written under the assumption was that this function would not need to modify the configuration for the user. Otherwise, it need not be a const.
> If I wish to use a member function to write back configuration I can't do that, right?
Well, you can create another configuration object. For instance: user_settings::configuration( { "modified SettingOne", 234, false, configuration.UserSettingsPath }, user ) ;
Thanks, I like your second example with another configuration object, that would be the beginning of asynchronous read/write of configuration data, correct?
However, I would need to be constantly accessing the configuration data on disk for that.
Otherwise perhaps I shouldn't use const so that I can keep things in memory and just do I/O on loading and saving of configuration data at critical moments, like when Opening/Closing the application and when people hit up the Options/Preferences dialog of my application.
Well, in the snippet I posted the configuration is held in an in-memory data structure. std::map< std::string, config > settings // map user name => configuration
user_settings::configuration() just updates the configuration in memory.
It is written out / read from persistent storage only when save() / load() is called.
Since value semantics is used, what a component receives is a snapshot of the configuration at a particular point in time. It can modify its local copy of the configuration without affecting the rest of the program. A configuration change is percolated to the rest of the program only when user_settings::configuration() is called with a modified configuration. Configuration changes made by other components remain invisible till a fresh copy of the configuration is retrieved with a call to user_settings::configuration()
Reference semantics would lead to a quite different scenario.
> just do I/O on loading and saving of configuration data at critical moments, like when Opening/Closing the application and when people hit up the Options/Preferences dialog of my application.