Jump to content

Class mutation history


Recommended Posts

I've read the term quite often on here, but never really wondered what it was about. I just did a quick test to confirm what I thought...

If I get it right, it means I can save an object to a file (Write to Binary File), and even if the private members (and the class methods, I presume) change, I'll still be able to load that object back with a simple 'Read from Binary File'.

I'm guessing clusters (and other typedefs) don't have that feature, since we have a lot of trouble with super-clusters of parameters that keep on being updated as the project goes... We need some very complex auto-update of that data, which is painful to maintain, quite unreliable and annoying.

So if I get this right, I could simply use a class, and even if I load an old object from the disk, all the members that disappeared since then would be simply be ignored, and the members that were created would simply be set to their default value?

That's... like... black magic, man :P

I'm also guessing saving/loading an array of these doesn't matter either?

Also, if typedef'd clusters don't have that ability (I say 'if' cause I'm not sure), what would happen if a class has several clusters as members? What happens when these typedefs are modified?

Edit: Just read this http://zone.ni.com/d...a/tut/p/id/6316: "LabVIEW, as a graphical programming environment, has an advantage over other programming languages. When you edit the class, LabVIEW records the edits that you make. LabVIEW is context aware as you change inheritance, rename classes, and modify private data clusters. This allows LabVIEW to create the mutation routine for you. LabVIEW records the version number of the data as part of the flattened data, so that when LabVIEW unflattens the data, LabVIEW

knows how to mutate it into the current version of the class."

Pretty much confirms what I thought... still unsure about typedef'd clusters within a class, though.

Edit2: After reading the entire thing, I don't think I have any questions left :P I guess I'll just reiterate how cool this is, and how I'm a little pissed that I didn't know about this before... would have saved me a lot of trouble...

Edited by Samapico
Link to comment

Based on my own experience, it's probably not a good idea to flatten classes as binary data, and then expect to unflatten them with a more recent version of the class by relying on the mutation history. This includes persisting objects to disk, or flattening objects for inter-application communication between two executables with different versions of the class.

Two reasons it's not good to rely on the mutation history: 1) The history can get wiped out pretty easily, for instance by renaming the class, and 2) The mutation history stops recursively tracking data structure changes once it encounters a Typedef (including Enums and Clusters) as a private data member. (reason 2 can actually get you into trouble while developing source code, which in my opinion is a good enough reason to never place a Typedef inside an LVClass)

About the best choice I've found for interoperability or persisting arbitrary structures is XML. Although it seems tempting to rely on the "magic" of the built-in mutation, it would be pretty easy to get into a situation where you get burned unless you become a domain expert on making the mutation history behave wink.gif

Link to comment
About the best choice I've found for interoperability or persisting arbitrary structures is XML. Although it seems tempting to rely on the "magic" of the built-in mutation, it would be pretty easy to get into a situation where you get burned unless you become a domain expert on making the mutation history behave wink.gif

I'd agree, but I feel that you should use the best tool for the job. Storing complex data as XML (whether using the built-in XML functions or the super awesome JKI EasyXML toolkit <- if you haven't tried it, get a demo copy and check it out) certainly fits the requirements of a lot of use cases, but one thing I like the class mutation history for is when I have a bunch of classes (let's call them plugins) that grow over the years, and now I want to add something to the class and/or deprecate something else, because my plugin interface needs to change - the mutation history can certainly help. I'm not saying it's perfect (eg: typedefs), but if you know that your class structure will change (eg: an app that's going to be in service for a looooooong time, with many new plugins coming online relatively regularily) then, with proper planning, it's a good choice.

Link to comment
Mutation history is not maintained is this case.
Or, rather, the typedef is treated as a single element by the class. Since the class may or may not be in memory when the typedef is edited, the class can only know "this version of the typedef changed to this version" and it does the same "attempt to maintain value" that you get on a block diagram constant -- which sometimes means resetting to the default value.

Except for enums, I pretty much avoid mixing typedefs into private data controls these days. It wasn't something I avoided when classes first entered LV, but these days, I find it easier to avoid them.

Link to comment

Is the class mutation issue the only reason to avoid using type defs as data members? And does the mutation issue exist if the type def belongs to the class? (In this case, the class is guaranteed to be in memory when you edit the type def.) I've never had issues with type defs in class data, but I haven't really used the mutation history feature, and I don't think I've ever used a type def as a data member that didn't belong to the class (other than simple, unchanging things like enums).

Jaegen

Link to comment

[...] And does the mutation issue exist if the type def belongs to the class? (In this case, the class is guaranteed to be in memory when you edit the type def.) [...]

That would definitely be interesting... if the only reason why typedefs don't carry a mutation history is because the class isn't always loaded as you change it, then it would be good to implement it for typedefs that are part of a class, indeed.

Link to comment
That would definitely be interesting... if the only reason why typedefs don't carry a mutation history is because the class isn't always loaded as you change it, then it would be good to implement it for typedefs that are part of a class, indeed.
It would also require changing the flattened data format of typedefs (so that the data records a name and a version number instead of just the data). That's a pretty big change.

Even if "not in memory" were the only issue, I believe typedefs should behave like typedefs regardless of where the typedef is located in a source project. I don't want people putting typedefs that were unrelated to a given class into the class just to get the mutation as a side-effect. And there are people who like that typedefs do not store the history -- witness the size problems with LV classes that another user on the LAVA forum was having last week. The mutation history is this magical data store that continuously builds up over time. There are many who argue that it was a mistake for classes to add this ability because it is an unbounded resource (although we only unflatten the history if you actually start reading flat strings from earlier class versions).

Unless typedefs as a whole change, I would not recommend changing how they behave when owned by a class.

Link to comment

Thanks for the insight AQ.

I wasn't implying type defs should change - just asking whether the "don't add type defs as data members of a class" rule changes if the type def belongs to the class. If I open the class and modify the type def, doesn't a new version get saved to the class mutation history (since its data type has changed)?

Link to comment

From what I understand: Yes, but the typedef will be considered as 1 field, so if you load a previous version, the data in that typedef'd cluster will be entirely replaced by the new typedef with default values. That is, "unless the data can be directly converted", which I assume means that it will work if you just change the numeric representation of some of the values in the typedef.

The same thing would happen if you had a numeric field, and you changed its type. If you change its type to another numeric, it will be able to properly convert, but if you change it to a string, your previous versions will be loaded with the default string value.

Edit: Oh yeah, I'm now "Active". cool.gif

Edited by Samapico
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.