Jump to content

Is LabVIEW Object Oriented or Actor Oriented?


Recommended Posts

This is my first post on LAVA although I have been using LabVIEW for five years.

I thought LVOOP in LAVA is the best place to ask this question so I am doing. I have been considering the Models of Computations (MoC) in LabVIEW, it is based on actor oriented design that is utilizing data-flow programming MoC and bla bla... But I couldn't answer myself why Object Oriented programming paradigm was required in an Actor oriented based design. Either we have a relation with OOP based languages that's why pushing OOP into LabVIEW or LabVIEW is not actually based on actor oriented programming paradigm or actually I don't understand it :rolleyes:

If LabVIEW is based on actor oriented design then shouldn't we exploit actor oriented design principles?

OBS! Remember this post is not related to Actor Oriented Design Pattern available in LV 2012.

regards,

Imran

Certified LabVIEW Developer

Link to comment

LVOOP is not "really" OOP unless you also use DVR....

Hmmm..., can you explain further what you mean by that?

In the glossary of T. Budd, An Introduction to Object-Oriented Programming, 3d. ed., we find:

"object-oriented programming: A style of design that is centered around the delegation of responsibilites to independent interacting agents and a style of programming characterized by the use of message passing and classes organized into one or more inheritance hierarchies."

I see similar descriptions of OOP elsewhere.

Certainly one can do all those things with native by-value objects!

Link to comment

Small disclaimer, I'm an engineer and not a computer scientist so I may be misunderstanding what you mean but here is my understanding:

The model of computation is how the software executes. In 'G' this is the dataflow paradigm. I would suggest that OOP or Actor oriented programming is a higher level than that. It is a means of design rather than execution and so we can use OOP with dataflow or other paradigms.

I am intrigued though about what principles you think would be useful, can you suggest any sites that discuss these?

Link to comment

On the original topic, my observation is that an actor and a UML component (which of course one often realizes with OOP) seem to be essentially the same thing....

