Jump to content

Editing an existing class


Recommended Posts

Excuse me while I vent, but I can't be the only one in this situation.

Let's see if this sounds familiar to anyone, as an exercise we'll play a follow along game with how to add a control to an existing class:

  1. Open the class' .ctl file.
  2. Drop the new control in the private data cluster.
  3. Wait...
  4. Does LabVIEW recover? If no, kill LabVIEW.exe and start again at step 1.
  5. Rename the control so it has a proper name.
  6. Wait...
  7. Does LabVIEW recover? If no, kill LabVIEW.exe and start again at step 1.
  8. Save the .ctl file and move on.

This scenario has become all too familiar on a large project I work on, let's just say there better be a damned good reason for me to change any of those classes (and honestly, it's not that "big", it's just "LabVIEW big", maybe 1600 VIs). But I also have a much smaller project with maybe 18 classes (~250 VIs) and the inheritance hierarchy is at best, three levels deep. And now LabVIEW sees fit freeze indefinitely when I drop a new control on one of my classes.

Don't get me wrong, I love OOP in LabVIEW. Frankly, without OOP I would have relegated the language as a relic of the past and moved on long ago. But I'm getting a little tired of not talking about this dirty little secret. OOP is great, but it's not all sunshine and lollipops, there are some serious gremlins creeping around in there. I've been trying for over an hour to add a DBL to one of my classes and still no luck. Seriously? Come on now.

Mass recompiled my project? Check.

Flush my object cache? Check.

Surely this happens to others?

  • Like 1
Link to comment

It's the ctl that defines the private data cluster of the lvclass. Granted there is no actual ctl file, but it appears as so in the project explorer. I probably should have best described it as an item in the project explorer.

Editing the class outside of the larger project often works, but that's really avoiding the issue. For starters if the lvclass is part of a library, the entire library must be loaded to edit the class. Often when this issue creeps up, the class can't be removed from the library either, for if you try to do so, LabVIEW gets horribly confused.

I did manage to get all the functionality I needed added to the class. However I still can't delete legacy elements. Last night I left LabVIEW for 14 hours, and when I came back in the morning it was still chugging away after I tried deleting a DBL from the private data cluster. Oh well, I guess I can live with orphaned data. It's inelegant, but at least the functionality I need is there.

Link to comment
  • 1 month later...

I believe you. Really. I just don't see these crashes myself.

I probably develop more classes than most people on this list, whether it be apps on my own, quick demos for people who ask for them, or testing for CARs. I *don't* typically have the problems you're discussing when editing the private data control or renaming classes. Just today, I had a hierarchy four levels deep in which I had classes in one library. I moved some of those classes to another library, renamed them, moved them on disk and then deleted fields from the private data control and had no problems, before, during or after the operations. I do this on both my Windows machine at work and my Mac at home.

If you have a situation where this happens, I need you to file CARs. Even though I'm not working on them myself any more (see thread in LAVA Lounge from last week), I still care about the quality. My team has done a huge amount to stabilize LV classes over the years. We will do more if you bring it to our attention. This is especially true for those of you who use source code control and can provide before and after images of the classes if they become corrupted.

Link to comment

I have not had any serious problems since upgrading to LV2011. 2010 would crash on me when doing anything with a lot of classes.

But what I did not realize is that if I use a class in a library then all classes get loaded into memory. I have some libraries with a lot of classes in them and now have to think about breaking things up somewhat. Again, it has not proven to be an issue yet but I want to be proactive. I have a development system with lots of horsepower and ram but the applications get deployed on systems with fewer resources. I use the factory pattern to load a preconfigured child class of an abstract parent because I didn't want to load all of the classes. But the parent and children are all in the same library so I guess that defeats the purpose. From a library standpoint it makes sense (to me) to include all those classes in the same library.

Do you have any specific guidelines on what goes into a library as far as class hierarchies go?

Is there any way this could change? Could it be possible to load pieces of a library without loading the rest? I ask because maybe it is something for the idea exchange. I don't want to post it yet because I don't know if it is a good idea or if it is even doable.

Link to comment

But what I did not realize is that if I use a class in a library then all classes get loaded into memory. I have some libraries with a lot of classes in them and now have to think about breaking things up somewhat. Again, it has not proven to be an issue yet but I want to be proactive.

I went through something similar about a month ago. Most of my classes are not in Libraries now, which is not really what I would prefer, but it is necessary if I want to only load necessary software (every so often I open a new project, open a fresh VI, and drop a single object into it and see how much loads up under “Dependancies”). It’s more than just Libraries; any VI in a class that refers to another class acts as a “linker”, causing that other class to fully load in memory. It just takes a few linkers to get a sort of “domino effect” as class after class loads up.

  • Like 1
Link to comment

