Jump to content

Editing an existing class


Recommended Posts

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.

Well, just tried it and of course it does pull most of the project in the dependencies. Which makes sense, because part of the classes inside each library are the classes intended for the messages for each library. Each message class is a child of the generic message class. So, all the libraries end up having some connection.

Now, I have this problem not only when I edit the messages classes, but also when I edit other classes in the libraries that might be unique to each library.

It is looking like the solution is to do away with lvlibs. However, like I said before, I really like the organization they provide. Plus it makes it easier to turn each lvlib into a separate VIPM package.

Fab

Link to comment

Well, just tried it and of course it does pull most of the project in the dependencies. Which makes sense, because part of the classes inside each library are the classes intended for the messages for each library.

Yep. That's been one of my two primary concerns with the AF--command-pattern messaging. It causes static dependencies to permeate the application to the point where you can't work on any single component in isolation. Developers have to write extra code specifically to break the dependencies.

Each message class is a child of the generic message class. So, all the libraries end up having some connection.

Nope. Child classes are statically dependent on parent classes, but parents are not dependent on children. Loading ActorA.lvlib will cause Actor Framework.lvlib to load, but it will not cause ActorB.lvlib to load unless A uses vis from ActorB.lvlib.

It is looking like the solution is to do away with lvlibs. However, like I said before, I really like the organization they provide. Plus it makes it easier to turn each lvlib into a separate VIPM package.

I really like lvlibs too. Given your time constraints that may be the best route for you. In the future you can prevent this by switching from an "input-only" messaging paradigm to an "input-output" paradigm. To do that with the AF you'll have to implement an event callback mechanism so the owning actor can tell the subactor at runtime which of the owning actor's messages to send when each event occurs.

Link to comment

3. Architect to avoid overly-complicated dependencies.

This should be item #1 in your list. The other two are possible because you do this first.

Dependency Management: For larger applications this is the most important requirement few people ever consider.

[Note to Elijah: Time to write another article.]

  • Like 1
Link to comment

I agree completely with you Mike, I have applications where such practices have produced easily editable code at any level.

However it doesn't help when dealing with old code where this issue already creeps up. Furthermore there are times where I'd have better luck squeezing water from a rock than getting a well defined set of requirements that will allow me to plan a proper level of abstraction from the beginning.

Link to comment

I am sorry to report that I had the opportunity to show this problem to AristosQ... and Murphy did its thing and LabVIEW worked as expected and I couldn't reproduce it while he was watching ... I guess is like when you take the car to the mechanic.

But I will keep jing ready and make a video the next time it happens.

Thanks,

Fab

Link to comment

I don't think anyone is doubting it happens, but for the record here's a video I made a few days ago when this issue crept back up to the top of the lava feed (no idea how to embed it).

http://www.screencast.com/t/e8szIGbKRz

Doesn't show much, just that it happens. I sped up time during the video, but it was a few minutes of me trying to add a numeric control to a class. Got so far as to add the control and attempt to change the name. I had to kill LabVIEW.exe before I even got a chance to change the control to an I64. By the time I produced the video I had let the IDE spin for about 20 minutes before killing it, but I've let it go overnight before and it has not recovered.

The ridiculous thing is when I went and edited the class alone, I then went back and opened up the original project and everything just worked, no big recompile times once it had to load the modified class. This is fairly typical when this happens.

The class in the video is very simple: it has no VIs except accessors, all are static and available through property nodes; not involved in any inheritance chains (except LabVIEW Object); and I'm pretty sure none of the fields are objects so it ought not to have any class dependencies.

  • Like 2
Link to comment

Thanks for sharing the video. It is good to know that I am not imagining things ;)

The class in the video is very simple: it has no VIs except accessors, all are static and available through property nodes; not involved in any inheritance chains (except LabVIEW Object); and I'm pretty sure none of the fields are objects so it ought not to have any class dependencies.

My classes also have static accessors available through property nodes. I wonder if that could be the problem.

Link to comment

My classes also have static accessors available through property nodes. I wonder if that could be the problem.

I'd rather not assume causation through correlation. While it might be possible, I typically define every accessor through property nodes and most of my classes don't have issues.

Link to comment

I'd rather not assume causation through correlation. While it might be possible, I typically define every accessor through property nodes and most of my classes don't have issues.

My bad... you are right, I should not assume, because when...

