I am interested in refining how I deal with configuration data and configuration files. Dealing with config files is a real pain, because the files need to be read at start-up, saved when something changes or at exit, and routed all over the place to get used by any routine that needs configuration information (I do a lot of converting data from volts to meaningful units, so there is a lot of conversion factors running around).
Here's some options, from simplest (and broken) to more complex (and better). Needless to say, I have questions and want input on the latter
:
0. Have a subroutine that reads or writes (based on an enum) a custom file format from the hard disk and outputs all configuration data as a cluster. Wire this cluster to a global in the top level routine and use the Globals whenever they are needed. This is #0 because I've had terrible luck with Globals and I now avoid them all together.
1. Same as above, but instead of using globals, wire the cluster directly to all sub-VIs that need it. This makes for a mess of wires for large applications.
2. Same as above but use TDM instead of a custom file format. I haven't done this yet, but TDM seems pretty useful. Does it have any major problems?
3. Use the TDM file format and create a subroutine that reads from disk, writes to disk, reads to functional globals and writes to functional globals based on an enum. Bundle all of the data into a cluster and use it locally in every VI that needs it. Only use the reading and writing to the hard disk for start-up and exit. I haven't done this yet, but because functional globals are reasonably efficient, and I no longer have to pass the clusters all around, there shouldn't be too serious of a performance hit here. Is that right?
4. Is there a way to load only the data that is needed? For example, if there are 100 different pieces of configuration data (ints, doubles, strings, arrays, enums, bools, ... the works) and I only want 1 of them. I could use an enum to select which I wanted and then use functional globals and polymorphic VIs, however I think the enum would have to have the same items for each polymorphic instance, which would mean that a number of bogus states exist (for example, if the enum is for an int type, but a string is wired up). Variants also seem like an option, except they would have to be cast outside of the calling routine, which is not good. It seems like polymorphic VIs could be a good way to go, but then all of the routines need the same number of inputs and outputs, so this could get difficult if I want a group of configuration items, for example 20 of the 100.
The behavior I'm after is like a DLL. I want to call a specific function from a sub-VI and have each function have it's own inputs and outputs. Some limitations (like the number of inputs and outputs) would be okay. I'd like to not have to actually build a DLL out of many VIs because it's easier to code, and actually possible to debug, without the application builder step.
What's the right thing to do? If #4 doesn't work out, I guess I could just make a different routine (TDM, read/write to disk, read/write functional globals) for each piece of configuration data and use them all locally. That would add a bit of extra work, but it would get rid of the clusters. Then, when all the bugs are worked out I could make one DLL out of all of my many routines. Then again, I could just skip making the DLL and leave it all in Labview. However, the clusters method seems efficient, so breaking up the clusters might cause a performance hit.
Is there a better way? Are there any serious pitfallls here? What's easy? What's fast? Any comments, conjecture, heckling or sage-like enlightenment is welcomed.
Thanks,
Casey