Could it be possible to load pieces of a library without loading the rest? I ask because maybe it is something for the idea exchange. I don't want to post it yet because I don't know if it is a good idea or if it is even doable.

I doubt it is possible. As soon as something is a member of a library, loading that item will force the library to be read so that item scope (among other things) can be determined. But when you load a library, LabVIEW must make sure that the library isn't broken, which demands that every item get loaded to verify status.

As DrJD implied, I think this effect propagates for linked libraries too. Break a VI that is part of a dynamic dispatch for example, you'll notice every method of every class in the hierarchy becomes broken until the single VI is fixed, never mind any other VIs that use these classes, and their libraries, ad nauseam...

Link to comment

What I’d like to see is for a LVLib to not automatically load its contained LVClasses until and unless something else in memory refers to that class. In other words, have LVClasses follow the same loading rule as regular VIs in libraries. That would allow me to organize classes in libraries without issue. It would be nice if LVClass libraries could load piece-by-peice, but that is less important and probably not doable.

— James

Link to comment
Do you have any specific guidelines on what goes into a library as far as class hierarchies go?
I discussed this issue a bit in the Actor Framework documentation. My personal policy is that "a library should contain intimately connected pieces that are almost always needed together for operations". In other words, your plug-ins and dynamically loaded content should not be in the same library as your core framework. In the case of the Actors, we've been making libraries that contain the actor and all messages that can be sent to that actor on the theory that each message represents a call to one method of the public API, and the public API is always expected to exist on a class.

I doubt it is possible. As soon as something is a member of a library, loading that item will force the library to be read so that item scope (among other things) can be determined. But when you load a library, LabVIEW must make sure that the library isn't broken, which demands that every item get loaded to verify status.

Only classes load all their member VIs. Regular libraries do not. Regular libraries do not care if VIs in them are broken as far as the functionality of other VIs is concerned. They do load all their member libraries, which, by the transitive property of "things that load things", means that a library having a class will load all the member VIs of that class.

Classes can relax this rule in the runtime environement, which we do when you deploy a class to RT, but we never found a satisfactory user experience in the dev environement without having all the members in memory. One weirdness was changing the name of a VI causing VIs of child classes to load or unload, and the unload case was especially weird if you got a Save Changes dialog -- no one expected Save As on one VI to cause a Save Changes dialog on a bunch of other VIs. There were multiple other weirdnesses. Eventually we decided that loading everything in a class is mostly ok since classes are generaly bundles of tightly related functionality such that if you need one part of the class, you mostly need the entire class. Mostly. As long as we could strip out unused methods when going to RT where memory is particularly tight, the tradeoffs seemed worth it.

What I’d like to see is for a LVLib to not automatically load its contained LVClasses until and unless something else in memory refers to that class. In other words, have LVClasses follow the same loading rule as regular VIs in libraries. That would allow me to organize classes in libraries without issue. It would be nice if LVClass libraries could load piece-by-peice, but that is less important and probably not doable.

Yes. I'd like this too. I hope they make something like this.

Ooo... that felt good... hoping something improves and not having to feel guilty that I'm not actively improving it... probably not a habit I should get into since I do expect to go back to direct LV development someday... ;-)

Link to comment
  • 4 weeks later...

I have had similar problems to mje's with altering a Private Data Cluster and having LabVIEW peg the CPU for longer than I wanted to wait (overnite once). Yesterday, I had another situation and wanted to share my work around.

Yesterday I wanted to start a new empty project and load my libraries one at a time to see what the dependencies had exploded to. I had an existing working project with all of the libraries. My project is heavily OOP with a hierarchy of up to 6 derived classes. Well, on the second library added to the project, LabVIEW2011 was trying to resolve something. I was about to hunker down for a long evening of disecting lvlib files but then I though about separating compiled code in my working project. I saved and closed the working project. Then I created a new one and added the two libraries. On the second one the dependent libraries came in fast with no problems.

I will have to look at the cross dependencies between libraries, but at least I loaded a fresh project and got to go home for the night.

Link to comment
  • 6 months later...

FYI: I've just posted on the Idea Exchange about improving IDE performance when working with classes. Would be nice to get some more visibility on these issues!

There's an ongoing "Idea Exchange" thread floating around on Lava users typically use to promote their ideas. Nothing wrong with putting it here, but it might get more visibility there.

It would be nice if LVClass libraries could load piece-by-peice, but that is less important and probably not doable.

It might be technically possible, but I think the side effects of doing that are much worse than the current behavior.

Have you ever edited a cluster only to discover later that some of the bundle/unbundle nodes have unexpectedly changed to an apparently random field? One reason that happens is because the vis with the bundle/unbundle nodes are not loaded into memory when the cluster definition is changed. When the vi is loaded after the edit, LV tries to map the old cluster fields to the new cluster fields. For certain combinations of edits LV can't tell what it should do and has to guess.

