LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Mutation History of Enums

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? )

0 Kudos
Message 1 of 24
(4,411 Views)

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.


___________________
Try to take over the world!
0 Kudos
Message 2 of 24
(4,396 Views)

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.


Paul
0 Kudos
Message 3 of 24
(4,389 Views)

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.

Message 4 of 24
(4,378 Views)

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.

0 Kudos
Message 5 of 24
(4,378 Views)

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

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
Message 6 of 24
(4,368 Views)

 

> 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.

 

22657i393749CDAAB32F34

 

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:

 

  1. Start, v1: {Alpha, Beta, Delta}
  2. Insert Gamma, v2: {Alpha, Beta, Gamma, Delta}
  3. Swap Gamma/Delta, v3: {Alpha, Beta, Delta, Gamma)
  4. Delete Alpha, v4: {Beta, Delta, Gamma}
For each run, the write accessor set the private class data to "Delta", as can be seen by the last two bytes of the four Flattened Data controls (0002, 0003, 0002, 0001 all correctly correspond to "Delta" for that revision). However, look at the Result array - the Read always returns the default value, ignoring the flattened value altogether.
 
Of note: the enum is a typedef. I tried to do this exercise with a non-typedef enum for the private data member, but it was quickly evident that a non-typedef enum would require insane amounts of maintenance both within the class implementation, the interface, and the callers. No, thank you.

 

0 Kudos
Message 7 of 24
(4,355 Views)

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)


"Should be" isn't "Is" -Jay
0 Kudos
Message 8 of 24
(4,347 Views)

 


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.

0 Kudos
Message 9 of 24
(4,335 Views)

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

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
Message 10 of 24
(4,318 Views)