The abstracts to these papers on actor-oriented design (http://www.google.com/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=1&cad=rja&ved=0CDwQFjAA&url=http%3A%2F%2Fciteseerx.ist.psu.edu%2Fviewdoc%2Fdownload%3Fdoi%3D10.1.1.230.1295%26rep%3Drep1%26type%3Dpdf&ei=srTQUK7fIMrjiwKI2oGgCw&usg=AFQjCNFpmCrg3Kg13RXHZjh7_rBbOlaSkQ&bvm=bv.1355534169,d.cGE, http://www.google.com/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=1&cad=rja&ved=0CDIQFjAA&url=http%3A%2F%2Fciteseerx.ist.psu.edu%2Fviewdoc%2Fdownload%3Fdoi%3D10.1.1.9.6762%26rep%3Drep1%26type%3Dpdf&ei=HLXQUJ3sE-eOiAKt3IDIDA&usg=AFQjCNFkPU5eV46p7bZYT9p01zHPSPmWIQ&bvm=bv.1355534169,d.cGE) are very interesting in this regard. (Take a look at a component in UML for comparison!)

There may be a fine distinction here, but I think actors and components are pretty much the same thing (and one of the abstracts starts with,

"Actor-oriented languages provide a component compositio methodology that emphasizes concurrency.")

So I guess my interpretation (I'm not an expert on actor-oriented programming, by any means) is that an actor (or a component) is a way of programming that emphasizes concurrency (and as such looks somewhat like dataflow, which is, I think, why LabVIEW appears in the abstract of one of the papers). Object-oriented programming aligns well with that concept since it emphasizes encapsulation, but of course it would be possible to implement actors or components without objects. With objects it seems to me to be easier since the concepts of encapsulation and delegation already are central themes. Actors/components and OOP are complementary concepts, it seems to me.

Link to comment

Thanks all for your replies.

So I guess my interpretation (I'm not an expert on actor-oriented programming, by any means) is that an actor (or a component) is a way of programming that emphasizes concurrency (and as such looks somewhat like dataflow, which is, I think, why LabVIEW appears in the abstract of one of the papers).

But my understanding is actor-orientation and dataflow do not fall in the same category, actor-orientation is a design notion and dataflow is a Model of Computation (MoC). Which is almost same as James wrote

"The model of computation is how the software executes. In 'G' this is the dataflow paradigm. I would suggest that OOP or Actor oriented programming is a higher level than that. It is a means of design rather than execution and so we can use OOP with dataflow or other paradigms."

If you get deeper into the definition of Actor-Oriented design you can design heterogeneous systems by utilizing different of MoCs not just dataflow.

Object-oriented programming aligns well with that concept since it emphasizes encapsulation, but of course it would be possible to implement actors or components without objects.

It seems a very good explanation but here I still have the same point as in my first post that why in one design notion (i.e. actor-orientation) you needed another one (i.e. object-oriented).

Please correct me if I am wrong since I am also an engineer not a computer scientist :)

Link to comment
Hmmm..., can you explain further what you mean by that? In the glossary of T. Budd, An Introduction to Object-Oriented Programming, 3d. ed., we find: "object-oriented programming: A style of design that is centered around the delegation of responsibilites to independent interacting agents and a style of programming characterized by the use of message passing and classes organized into one or more inheritance hierarchies." I see similar descriptions of OOP elsewhere. Certainly one can do all those things with native by-value objects!

I'm also "just" an engineer "cheating" in the programming department, but I have been programming for 25+ years. I use LVOOP for almost anything when using labview, but if you look at typical patterns used in OOP, most of them can only be implemented in a natural and stright forward fashion if you use references, typically an LVOOP in a DVR. Othervise LVOOP is an extension (a really powerful one) to dataflow paradigm, but not really OOP in a broad sense like OOP in C++. LVOOP is to dataflow like the ++ is to C, but LVOOP != ++ in a same manner as C != dataflow.

But the moment you start using LVOOP in a DVR, you can use all the patterns in the book. I have to admit that so far I have seen no real reason to do that. I use DVRs, but not like that. Dataflow + LVOOP has been the tools that works great for me. The actor thing looks really interesting though. I use a similar technique (I think?), but I use DVR to pass values between an arbitrary number of state machines, while the synchronizations are taken care of by dataflow alone.

Link to comment

Absolutely nothing about OOP requires a by reference design.

Even if 99.99% of OOP Implementations DO use references, it does not change the matter that the very nature of OOP does not demand either by value or by reference idioms.

Shane.

This is exactly correct. Nothing absolutely requires references it's just that some come from the perspective of C++ as THE gold standard for how OOP is to be implemented and, since C++ is generally taught musing byref constructs, it's implicit that such an implementation is "better" or "fundamentally different" in some preferable manner -- generally in terms of "ease", "readability" or some similar criteria in the mind of the person making that judgement.

Like almost all language related discussions, it reflects much more the biases and history of those involved in the discussion rather than any structural realities OF the language. Parisians cringe at Quebecois and vice versa and both wag their heads at Cajun Creole.

Of course you could say that I have a bias. After all, all of my programming is byval..... :yes:

Link to comment

Absolutely nothing about OOP requires a by reference design.

Even if 99.99% of OOP Implementations DO use references, it does not change the matter that the very nature of OOP does not demand either by value or by reference idioms.

Shane.

I disagree. Most of the patterns used in OOP design are build around the very principle of references. References to objects. How do you make a singleton without using some kind of reference? You can do it with LV2 style globals, sort of. But when using a DVR, the whole process becomes much more natural and stright forward, and you stick to the principles of dataflow. You could say that when using dataflow you can do well without a singleton, but then you also end up way outside true and trusted OOP design patterns that have proven their usefullness over and over. Sometimes the data is the reference, sometimes it is the value, it's still dataflow IMO.

Link to comment

I disagree. Most of the patterns used in OOP design are build around the very principle of references. References to objects. How do you make a singleton without using some kind of reference? You can do it with LV2 style globals, sort of. But when using a DVR, the whole process becomes much more natural and stright forward, and you stick to the principles of dataflow. You could say that when using dataflow you can do well without a singleton, but then you also end up way outside true and trusted OOP design patterns that have proven their usefullness over and over. Sometimes the data is the reference, sometimes it is the value, it's still dataflow IMO.

You're basically remaking my point. "Most of the patterns..." are programmed in C++ by those who use and "grew up" using/learning programming constructs via C++ and/or UML oriented to byref constructs. And what is "more natural and straight forward" depends on the eyes of the beholder. Having used LV as long as I have, FGV seem VERY natural and straight forward to me.

Link to comment

Most of the patterns used in OOP design are build around the very principle of references. References to objects. How do you make a singleton without using some kind of reference?

Can you list some other examples? “Singleton” is the most obvious one, but Singleton is far more “by ref” than it is “object oriented”. Any non-reentrant VI is a singleton.

Link to comment

Most of the patterns used in OOP design are build around the very principle of references. References to objects.

I will concede that some design patterns likely require object references. On the other hand, we have successfully implemented all the GoF design patterns we have tried thus far with by-value classes, and we didn't need any special tricks to do so.

Link to comment

I will concede that some design patterns likely require object references. On the other hand, we have successfully implemented all the GoF design patterns we have tried thus far with by-value classes, and we didn't need any special tricks to do so.

I have only used singleton for any real purposes so far (an object in a dvr using non-reentrant vi to obtain the ref). I have looked at some of AQ's patterns ages ago, but found them unintuitive and slow executing. While using DVRs things get light weight, fast and intuitive. Maybe I should take another look. Fundamentally what I use most are state machines, and I want them to run in parallel and be as reusable as possible while keeping the overhead down. They must also be able to communicate. That is why I find the actor thing very interesting.

Link to comment

No, nothing REQUIRES byref implementations, however, for various reasons (including what appears most "natural and simple" to an individual) the DVR implementations may be preferred. You might want to look at for one of the threads discussing this issue.

It depends, in the end, on what you mean but I've always been struck by how much the legacy of a primacy effect impacts these kinds of discussions. For instance, if you learned C++ first, you most likely learned of "singleton" in terms of byref implementations. If, however, you learned C first (esp if you were involved in the earliest standardization efforts of C), you probably didn't learn of it in that way as "classes" per se didn't yet exist. Instead all of the various semaphore "tricks" or, if you prefer "workarounds", became familiar to you and you might even continue to PREFER to have the increased flexibility of NOT being restricted by the now-classic implementation of "singleton" in C++. As you can guess, my history extends beyond the early days of C (in fact all the way to PL/1, FORTRAN, etc) and so I prefer the more purely "dataflow" implementations using SEQ+FGV instead of DVRs. But unless you demand the strictest definition of "singleton" (a la the C++ construct), it is clear that nothing does require byref.

Link to comment

Fundamentally what I use most are state machines, and I want them to run in parallel and be as reusable as possible while keeping the overhead down. They must also be able to communicate. That is why I find the actor thing very interesting.

We have implemented asynchronously communicating, stand-alone state-based components (which meet the descriptions I have seen thus far for actors, even though we don't think of them as actors) using native by-value classes and design patterns (see especially the State Pattern and perhaps my NI Week presentation on it.). (We have since also implemented orthogonal state machines within an application.) Our components can communicate over the network, allowing flexibility in deployment, and maintain state information in the proper places. And yes, we reuse the top-level state machine, for instance, in every component controller. :-)

I think that the Gang of Four Design Patterns book and Head First Design Patterns are wonderful sources on how to implement and use design patterns effectively, but those texts didn't really click for me until I began to understand interfaces, which is why I bring up the topic so often in the papers and presentations I have compiled on design patterns.

Link to comment

We have implemented asynchronously communicating, stand-alone state-based components (which meet the descriptions I have seen thus far for actors, even though we don't think of them as actors) using native by-value classes and design patterns (see especially the State Pattern and perhaps my NI Week presentation on it.). (We have since also implemented orthogonal state machines within an application.) Our components can communicate over the network, allowing flexibility in deployment, and maintain state information in the proper places. And yes, we reuse the top-level state machine, for instance, in every component controller. :-)

I think that the Gang of Four Design Patterns book and Head First Design Patterns are wonderful sources on how to implement and use design patterns effectively, but those texts didn't really click for me until I began to understand interfaces, which is why I bring up the topic so often in the papers and presentations I have compiled on design patterns.

How do you implement interfaces?

Link to comment

Thanks

 

I use lots of polymorphic vis for performance reasons. I still use LVOOP though, but polymorphic vis are of course compiled at compile time. I thought of it as interfaces, but maybe it's more "template style" ? I see that by using interfaces (as in your example + some restructuring), the code could be more easily maintainable, but the cost in performance is really too high. I tried once simply replacing some polymorphic vis with dynamic dispatch, and the slow down was unbelievable, about 1/3 performance.

 

I looked at your example and some of the other patterns. It's all very nice, but I get the impression that all the work has gone into "making a pattern in LVOOP" and not so much into showing real world benefits (and shortcomings). For instance creating a bing bang type controller using state machines is done in a couple of hours, even when starting from scratch using "ordinary" G. It becomes more complex with some PIDs there, but still simple enough. But what about when you include more advanced and computationally much more costly controllers like multivariable MPC? A singleton would help me, because it is efficient and simple.

Link to comment

Had some visitors popping by. What I meant was that I see benefits using those patterns from a maintainability point of view, but it is not clear to me that the end result is better overall. Partly because my experience with dynamic dispatch in LV is a killer of performance, and partly because the examples are too simple and too far from real world applications. A singleton (not the one used in the pattern site at NI, but another one) is simple and the performance is always top, and it is easy to integrate in the ordinary dataflow. But I must admit, there are lots about this I don't understand, the patterns and stuff. For instance the factory pattern, if you don't use it in relation with pointers to objects (by ref), what is the benefit?

Link to comment

bsvingen, are you using “singleton” in the same meaning as in OOP; something of which there can only very be one instance of?  Because I don’t see how that is useful in something like a PID controller, which one might easily want multiple of.  Do you perhaps use “singleton” to mean any by-reference thing?

Link to comment
bsvingen, are you using “singleton” in the same meaning as in OOP; something of which there can only very be one instance of?  Because I don’t see how that is useful in something like a PID controller, which one might easily want multiple of.  Do you perhaps use “singleton” to mean any by-reference thing?

No, singleton as in singleton. I haven't said it would be particularly useful for PID. For MPC on the other hand it is very useful, but it is useful because it is by ref, not only because it is a singleton, even though you normally want only one single MPC controller in any system. The typical architecture in larger systems is several PID or lesser controllers, often per component basis, and one single MPC controlling all the other controllers and/or through direct control of actuators.

 

Anyway, the actor pattern do look interesting.

Link to comment
The typical architecture in larger systems is several PID or lesser controllers, often per component basis, and one single MPC controlling all the other controllers...

Yes, that’s how I (and many or most others) would do.  I would have dynamically-launched VIs as “components”, which I think of as “parallel processes” or “actors”.  I use LVOOP for the inter-process communication (“messages” and “addresses”), with each parallel process being represented by-reference to its LVOOP address object.  The address is effectively by-reference because it wraps some communication reference like a queue, user event, or TCP client.

 

Note that an “actor” is effectively like a by-reference, asynchronously-accessed, active object, which is not the same as standard OOP objects in text languages, which are by-reference, synchronously-accessed, non-active objects.  One can create the latter using a DVR in LabVIEW, but whenever I’ve considered using one I’ve always decided that stepping up to an actor is better (one concern, though, would be speed; straight DVR access will be fast compared with a request-reply exchange of messages via queues).

Link to comment

"What I meant was that I see benefits using those patterns from a maintainability point of view, but it is not clear to me that the end result is better overall. Partly because my experience with dynamic dispatch in LV is a killer of performance, and partly because the examples are too simple and too far from real world applications. ... For instance the factory pattern, if you don't use it in relation with pointers to objects (by ref), what is the benefit?"

 

The factory method pattern lets clients create concrete objects without having any references to the concrete objects.  For instance, clients create state objects without having a reference to the concrete states.  This sometimes makes a huge difference in the amount of interlinking and hence can affect project load time (and on RT can make the difference between successfully deploying an application or not).  (It also means that one developer can work on the client code in one project while another developer works on the state code in another project.)

 

I haven't completed incredibly thorough studies of the performance of dynamic dispatching except in a few cases, and in the situations where we use dynamic dispatching performance is not an issue for our applications.*  Certainly in absolutely performance-critical pieces it will be necessary to use static methods and in-line them.  (*We did identify one complex but repeatable situation where using an object that was a collection of objects was many, many times slower than when using a cluster containing those objects, and we reported that to NI.  That is the only situation we have encountered such an issue to date.)

 

We use OO design patterns in all our applications.  I think you are on the money, in that the primary benefit of using design patterns is to the programmer and thence to the customer, in that it can make the code more maintainable (and, I would add, easier to design and write in the first place), rather than in application performance; I think that it is of immense value.  For instance, we find using the State Pattern results in a very clean and explicit implementation of states, with hierarchical states (so that we don't need to repeat behaviors in subclasses), and when something works in an unanticipated manner anyone on our team knows exactly where to look in the code to investigate the issue.  Those are pretty huge benefits for us when we are developing robust applications that we want to remain operable for many years.  We definitely have seen the benefits in the real world, where our system is functioning extremely reliably.

Link to comment

On the question of whether LV is object oriented or actor oriented: Neither, inherently. Both of those are design styles, and they are orthogonal to each other. One speaks to a way of data packaging (object) and the other speaks to a way of controlling execution flow (actor). It is possible to design a system that is pure procedural, purely object oriented, purely actor oriented, or both. Such systems can be built in just about any programming language. Having said that, various languages provide syntax support to make it easier to implement these designs. LabVIEW supports object-oriented programming through the .lvclass files and related features. LabVIEW supports actor-oriented programming through the queues and VI Server systems. The Actor Framework provides syntax to unify the two, though there are plenty of other ways to achieve that effect.

 

As for the singleton pattern... I do wish that pattern would die. Yes, it is terribly useful and I use it all the time in C++. But I also get burned by having used it all the time. The single static instance of an actor/object (because you're treating it as the same thing in that case) makes it nearly impossible to fork two copies of your application or module within your application, and you'd be surprised just how often an app becomes successful and someone says, "Hey, let's run two of these side by side!" and suddenly that easy-to-implement global singleton that was so nice in the original version becomes a liability that is damned hard to refactor because you now have to rewrite your API to propagate a parameter to the far reaches of your program so it can know which of the two former-singleton objects to use.

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.

  • Similar Content

    • By Ryan Vallieu
      I have seemingly found an issue with the shipping example code for Nested Malleable VIs.  Another user has verified that he saw the same behavior in 2019.
       
      I am working through the examples and the presentation from NIWeek 2019.  In running the Lesson 2b code (C:\Program Files (x86)\National Instruments\LabVIEW 2019\examples\Malleable VIs\Nested Malleable VIs) I found the Equals.vi in the class was not being leveraged and the search failed.  When I went to my LabVIEW 2018 machine and ran the Lesson 2b.vi the code worked to find the element by correctly leveraging the in-class Equals.vi.
      One difference I see is that in the 2018 example the Equal.vi is in the example folder with the code, and in 2019 the Equal.vi has been moved to VI.lib - otherwise the code looks to be the same.  The Equals.vi code looks identical, and the calling VIM look identical.  I posted on the LabVIEW NI.com forum here: 
      https://forums.ni.com/t5/LabVIEW/LabVIEW-2019-Malleable-VIs-Shipping-Examples-Lesson-2b-Nested/m-p/3966044/highlight/false#M1129678
       
      I am trying to determine what may have broken or changed between the implementation in 2018 and 2019, visually the code looks the same.
    • By Voklaif
      Hello all,
      I am programming with LabVIEW for around 2 years and was recently stumbled upon LVOOP.
      I am required to write a communication protocol to work with a micro-controller, which later will be also used for ATP and debug purposes.
      I want to build the program "correctly" from the beginning so it will be maintainable and flexible to additions and changes.
      My natural way of building a program would have been a queued state machine, with several loops, each loop is in charge of a different module (one for GUI obviously), but as I stated in the beginning, I want to use LVOOP.
      Does anyone have a LVOOP project I can use as reference? I've searched online and found some nice examples, but they are small and teach you the basic stuff.
      For me it's important to see the how to use the project tree wisely, where to place the classes, see the managing loop and to learn as much as possible before I create one of my own.
      Thanks in advance,
      Voklaif
    • By GregFreeman
      I have an array of classes, let's call the object TestPass, of size 1 (but it is an array because it can scale out to multiple test passes). In this class, there is one other nested class which is not too complex, then various numeric and string fields to hold some private data. There is also an array of clusters. In this cluster there is a string, two XY pair clusters, and an integer. Not very confusing.
      This array of clusters gets fairly large, however, upwards of 80-100k elements. What I am finding is when I index the array of pass classes it is crazy slow. On the order of 30 ms. Doesn't seem like much, but we are indexing the array in our method to "Get Current Pass" which is used in various places throughout our code. This is adding potentially hours to our test time over the 80k devices we are testing. 
      So, I started digging. When I flatten the class to a string and get the length, it's 3 mb. But, when I run the function with the profiler is is allocating close to 20 mb of memory!
      My gut feel was that the string is causing the issues. So I removed the string from the cluster and the index time went to 0 ms. 
      Luckily we can normalize a bit and pull the strings out of the cluster since a lot of them are duplicates. But it makes our data model a bit uglier. 
      Has anyone seen these kind of performance issues before? I saw them in 2013 and 2017.
    • By ted Francis
      I am new to LVOOP and have jsut started writing my first LVOOP program which I have attached.
      I would appreciate greatly help with the question I have
      Thank you in advance 
      Ted
      This vi will perform two tasks 
      1.Generating Report data sheet for metrology 
      2. updating the scales in a MAX .nce file
      1. Metrology will input calibration information into the tables on the tabs
      Metrology will then click "Update Tables" then "Create Report ( create report section of code is not yet written
      Update Tables will write all information entered in the tabs to class varaibles and will also delete current Max informatiomn
      2. Metrology will click "Load NCE Scale"
      vi will prompt for nce file to load and then once file is selected, display existing scales for two channels (Current Motor 1 and 
      Current Motor 2)
      Metrology will then click "Update Scales"  the program will replace the existing scales with those entered in Step 5.14 and 5.15
      from the tables on the tab
      Question 1.  Steps 5.14 and 5.15 are needed by both classes ( Table Variable and MAX) - what is the best way to share this information
       
      CAT0000032 Class Version.zip
    • By shoneill
      I was browing through the actor framework discussions on the NI site yesterday and I came across a statement by AQ.
      Never inherit a concrete class from another concrete class
      I had to think about that for a second.  The more I think about it, the more I realise that all of the LVOOP software I have been writing more or less adheres to this idea.  But I had never seen it stated so succinctly before.  Now that may just be down to me being a bit slow and all, but in the muddy and murky world of "correct" in OOP-land, this seems to be a pretty good rult to hold on to.
      Are there others which can help wannabe plebs like me grasp the correct notions a bit better?  How about only ever calling concrete methods from within the owning class, never from without?  I'm learning for a long time now, but somehow, my expectations of LVOOP and the reality always seem a little disconnected.  AQs statement above helped crystallise out some things which, up to that point, had been a bit nebulous in my mind.  Well, I say I'm learning..... I'm certainly using my brain to investigate the subject, whether or not I'm actually LEARNING is a matter for discussion... The older I get, the less sure I am that I've actually properly grasped something.  The old grey cells just seem to get more sceptical with time.  Maybe that in itself is learning...
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.