Loading all class members into memory when any single class element is loaded ensures that all bundle/unbundle nodes will be in memory in case the class data cluster is changed. If you take that behavior away users will be exposed to the same potential problems that exist with clusters. In theory I suppose it would be possible to postpone loading the entire class until the class ctl editor is opened, but there may be other reasons why that is unfeasible.

Link to comment

There's an ongoing "Idea Exchange" thread floating around on Lava users typically use to promote their ideas. Nothing wrong with putting it here, but it might get more visibility there.

Ahh... thanks for the heads up :-)

... In theory I suppose it would be possible to postpone loading the entire class until the class ctl editor is opened, but there may be other reasons why that is unfeasible.

I think this would be a great leap forward. A large number of class edits do *not* affect private data. It would be great if these edits could be made quickly and easily without necessarily loading a bunch of member VIs and dependencies.

Edited by fabric
Link to comment

I have experienced this a lot in the project I am working on. At first I thought it was something I was doing wrong. now that I found this thread and the discussion in the AF community, I realize that there is something going on with the IDE.

I continue to have my classes in lvlibs. The architecture I am working on has multiple QDMH with their messages wrapped in classes. Not as fancy as the Actor framework but it gets the job done. I like to have the messages inside the lvlibs.

So, my workaround has been:

Remove the class from the library

save

Disinherit the class

save

modify private data

wait for LabVIEW to take its time (if it is too long for my taste, couple of minutes, then I kill it and try again).

modify accessors/property nodes

save

inherit again

move back into lvlib

some times I don't have to kill LabVIEW at all, other times I have to. I have even gotten into a situation where I have two machines working in parallel and see which one can do the modification without choking.

Even after all this, I won't give up on using classes nor lvlibs. I like the project organization, name spacing and dynamic dispatch too much. But I wonder if I would be so optimistic if my project was larger.

Glad to know I am not the only one.

I hope Fabric's idea gets a lot more kudos.

Fab

  • Like 1
Link to comment

This issue continues to be a thorn in my side as well. I have classes that simply can not be edited while in the context of larger projects. Fortunately I've managed to pull all my classes out of library scope and when I need to edit them and run into trouble, I can shut everything down, open the bare class and make changes, then reload the project. This is not a good solution-- for one I need to spend the time unloading/loading all for the most trivial changes. More importantly is it precludes renaming anything, so I end up with absurdly named items and a legacy of orphaned/deprecated members since what I really want to do is change/move something but I can't...

If NI really doesn't see this issue often enough, I imagine I can throw my code into a package and sent it off to them, but I'm not even convinced any of these issues are that reproducible as I can go hours making some rather drastic changes to my classes, only to have the IDE choke up on something as simple as changing an I32 to an I64.

Link to comment

So, my workaround has been:

Remove the class from the library

save

Disinherit the class

save

modify private data

wait for LabVIEW to take its time (if it is too long for my taste, couple of minutes, then I kill it and try again).

modify accessors/property nodes

save

inherit again

move back into lvlib

What happens if you close the project, open an empty one, add the library with the class to be edited, and make the changes? Does the editing performance improve? Are your libraries interlinked to the extent that loading the library ends up loading the entire project?

Link to comment

What happens if you close the project, open an empty one, add the library with the class to be edited, and make the changes? Does the editing performance improve? Are your libraries interlinked to the extent that loading the library ends up loading the entire project?

I have not tried that. I have tried opening the library by itself and I have the same problems.

Link to comment

This issue continues to be a thorn in my side as well. I have classes that simply can not be edited while in the context of larger projects. Fortunately I've managed to pull all my classes out of library scope and when I need to edit them and run into trouble, I can shut everything down, open the bare class and make changes, then reload the project. This is not a good solution-- for one I need to spend the time unloading/loading all for the most trivial changes. More importantly is it precludes renaming anything, so I end up with absurdly named items and a legacy of orphaned/deprecated members since what I really want to do is change/move something but I can't...

If NI really doesn't see this issue often enough, I imagine I can throw my code into a package and sent it off to them, but I'm not even convinced any of these issues are that reproducible as I can go hours making some rather drastic changes to my classes, only to have the IDE choke up on something as simple as changing an I32 to an I64.

I think I can reproduce it with my code fairly consistently. I don't have the time now, because I am in the middle of a deadline... but when I am done with this project I will try to send my code to NI.

I will keep you posted.

Link to comment

I have not tried that. I have tried opening the library by itself and I have the same problems.

Yeah, that's not quite the same--it doesn't show dependencies. Adding the library to a new project will also yank in all the dependencies so you can get an idea of what else it is linked to. If it drags in a sizeable chunk of your project that could be part of the problem.

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.