10-25-2010 07:01 AM
aliasThree, instead of using references to the Main VI's controls (that's like sneeking on the top level VI, which does not sound like a very robust approach, expecially if you want to change your Main VI) you could instead have the Main VI send Dynamic Events to the sub VI each time one of the cluster components is modified. You would have to first define the Dynamic Event in the Main VI and find a way to pass the reference to that Dynamic Event to the Sub-VI (usually done via a LV2 global or even a global variable) so that it can register to it. You would have one event for each component (for instance the type of the event could be an enum listing the components you are interested in).
My 2 cts,
X.
Thanks for the response, X. I am passing references to the main fp objects via a functional global. I'm not sure what you mean by "sneeking on the top level VI"--do you mean "peeking"? And it seems robust in that, since the controls are typedefs, changes are pretty easy to incorporate.
What I've found, though, is that writing the cluster to a value (signaling) node queues events for each and every one of that cluster's componenets. For some stupid reason I hadn't expected that behavior, though it does make some sense, I guess. Further, writing a value (signaling) node for any particular component queues an event for the cluster, and that particular component, but not for any of the other cluster components. So my code is usable on the "receiving" side without modification; but the "sending" side has to be modified to detect the component that changed and write it, value (signaling), via that particular component's reference.
I now see the sense in how it works that I had kind of glossed over in my earlier understanding. My earlier assumption about how it worked was not as well-considered as it should have been. But, at least, that's one mistake I won't make again.
10-25-2010 11:56 AM
I wanted to edit my post to correct the spelling of "sneaking" but could not find my message again
(do I need to repeat once more that somebody needs to work on that "search" function on NI's website?)
I am not a CLA but it does not seem good practice to have subVIs assume anything special about the Main VI (name or structure of controls, for instance) like your approach requires. That's why I was suggesting going the other way around, with the producer signalling to the consumers that there is something new, rather than having the consumers spying on the producer...
My 2 cts,
X.
10-26-2010 06:53 AM
I wanted to edit my post to correct the spelling of "sneaking" but could not find my message again (do I need to repeat once more that somebody needs to work on that "search" function on NI's website?)
I am not a CLA but it does not seem good practice to have subVIs assume anything special about the Main VI (name or structure of controls, for instance) like your approach requires. That's why I was suggesting going the other way around, with the producer signalling to the consumers that there is something new, rather than having the consumers spying on the producer...
My 2 cts,
X.
No, I thought you meant "sneaking", I just didn't understand what you were getting at. I'm not a CLA either, but I still don't understand the "good practice" objection. I've always used the main VI as the user interface; but I don't want to tie it up with the bulk of code execution. So I execute the bulk of the working code in parallel subVIs. Given this construction there don't seem to be a lot of choices for getting data to and from the main VI's fp objects. I've found sub-panels difficult to work with from an aesthetic point of view (don't they have functional limitations as well, such as being inappropriate for remote panel usage?); queues are a little clutzy in their indirectness; globals are problematic. I find references to be the best solution.
I bundle all my main fp objects' references into a functional global so that they are globally available--even to any subVI. I develop the parallel subVIs in a stand-alone mode using references to the local fp objects, then migrate those fp objects to the main fp. So I have a switch on the subVI's diagram that lets me choose versions of fp objects to use. Event cases are configured for both versions, so with the flip of a switch I can develop/debug in either stand-alone or integrated mode.
Indeed, most subVIs I create care nothing about anything except their wired inputs, some of which may be references, though. But my parallel/asynchronous subVIs must have a relationship peculiar to the main VI--I don't see how I could go about making them..."universal"...at least not without going to a lot of trouble. To a great degree, references can be universal, or generic, allowing for no great knowledge of the referenced object being necessary.
10-26-2010 08:17 AM
I do something similar and am waiting for the rest of the world to catch up.
![]()
First off let restate that I am into re-use low-coupling etc etc. But as far as I have read into the high-faluting software speak, there is a point in an app where the code for the application is unique to that app and that app only. I have found this to be true in the top-level VI and its subordinates.
In an attempt to make it easy for my readers (my customers maintain the code when I am done) I break down the app into parts that make sense (high-cohesion) to someone that understand the domain (someone who could do it without the software). The following show this approach as I have implemented it.
Note:
For small applications this formalism will seem like over-kill.
This app has three mode of operation. Can you tell that from the diagram? Where would you look if you wanted to change the "analalysis" ?
Just after the Event Logger is launched (Rocket ship icon) you see me inititalizing an GUI Controller (AE) where I verify the refs are all valid (in large apps with many FP objects, it is very easy to forget to wire a ref).
If valie the refs are cached for use latter.
At code run time the Gui Controller is invoked to set the GUI state as shown in this sub-VI called by the GUI Controller.
When the user select an operating mode I call the sub-VI that handles that mode and it takes over. The image below shows what the analyis mode looks like.
So if you look at the above analysis code you will see that it has a high degree of coupling to the top-level VI, BUT provided the same types of FP object are available on another GUI, it will work there as well.
I hope this helps or at the very least get some people talking about how to implement complex code in LV sich that you can walk away from it and not fear that raving lunitic (who knows where you live) will someday take over your code.
Have fun,
Ben
10-26-2010 08:33 AM
10-26-2010 08:45 AM
@helmut O'Brian wrote:
Hi Ben,
Thanks for this great post.
Can you show us the BD of Get Ctrl Refs ? It's very interesting and I'm wondering how you build the cluster of control refs.
Regards,
That VI is a wrapper VI around the GUI AE that invokes a method "Get refs" which is basically a no-op but the SR holding the refs is wired to the ouptut of the SR.
But I am guessing that you want to know how I build that cluster of refs. Way off to the left of the first image there is a straight line state machine that buidls the cluster for each mode of operation.
I found an early version of this code in my image gallery and it give you a hint what is happening when the app starts up (look to the left).
Thanks for the kind words,
Ben
10-26-2010 08:47 AM
Very nice, Ben! I can't claim to be as thorough--or as artistic--as you, but I certainly agree with your points. I am curious though: what do you do in your "Handle Events" event structure's timeout case? Some kind of "heart-beat" signal? Again, thanks for the inspiration.
Elton
10-26-2010 08:52 AM
10-26-2010 08:54 AM
@aliasThree wrote:
Very nice, Ben! I can't claim to be as thorough--or as artistic--as you, but I certainly agree with your points. I am curious though: what do you do in your "Handle Events" event structure's timeout case? Some kind of "heart-beat" signal? Again, thanks for the inspiration.
Elton
Excellent question Elton!
That Q brings up an advantage of using sub-VI for each mode.
While in "Analysis" mode, the time-out is a no-op.
In the "Acquire" mode the Timeout event checks the queues coming from the various data collectors (The number and type of data collectors is driven by the configuration and realized using my version of a LVOOP Active Object) and keep the display updated.
so by using the sub-VIs with dynamic event registration, I am not burdened with keeping track of what mode I am in and if I should be looking for updates.
Thank you for asking!
Ben
10-26-2010 09:00 AM
@helmut O'Brian wrote:
Hi Ben !
Thanks for sharing !
Well, ok I get it 🙂 This can be a very huge cluster, it depends on the final application, but I guess we have no other choices !
Regards,
Well actually we do have a choice.
I could have code the sub-VI to go poking around in the top-level VI using control refs and find them by name or location. This would have made teh GUI cleaner but the coupling that approach would have placed on sub-VI with the top-level would have been wicked-tight and any change to the name or location (in tab pages etc) would have required changes to the sub-VI to account for the change in the GUI.
So I chose the approach that did not impose the tight coupling.
BTW:
Not all of our VIs take this approach. One of my rookies (a LCA and a CPI) wrote an XControl that dynamically build that cluster at compile time so in his version, no requirements imposed on the GUI and his appraoch is 100% re-suable across apps.
Again thanks for the reading and replying!
Your brother in wire,
Ben