BreakPoint

cancel
Showing results for 
Search instead for 
Did you mean: 

LV OOP small tutorials and introductions in a "workshop style"

Hello!

 

Previously somewhere else I mentioned I am still a "classless" LV developer. In the last couple of years I could not find a single resource which could push me over "my barrier". Most of the resources I do not find "comfortable", or I feel big part of it just wastes my time or bores me (like the self-paced online training for OOP, with those sound player demo stuff). I am sure the problem with me, I guess other programmers are fine with the available resources...? 🙂

 

So what I am doing recently, I try to collect together small pieces, smaller tutorials/workshops which give me usage ideas how I could use OOP in my projects in a helpful way.

One small example is here: https://forums.ni.com/t5/LabVIEW-Development-Best/Introduction-to-Object-Oriented-Programming-and-Ha...

 

I have some more complex and advanced sources for later "digestion" (here and here), but I feel I should play with small tutorials first. My question is that, are you aware of resources of simple small tutorials, or even complex ones but with a step-by-step nature to build up more advanced examples?

 

Right now what I am thinking of which parts of my projects (or my personal User Event based frameworks) could benefit from using OOP. I imagine, my recent intercom User Event/Queue/Stream messages (consisting of an enum/string and a variant) could become Classes. The immediate benefit as I read somewhere, would be that the msg data parsing errors could appear during compile and not during runtime (if I try to use the wrong data type for the "variant to data" function). Another big improvement would be to create a "RS232 class", since my projects use lots of different vacuum sensors, flow controllers, etc, all with very similar feature set and serial request/response communication scheme...

 

Thanks for any hints and advices! 🙂

Message 1 of 31
(7,783 Views)

Personally, I would suggest that one ignore dynamic dispatch entirely at first, and just use classes as a nice way to package a type-def cluster and all the subVIs that access the internals of the type-def cluster.  This will show you the benefits of encapsulation and get you familiar with the LVOOP editing tools.  Only then should you consider the fact that LVOOP type-def clusters are extendable, and find the simplest possible application for that.  Do not read anything about "patterns" yet, and do not try actually use it in something "reusable" (as that is always more complicated).

Message 2 of 31
(7,764 Views)

@Blokk wrote:

 

Most of the resources I do not find "comfortable", or I feel big part of it just wastes my time or bores me (like the self-paced online training for OOP, with those sound player demo stuff). I am sure the problem with me, I guess other programmers are fine with the available resources...? 🙂

 

So, a couple years back at NI week I decided to take the LVOOP class (started Sunday if I recall so I showed up early).  It was disappointing enough that I didn't even bother showing the second day of the class - and I know I'm not the only one. 

 

I went through all of the materials and it was primarily "here is how you make a class inside of the LabVIEW IDE" rather than "here is why you would want to make a class, and here is how you use classes inside of a project"

 

I agree that the resources out there on LVOOP leave something to be desired.  I also agree with drjd that just use them as a nice encapsulation to start with.  As it turns out once I finally made the dive and started using classes in projects - it wasn't really much different than what I'd been doing anyway.  It just forced a little more rigor on using typedef clusters.

Message 3 of 31
(7,712 Views)

Thank you both for the insights! If you do not mind, I would have some follow up questions, I would like to see more clear and to understand better the differences between methods.

I will think about how to properly wrap-up Typdef cluster messages (usually string/enum + variant elements in cluster) into classes (for Queues, Streams and User Events), and what are the benefits/cons.

 

But first, I am thinking about those lvlibs which I usually create for hardware operations, File logging, Data manipulation, etc. So what I often use, is an lvlib with private typdef cluster to store data and a single Action Engine made also private. I wrap up the different "methods" into public VIs which I can call from my general VIs. So actually this also hides all wires, if I initialize for example some hardware, the HW reference/parameter list is stored in the Action Engine, and next time I can call other methods, since the HW is initialized. Pros are hiding the wire, and protect the Action engine being private. Cons, as I imagine, there is possible problem with execution order, and keep track where I placed the public VIs around in the main code, since there is no visual data flow dependence between them (no wire connects them).

Another such lvlib I often use, a kind of simple TDMS data logger: when I need, I init the file record from the GUI loop, and I have always active File log method VI running in a consumer loop. The internal Action Engine "knows" whether there is an active file record ongoing, and if not, it does nothing using a case structure inside. The "Close" public VI can be safely fired, since the Action Engine knows if there is ongoing file rec, otherwise no op.

 

I would like to hear criticism of the above wrapped up Action Engine usage scenarios via lvlibs. What are the main benefits if I start to use Classes? How should I turn my such lvlibs into classes?

0 Kudos
Message 4 of 31
(7,668 Views)