Hopefully NI finds what the problem is and it gets addressed. Fabric's idea in the idea exchange is getting more kudos, that is encouraging.

Link to comment

mje, dave: I was listing those tips for the sake of the newbies who might care to read as you vent your frustration

I knew what you meant and I think those are excellent suggestions.

Why may I ask?

Outside of dynamically loaded VI's, I've never had to consider this. Surely this is a deployment aspect rather than a design consideration.

Knowing the dependencies during deployment is important if you're deploying your app as components or have external dependencies. I don't do that very often, but I still pay strict attention to my dependencies during development because it has a huge impact on the development process. Poor static dependency management affects my ability to test code, reuse code, and make the correct changes to the code. I don't like to make changes unless I'm confident I know what will happen, and I can't know that unless I also know the dependencies. (Not just static dependencies, but behavioral dependencies as well.)

Furthermore there are times where I'd have better luck squeezing water from a rock than getting a well defined set of requirements that will allow me to plan a proper level of abstraction from the beginning.

Just out of curiosity, do you code primarily top-down or bottom-up? I've found bottom-up development to be much more flexible as requirements change over the life of a project.

For the past couple years I've been focusing my personal development on using implementation patterns and practices that support (relatively) easy and correct refactoring. My goal is to never have to say to a customer, "The application has outgrown this architecture. We'll have to rewrite it." I'm not 100% there (and probably never will be), and some changes that are more difficult than others, but I think I've got a fairly smooth path from a simple two loop single vi to a multi-target distributed application.

Link to comment

This may be the musings of an amateur, but can you not maintain slightly more component independance by having every message which expects to arrive at a certain component inherit from a message class designed specifically for that component?

So your inheritance goes:

Concrete Message for Component

inherits from

Component Base Message

inherits from

Base Message Class (with do.vi and all that other good stuff).

Only Component Base Message and it's children are included in a library. This allows you to specify the object data terminal on Component Base Message and all its children as a specific implementation of an Actor rather than the generic Actor class (to borrow from the AF). Then in my head, a messaging library will depend on a specific Child (and thus the base actor class), and the Base Message Class. Am I missing some obvious dependency channel?

Link to comment
  • 4 weeks later...

I too have seen this behaviour, although it was back in LV2010 (or was it 2011?). As soon as I removed the class property nodes from all the code everything *immediately* sped up drastically and the problem never came back. I think there is a CAR kicking around about this particular behaviour.

I'm not at work (or VPN'd) in right now, but I do know which CAR you're talking about. It was fixed in LV 2012. mje, neil, Fab: what version are you using? The bug was specifically that edits to a diagram with many LV Class Properties took a long time. The time was proportional to the number of unique property items on the diagram.

Link to comment

I'm not at work (or VPN'd) in right now, but I do know which CAR you're talking about. It was fixed in LV 2012. mje, neil, Fab: what version are you using? The bug was specifically that edits to a diagram with many LV Class Properties took a long time. The time was proportional to the number of unique property items on the diagram.

The project was in LV 2011. I will start using LV 2012 in my next project.

Could you post the CAR number, so we have something to mention if we see this behavior again in 2012?

Thanks,

Fab

Link to comment

I'm not at work (or VPN'd) in right now, but I do know which CAR you're talking about. It was fixed in LV 2012. mje, neil, Fab: what version are you using? The bug was specifically that edits to a diagram with many LV Class Properties took a long time. The time was proportional to the number of unique property items on the diagram.

Interesting. We are still on LV2011 and will remain so for another month or so.

I've spent quite a bit of time de-coupling my application in an effort to make it more editable. Basically I now have an application level project which defines the entire scope of the application, bringing in each component such that the run-time entity can be defined. Then a bunch of individual component level projects for working on each part by itself. If you look at the dependency tree for a component level project, each has some common framework ancestors as dependencies, the core application level object, and then whatever else it ends up using as it goes about it's business. With one exception no component is aware of other components. In some situations it has helped, but not others. Some classes remain un-editable in the larger application level project, the process for working on these classes is tedious at best:

  • Open the component level project to perform editing. Save. Close project.
  • Open the application level project. Run, debug, identify problem. Close project.
  • Open the component level project to do more editing. Save. Close.
  • Etc...

