From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Nested classes and HMI/DVR data exchange

Hello everyone, this is my first post here, I'll try my best not to do anything wrong.

 

I'm working on a quite complex software (I use LV 2012 on a Windows 8.1 machine) that can load several user interfaces: these contain the paramaters that must be configured, gathered in some typedef clusters according to different areas of interest (e.g. a form divided into "personal information" - name, surname, address, etc., "company information" - name, hub, etc.). Every interface corresponds to a LV class with its DVR; classes used to be made of the same typedef clusters of user interfaces (and of some extra data), so that updating values in the DVR after HMI parameters were changed or vice versa was very easy. However, the program suffered lots of problema when I modified or added parameters to one of the typedef clusters, in addition to having some unnecessary data mapped in classes (i.e. strings that are inserted in HMI clusters for aesthetycal reasons, but could be substituted by controls labels in classes); when I came across this topic I understood that my problems could be caused by the presence of the typedef clusters inside classes. Therefore I'm now working on a different building of the classes that doesn't include typedef clusters: my current attempt calls for three levels of classes, as figured in the image below:

Nested classes.PNG

The controls of the 3rd level class are the same I have in the user interface (except for the label strings I mentioned before); there are no inheritances in this system, since 1st level classes are made of 2nd level classes (and of the other data) exactly as a polygon is made of line, and the same is for 2nd and 3rd level classes. Also, different interfaces correspond to different 1st and 2nd level classes, but some 3rd level data clusters can be the same; this is why I use 3rd level classes.

What makes me doubtful about this is the code needed to access 3rd level classes data; due to the amount of parameters to configure, I'd like to access both a 3rd level class and the corresponding HMI typedef cluster entirely when I change one of their parameters, otherwise I would need hundreds of methods and hundreds of events in the structure intercepting user changes to interface parameters. This made me create only one read method and one write method for each 3rd level class that manages all the data "converting" a LV class to a normal cluster:

3rd level class method.PNG

On the one hand I understand this is quite paradoxical because I incapsulated data in LV classes and the only methods I created convert them into normal clusters, but on the other hand I need 3rd level class data to be reusable in different parts of the program and I can't use typedef clusters in classes, so I can't find a better way to accomplish my objective. Also, the access to three consecutive levels of classes makes some parts of the code quite intricate, so I'm wondering if I'm really using LVOOP properly; I'm not extremely expert in LV, since I saw it for the first time 9 months ago, so maybe there could be something useful I don't know.

 

In conclusion: hoping to have explained my situation well enough, can anyone give me any suggestion about something better that this I could do?

0 Kudos
Message 1 of 4
(3,123 Views)

I can't comment on everything because I'm not 100% sure where the problems lie but some text got my attention:

 


@Cente90 wrote:

What makes me doubtful about this is the code needed to access 3rd level classes data; due to the amount of parameters to configure, I'd like to access both a 3rd level class and the corresponding HMI typedef cluster entirely when I change one of their parameters, otherwise I would need hundreds of methods and hundreds of events in the structure intercepting user changes to interface parameters. This made me create only one read method and one write method for each 3rd level class that manages all the data "converting" a LV class to a normal cluster:

 

-image not copied-

 

On the one hand I understand this is quite paradoxical because I incapsulated data in LV classes and the only methods I created convert them into normal clusters, but on the other hand I need 3rd level class data to be reusable in different parts of the program and I can't use typedef clusters in classes, so I can't find a better way to accomplish my objective. Also, the access to three consecutive levels of classes makes some parts of the code quite intricate, so I'm wondering if I'm really using LVOOP properly; I'm not extremely expert in LV, since I saw it for the first time 9 months ago, so maybe there could be something useful I don't know.


While such structures feel "good" and "proper" when designing them, trying to leverage re-use by implementing fields of classes as classes themselves, the inability of the IDE to scale with this is soon apparent.  This is not a LabVIEW problem per se (from a language point of view) but rather a limitation of the IDE (the two are intertwined, but separate entities).

 

The need for truckloads of "passthrough" or "proxy" VIs just to get at class data or methods at level 3 is painful.  I've been there myself and some of that code is currently in our main software but I'm eyeballing the option of actually refactoring the nested objects out again.

 

Regarding your typedef problem, even if your class data itself is not a typedef, just make the output of your Accessor VI a typedef.  Assuming you access the data only via the accessor, this will then propagate the typedef as if it would be part of the class data definition.  This is an example of encapsulation helping.  Your code calling the Accessor doesn't need to know (can't actually know) if the internal class representation is the same.

 

Apologies if I've misunderstood your intent.

Message 2 of 4
(3,094 Views)

Thanks for your reply, it seems my approach makes sense, which is very useful for me to have confirmed. I'll follow your suggestion and make my output clusters typedefs.

0 Kudos
Message 3 of 4
(3,080 Views)

To be more clear.  It makes sense in a logical way.

 

Having said that, I cannot comment on your SPECIFIC use case because I am too unfamiliar with the actual purpose of the code.  Therefore I cannot (without blatantly lying) endorse the SPECIFIC code.  I can say, however that the idea of partitioning up a main object into smaller contained objects is a common use of OOP, it just sometimes doesn't translate too well into the whole IDE / LabVIEW experience.

 

Where the "line in the sand" is regarding the tedious creation of accessor VIs for objects 3 layers down.... everyone has their own opinion on that.  Just bear in mind that this can be a SIGNIFICANT factor and if you have another way of solving the same problem, you might want to consider that.  Hopefully at some stage this kind of thing will become much easier in LabVIEW.

0 Kudos
Message 4 of 4
(3,069 Views)