Global Settings & Acquired Data
Reason
When I start developing software commonly used to store settings were structures that were binary saved to disk. The same structures were used to exchange settings between modules or even systems. At the end of the structure reserved bytes were added to accommodate additional settings in the future.
At the time the company I worked for used DOS and an extension ISA card with a dual RISC processor to process the data generated at 250 MByte/s by a video ADC (Analog to Digital Converter) where settings were exchanged using structures.
When request was made for an additional application setting that influenced the processing almost all code had to be touched to implement this new setting. This resulted in many weeks of programming and testing. The reason for this was that when a setting changes it needs to trigger the software to send it also to the other system. You can just tell it to set/send all settings again but this resulted in unwanted behavior. Some settings could be set always and some not when acquiring data. Settings had limits and were statically programmed into the GUI. When even a setting limit was changed the whole application needed to be checked and recompiled. The code on the RISC system had to correspond to the PC DOS code. Some integer settings were states where the UI produced a selection box.
In-short this was an unworkable situation causing many hours wasted and not to forget non-matched RISC system software was not compatible with PC software.
Also, unit-tests were something in the future... :)
This overhead made me think about creating a global interface for settings. (Later also for acquired data.)
Solution
First I needed a generic way of storing a setting in memory and on disk.
This was the Value class which could initially contained 4 different types:
* Undefined/Null
* Dynamically allocated string
* 4-byte signed integer
* 4-byte float-point (double)
The type name variant did not exist yet in C++98.
The Value class was used to create a static but dynamic list of VariableReferences class instances.
The VariableReferences was connected to a Variable class and registered itself at the VariableReferences in also a list.
This last list was to signal other Variable classes when a value change occurred.
The first entry in the list is the owner and creator of the reference.
A VariableReference instance is created by the owner using a comma separated string describing all
facets of the setting/variabel where the id is a number and the first field in the description string.
To connect a second not owning Variable to an instance created using that id.
The id's were ordered in such away that each device had its own id-range.
The Variable instance keeps track when a value or property changes distributes a signal to all variables connected.
To handle the signal events a virtual handler class is create and implemented by the using class and linked
to each Variable instance.
The user interface can automatically figure out through the id-mapping how and where to display the settings and when a setting was allowed to be changed.
The RISC system software when loaded serves a list (plain text) of variable descriptions for all settings available which the DOS-PC software has to process and then is able to build its UI dynamically.
After this was implemented adding or changing a setting only took a few hours since only the code in the RISC system changed and nowhere else so no testing for those part was needed. Focus was pure on the implementation of the new setting in the RISC processing software.