Fortunately this process only really needs to be done when some fundamental changes are being made to the classes. I never try to change the private data clusters from the application scoped project for any class. Deleting or renaming VIs can (but not always) throw LabVIEW into a tizzy. Generally editing an existing VI is fine, though you need to step into a cadence where you make an edit then wait for the compiler to catch up. What I wouldn't give for an option to have LabVIEW wait to recompile until the UI idles for a few seconds. Yes it takes me 30 seconds to wire up a VI because I have to wait. After. Every. Wire. Or. Constant. I. Drop. A few minutes of that usually ends with me closing the application project and going back to the component project only to switch back a few minutes later.

In the end though, I've actually learned a lot from all of this. I still don't know exactly why it happens, but I have learned a tremendous amount when it comes to large application development in LabVIEW. Over the years this project has grown so much and I am a far better programmer now for having to had tackle these challenges. For all my criticism of LabVIEW, I still love it.

  • Like 2
Link to comment
  • 1 year later...

I know there has not been any activity on this thread for a long time, but thought I'd give my 2 cents on our recent experience. Our (FairlyFunctional and my) medium size Actor Framework (~70 classes total, including messages) project started getting bogged down and updates to class data started incrementally getting longer, as well as moving things around in classes and libraries. In reading through this forum we first moved all of our classes out of libraries, which didn't seem to help, and then recalled Daklu saying something in this forum about clearing the mutation history, which I had to look up. 

 

It seems to me that many of the heartaches in this thread were due to mutation history. To delete the mutation history (see this Preserving LabVIEW Class Data whitepaper) you can either edit out the text of the .lvclass file, or rename the class and then name it back. FairlyFunctional added an add right-click option to delete class mutation history idea to the Exchange. We had a fairly large array of clusters that was initialized in the private class data, so every time we made a change to the private class data it was adding another copy of that array to the mutation history (at least that is my guess). If that is the case, another (and better) fix would be for LabVIEW to only update what changes in the class data for the mutation history instead of making a new copy of everything into the geneology.

 

My thought is that previously (pre LV2013?) moving a class out of a library would delete its mutation history, which is why that worked for many people. This idea to warn the user that the mutation history was being destroyed may have prompted the idea to not delete the history when moving it out of libraries?

 

-Sleepy Engineer

  • Like 2
Link to comment
I know there has not been any activity on this thread for a long time, but thought I'd give my 2 cents on our recent experience. Our (FairlyFunctional and my) medium size Actor Framework (~70 classes total, including messages) project started getting bogged down and updates to class data started incrementally getting longer, as well as moving things around in classes and libraries. In reading through this forum we first moved all of our classes out of libraries, which didn't seem to help, and then recalled Daklu saying something in this forum about clearing the mutation history, which I had to look up. 

 

It seems to me that many of the heartaches in this thread were due to mutation history. To delete the mutation history (see this Preserving LabVIEW Class Data whitepaper) you can either edit out the text of the .lvclass file, or rename the class and then name it back. FairlyFunctional added an add right-click option to delete class mutation history idea to the Exchange. We had a fairly large array of clusters that was initialized in the private class data, so every time we made a change to the private class data it was adding another copy of that array to the mutation history (at least that is my guess). If that is the case, another (and better) fix would be for LabVIEW to only update what changes in the class data for the mutation history instead of making a new copy of everything into the geneology.

 

My thought is that previously (pre LV2013?) moving a class out of a library would delete its mutation history, which is why that worked for many people. This idea to warn the user that the mutation history was being destroyed may have prompted the idea to not delete the history when moving it out of libraries?

 

-Sleepy Engineer

 

Thanks for adding this, what you are saying regarding mutation history makes sense. I tend not to put default data in clusters in the private data, just as I don't put type def cluster constants that do not have default values in a block diagram (see VI Analyzer test for this one). 

Instead what I do is to add a method to my class that is called "Default.vi", and then generate the clusters there and return the default object that way. This way I don't have to worry about the mutation history and I don't have to worry about the organization of my private class changing. I can see now by your post why this practice inadvertently made things better for  me.

 

Thanks,

Fab

  • Like 1
Link to comment
My thought is that previously (pre LV2013?) moving a class out of a library would delete its mutation history, which is why that worked for many people.

 

Wait, are you saying that changing a class' library membership doesn't reset the mutation history in 2013?

Link to comment
  • 7 months later...

This was reported in Nov 2011 and I can't believe such unacceptable sluggishness isn't resolved in Labview 2013! The part that sucks is, to come out of this dilemma i.e. fixing the project with packed libraries is painfully slow too.

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.