08-28-2010 08:30 PM
A class has an enum as a private data member, and the class is flattened and written to disk as persistent data. The enum private data member undergoes a mutation (add an element, rename an element, delete an element, or rearrange two elements), yet the mutation history of the enum is not stored along with other data structure mutation history of the class. Subsequently, when the previous version flattened class is read from disk and unflattened to the current version, the enum value loses integrity.
My main question is this: what's the best method for circumventing the problem that classes do not maintain enum mutation history?
(Specifically, what's the best method of storing an enum to file, then reading it later with the assumption that the enum may have been mutated in a manner that allows for predictable upconversion? )
08-29-2010 03:45 AM
Don't delete elements from the enum.
Don't add values in the middle.
Don't rearrange values
Only ADD values and ONLY at the end.
That's the only way I can think of offhand.
One other option, though - I'm guessing the enum is a typedef? I haven't tried looking at enum mutation in classes at all, but is it possible that it is working and that in your case it simply didn't work because you were editing the enum when the class was closed? The typedef obviously can't maintain the editing changes, since it's not versioned, but maybe the class could if it was open? My guess is that it's quite possible that the class is not maintaining the mutation data for typedefs, not for enums, since the typedefs are edited outside the class, but that guess would have to be checked.
08-29-2010 04:41 AM
If you are going to take the easy way of flattening the data... you run into this problem. However, if you disassemble the class member data into individual elements, you can save the data and then, in your case, load the enum as a string. By doing this, you can can check the persistent data against the current class member definition and load it if the stored data is present in the current class definition (regardless of its location in the enum), set it to a default value if it is not present (if that is desired) or warn the user if you like. I realize that this a fair amount of overhead programming, but then again... done right, you will have a palette of reuse VIs so that in the future this is a snap.
08-29-2010 07:21 AM
Alternatively, store your enum as a string, then make your accessors convert it to/from your enum. That way, you dont have to worry about the enum getting messed up in the flatten obj / unflatten obj primitives.
08-29-2010 07:21 AM
Alternatively, store your enum as a string, then make your accessors convert it to/from your enum. That way, you dont have to worry about the enum getting messed up in the flatten obj / unflatten obj primitives.
08-29-2010 09:50 AM
Use Format to string and Scan from string and it should work as long as the Enum elements dont change name as part of their mutation.
/Y
08-29-2010 12:05 PM - edited 08-29-2010 12:08 PM
> Don't delete elements from the enum.
> Don't add values in the middle.
> Don't rearrange values
> Only ADD values and ONLY at the end.
This is an undesirable workaround for a large enum that could potentially undergo several revisions - it would get bloated with "dead" items.
> One other option, though - I'm guessing the enum is a typedef? I haven't tried looking at enum mutation in classes at all, but is it possible that it is working and that in your case it simply didn't work because you were editing the enum when the class was closed?
I created a specific case-study VI (see below) to test enum mutation behavior for upconverting previous version data, and I'm certain the class was in memory and saved between versions.
PJS, shew82, and Yamaeda:
You're all reinforcing the best solution of which I was previously aware, yet it contains limitations. What if, for instance, an enum item contains a spelling error that you wish to correct, or you improperly named the item "thingamabob" when it should have been more appropriately called "whirleygig"? This is a limitation I can admittedly live with for most of my use cases, because it's robust against adding, deleting, and rearranging - it only falls short in renaming - the least likely mutation to occur on the enums I need to work with.
The biggest irk is that now, instead of keeping the enum datatype in my private class data, I must keep a string, transformed to the enum by the accessors. The convenience of bundle/unbundle of the private data inside class members is diminished.
That being said, I think there should be a native version and mutation history that should be stored in enums, or perhaps a "new type" of enum that's smarter than the current "legacy" enum. Keep your eyes peeled this week on the Idea Exchange if you agree with this.
Case study:
This VI was run for each of the four versions. The private class data underwent one enum mutation between each version as follows:
08-29-2010 12:27 PM - edited 08-29-2010 12:31 PM
Jack-
I'm not so certain that you want to play with enums this way (Although it would be SLICK) You cannot set the strings and values property of an enum while in run mode. This differes fro the ring control where the same property CAN be assigned while running.
I certainly cannot PROVE that this unique feature of enums is related to what you are seeing but,..... it does suggest both an approach to investigate and a potential work-around that may do what you need.
And I'll look for the "new enum" idea. For some reason I think a blue-bar may lift the lid a bit on the difference between enums and rings. (my precognition is good this week)
08-29-2010 01:01 PM
Jeff Bohrer wrote:I'm not so certain that you want to play with enums this way (Although it would be SLICK) You cannot set the strings and values property of an enum while in run mode. This differes fro the ring control where the same property CAN be assigned while running.
You misunderstand my purpose: I'm not talking about run-time mutations of the enum, I'm talking about design-time mutations. I know the differences between rings and enums, and enums are almost always more appropriate for type definitions (wiring into a case selector to get the text banner, updating items when typedef updates, etc...), whereas a ring is more capable UI construct.
You bring up an interesting consideration I have not thought about: maintaining mutation history of rings as well, and more generically, any typedef.
08-29-2010 04:46 PM
Changing the spelling of the Enum isn't any problem within the program, but as you say reading back old files will create some problems.
If the files are stored in a specific folder or database you could change them at the same time (or basically must to keep it working), else the read VI (or a mutation VI) needs to read and translate all spelling changes done. That could be rather easily done by reading from a Mutation file as such:
Current, Previous...
State1, Stat1, Stateone
Init, Int
When reading a supposed Enum it scans to see if it fits any of the words and if so exchange it with the first in the row. Then a normal Scan from string should work with the current Enum.
That or a upconvert VI for the files.
Backward compatibility is always a female hound. That's why most programs state "old save games not usable anymore".
/Y