Blokk wrote:

But first, I am thinking about those lvlibs which I usually create for hardware operations, File logging, Data manipulation, etc. So what I often use, is an lvlib with private typdef cluster to store data and a single Action Engine made also private. I wrap up the different "methods" into public VIs which I can call from my general VIs. So actually this also hides all wires, if I initialize for example some hardware, the HW reference/parameter list is stored in the Action Engine, and next time I can call other methods, since the HW is initialized. Pros are hiding the wire, and protect the Action engine being private. Cons, as I imagine, there is possible problem with execution order, and keep track where I placed the public VIs around in the main code, since there is no visual data flow dependence between them (no wire connects them).


Ben has actually coined this to be "Pseudo-OOP".  You have the principles of encapsulation already there.  The only real difference with going with LVOOP is that you will now have a wire holding all of your data and enforcing your data flow.  As you already stated, it becomes easier to keep track of where this object is used.  You also gain the benefit of being able to have multiple instances of your object (think having 2 power supplies) without having to code anything to manage them.  Then you also get the benefit of inheritance where you can have different types of power supplies and your main code does not care which one is being used.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 5 of 31
(7,661 Views)

@crossrulz wrote:

Blokk wrote:

But first, I am thinking about those lvlibs which I usually create for hardware operations, File logging, Data manipulation, etc. So what I often use, is an lvlib with private typdef cluster to store data and a single Action Engine made also private. I wrap up the different "methods" into public VIs which I can call from my general VIs. So actually this also hides all wires, if I initialize for example some hardware, the HW reference/parameter list is stored in the Action Engine, and next time I can call other methods, since the HW is initialized. Pros are hiding the wire, and protect the Action engine being private. Cons, as I imagine, there is possible problem with execution order, and keep track where I placed the public VIs around in the main code, since there is no visual data flow dependence between them (no wire connects them).


Ben has actually coined this to be "Pseudo-OOP".  You have the principles of encapsulation already there.  The only real difference with going with LVOOP is that you will now have a wire holding all of your data and enforcing your data flow.  As you already stated, it becomes easier to keep track of where this object is used.  You also gain the benefit of being able to have multiple instances of your object (think having 2 power supplies) without having to code anything to manage them.  Then you also get the benefit of inheritance where you can have different types of power supplies and your main code does not care which one is being used.


Thanks! I start to feel the power! 🙂 It happened before that I got a second identical device (MKS PR4000), and with my actual wrapped lvlib method, I had no other straightforward solution than I just duplicated the lvlib, and saved the second under different name. I felt it is just way stupid, "nicely" scalable to N+1 😄

 

If I use a class, as you say, I can just have multiple instances without any coupling! 🙂 It is obvious now, but why I did not think of its importance before??! 🙂 So actually I eliminate the action engine and the internal shift register! The class wire will hold all the data. Hmm, this will simplify things a lot. And I even did not consider inheritance, but I wanna go in small steps 🙂

Thanks again, some mosaic got in place now...

0 Kudos
Message 6 of 31
(7,655 Views)

Blokk wrote: And I even did not consider inheritance, but I wanna go in small steps 🙂

That is for the best.  Things can get quite tricky when you start thinking about inheritance and turning that into a HAL.  Get used to using objects and the rest will come.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 7 of 31
(7,651 Views)

I am checking which of my many lvlibs would be a good candidate to turn it into a class. As it was discussed before, one advantage of using a class is that, the class wire holds all the info, so for example it is easy to program communication with two identical hardware interfaces. 

Question: if so, I guess usually (always?) all method VIs in a class should be set to "Preallocated clone reentrant execution", with the same logic as in the case of the DAQmx VIs. Is this correct?

0 Kudos
Message 8 of 31
(7,589 Views)

I don't think I actually change that setting in a very large majority of my VIs, even OOP methods.  So I have been just fine with using non-reentrant.  If you want to be reentrant, I would probably lean more to the shared clone variety to save a little memory.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 9 of 31
(7,576 Views)

@crossrulz wrote:

I don't think I actually change that setting in a very large majority of my VIs, even OOP methods.  So I have been just fine with using non-reentrant.  If you want to be reentrant, I would probably lean more to the shared clone variety to save a little memory.


If we keep OOP method VIs non-reentrant, there is always a danger that parallel executed same VIs, like a read method for two or more IDENTICAL hardware interfaces will block each other partially time by time, no?

 

Ihave no idea how it works in case of inheritance, like if there are two SIMILAR hardware interfaces, and we use two differently inherited classes. I guess in this case the two inherited slightly different Read methods cannot block each other even if they are non-reentrant? 

 

0 Kudos
Message 10 of 31
(7,574 Views)