01-13-2010 08:52 AM
With a new project assignment thought it would be a good time to step up using labview's OO features. In my instance I'm trying to use a class to hold a bunch of different calculations. The calculations require several inputs to complete so I built a control to take care of this data. My plan was to build separate methods for each calculation. This will allow easy addition of new calculations and considering many calculations depend on prior calculations seems like a great opportunity to learn a new part of labview.
My problem is figuring out a elegant way to populate this large control; I believe I have to write accessor vi's to allow outside object access. I am not sure if there should be an accessor vi for EVERY parameter or if I can access these items as a cluster.
I can only relate to using get / set in .NET and typically I would write one for every variable I was access to; I am unsure how to do this in LabView. Any insight would be great.
I'm attaching a couple images. One showing just a sumple calculation and one of my ctl. Again, my main question is what is the best way to populate items in this ctl.
-Chris
Solved! Go to Solution.
01-13-2010 09:25 AM
You can create accessors by right clicking the VIs in the project window or by right clicking the controls inside the class cluster. In the dialog that you get, you can use Ctrl and Shift to select multiple elements so that you can create multiple accessors at once.
The unfortunate thing about this is that the icons created for these accessors are useless. One way of cutting down on some of that time is using Endevo's GOOP developer studio, which has all kinds of useful features. I don't have enough experience with it, so I can't really say any more.
If you have elements which need to be set together, you should consider using one VI to set them at the same time.
Also, there should be some tutorials, videos and white papers in the site and I suggest you start with those.
01-13-2010 09:48 AM
Since there is no such thing in LVOOP as public class members (and thank god/NI for that) you must always provide accessors (getters/setters) to reach class data members from outside the class.
Inside class method VI's there is no need for them since you can reach them directly from the wire with bundle/unbundle (as in your pictures).
I've implemented a similar class that performs calculations, and I choosed to use recursive calls to handle the problem of some variables must be calculated before others.
I have a Class member VI that is called GetCalculatedVariable.vi which takes the name of the variable to calculate as input (as typedefed enum).
Inside that VI have a case structure with a case for every variable that can be calculated.
Inside the case I define the calculation, and if I need another variable, I here call GetCalculatedVariable.vi recursively.
In addition I also have a CalcBuffer so I don't have to call GetCalculatedVariable.vi more than once for each variable.
The class also have a GetMeasuredVariable.vi which also uses recursion in the same manner, but operates on my measurement files instead.
The benefit is that my application code gets very clean as it only contains one single SubVI callto get and use any calculated variable.
I also have a GetCalculatedVariables that takes an array of VariableNames and returns an array of values.
Hope this helps...
01-13-2010 09:59 AM - edited 01-13-2010 10:01 AM
Sorry for the double post...
01-13-2010 10:00 AM
Leif -
Your example is exactly what I am trying to implement. I currently have VI's all over the place from previous test-setups so I am determined to build this new app cleanly. These same calculations are used over and over again so it had become critical I clean my act up to save time in the future.
I've never had to call anything recursively so I need to wrap my head around just how to do that as it solves the problem of having to run other calculations before I can complete the current requested calculation.
01-13-2010 10:18 AM
LeifS wrote:Since there is no such thing in LVOOP as public class members (and thank god/NI for that) you must always provide accessors (getters/setters) to reach class data members from outside the class.
Inside class method VI's there is no need for them since you can reach them directly from the wire with bundle/unbundle (as in your pictures).
I've implemented a similar class that performs calculations, and I choosed to use recursive calls to handle the problem of some variables must be calculated before others.
I have a Class member VI that is called GetCalculatedVariable.vi which takes the name of the variable to calculate as input (as typedefed enum).
Inside that VI have a case structure with a case for every variable that can be calculated.Inside the case I define the calculation, and if I need another variable, I here call GetCalculatedVariable.vi recursively.
In addition I also have a CalcBuffer so I don't have to call GetCalculatedVariable.vi more than once for each variable.
The class also have a GetMeasuredVariable.vi which also uses recursion in the same manner, but operates on my measurement files instead.
The benefit is that my application code gets very clean as it only contains one single SubVI callto get and use any calculated variable.
I also have a GetCalculatedVariables that takes an array of VariableNames and returns an array of values.
Hope this helps...
Hi Leif,
Accessors let child classes get at the data of the parent, so they have a purpose.
Re: a case .... for every....
My first thought would be to use dynamic dispatching so new methods can be added without touching what is already there...
In this thread I posted some code to to demonstrate one way Dynamic dispatching can be used to "Add A + B" as numerics or as strings. maybe that will inspire you.
Take the above with grain of salt since I am still learning as I go!
Ben
01-13-2010 10:27 AM
Are you saying that instead of creating ONE method with a large case structure to use individual methods for each calculation? That was the route I was taking; it was getting kinda big though as I was creating accessors for EVERY item in the ctl. Inside the accessors I would validate the input so I would KNOW without a doubt the data was valid before it would get passed to the methods.
Now I'm well more confused......
01-13-2010 10:36 AM
There might be smarter ways of implementing the "VariableCalculator" than the one I suggested, and initially I also thought of using inheritance.
It's almost a reflex to start thinking about how inheritance could be used when one stumbles upon "for each case... code in combination with arrays", but I couldn't see how that would help me.
It seemed that I had to derive a new class for each new variable, and that didn't feel good.
So I used one large case instead. Maybe not the most fancy solution, but it worked very well for me.
I'm attaching a sample of my VI.
/Leif
01-13-2010 10:47 AM
F1_Fan wrote:Are you saying that instead of creating ONE method with a large case structure to use individual methods for each calculation? That was the route I was taking; it was getting kinda big though as I was creating accessors for EVERY item in the ctl. Inside the accessors I would validate the input so I would KNOW without a doubt the data was valid before it would get passed to the methods.
Now I'm well more confused......
THe average size of my application (measured in VI count) has doubled since I switched over to LVOOPing. The Wizard Yair mentioned in the project makes creating the accesors easy.
Create an accesor for every item?
That maybe over-kill in the end if you have items that are only accessed in the parent and the children will never have to get at them or if items are only accessed as a group (cluster).
If you do a complete design of your class hiarchy and figure out the details of every method ahead of time, that would tell you better what fields need accessors and which do not.
What I have been trying to build and design toward is Class hiarchies where the Parents do most of the work and the Children use the methods of the Parents whenever possible and only what make the Child special requires coding. THat example i posted should demonstarte that idea where the childeren have very few methods.
As i understand it....
A well designed and implemented CLass hierachy gets simpler to enhance and support as you add more children.
Using a single case structure menas the code get more and more complex.
As i said I am sitll learning so don't take my opion as gospel.
Ben
01-13-2010 12:47 PM - edited 01-13-2010 12:48 PM
I think I'm starting to wrap my head around this.....
Lets say I have 3 different calculations to complete -
i. I have one ctl for the calculation class.
ii. I have 3 methods inside this class; one for each calculation.
iii. Perhaps the control has 18 objects (is this the correct term???) inside; only 8 need to be exposed via accessors as the rest are used internal of the class.
iv. I would code 8 accessor vi's to allow me to set and get the required data.
If the above sounds good; my only question is how to I deal with the problem of requesting say calculation #3 but I need to complete calculation #1 first before #3 can be completed? Is it possible to do that without using a case structure with recursive calls?
This is all very interesting but confusing at the same time....