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.

Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

What do you think about creating only one message for an actor?

Basically I find myself sometime just creating one message with only one do method for all my actions that an actor should do. Just like the old way with commad and data clusters i just handle what the actor is supposed to do in case structure in one message.

I find this to make everything much more readable + when something is needed to load dynamically I can still use dynamically loaded messages that handle something else. I also found this to increase readability and decrease overhead of the project.

What do you think about this approach? Shouldn't we try to promote this aproach?

Piotr Kruczkowski
Certified TestStand Architect
Certified LabVIEW Architect
0 Kudos
Message 1 of 12
(7,872 Views)

Do your method then look like a big case structure? I don't agree that it would be more readable, just readable in a different way. I group methods in my project that are the action in the Do.vi and it is readable from the project view. You discover the interface to the actor by looking at its messages not by looking at a enum for a single message.

My $0.02.

Casey Lamers


Phoenix, LLC


casey.lamers@phoenixwi.com


CLA, LabVIEW Champion


Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!

0 Kudos
Message 2 of 12
(4,515 Views)

Piotr_Kruczkowski wrote:

What do you think about this approach? Shouldn't we try to promote this aproach?

No, I don't think this approach should be promoted.

Currently in the Labview community there are two main messaging paradigms for actor-oriented programming:  Name/Data messaging and Command Pattern messaging.  Each has advantages and disadvantages.  Though the Actor Framework supports Command Pattern messaging natively, you can (as you have discovered) implement AF applications using the Name/Data paradigm under the covers.

The question is, why bother?  Combining the paradigms doesn't give you the best of both worlds--it gives you the worst.  If you prefer the readability and simplicity of Name/Data messaging, I'd recommend not using the AF and just writing your own actors.  Your application will be much simpler in the long run.

0 Kudos
Message 3 of 12
(4,515 Views)

Considering this is one of the big bugs that we set out to fix in the design of the AF, no, I don't think it is an approach to consider. 🙂

  • You lose type safety. You have a giant cluster. Which fields are being used on any given messge? Inevitably, someone starts reusing the same integer field for multiple messages, so you end up naming it something really generic. Or you use a variant instead of the giant cluster, which means you have substantial memory copy overhead and the performance hit of testing the type to cast it back to its original data (not a cheap operation).
  • You generate lots of junk data. The giant cluster has to be sent on every message, even messages whose payload is just a boolean.
  • You reduce findability  (the ability to find where in code a particular message is sent). Sure, you can use a text search of your code to find where a given string name is in a constant, but you'll find a lot of other places where that text is used, like comments, etc, rather than a dedicated Send VI whose call locations you can find. So clever people start wrapping any single command in a custom Send VI. Well, that's 1/3 of the class right there. Finish it out with a typedef and a subVI for the Do.vi and you're back where you started.
  • You introduce the risk of mistyping a string name. Again, custom Send VI ameleorates this.
  • You lose the independence of the Do.vis on large projects where multiple developers are editing. When everything is one VI, you have to make changes to that one VI and you can't selectively roll back the changes to a single message.
  • You are restricted to a fixed set of messages -- you can only handle those messages whose strings are pre-defined for you. A third party creating a custom message with its own handling routine is really tricky to do (it involves opening VI refnums in some weird ways).
  • If a given message isn't used in a project, its code can be eliminated during AppBuilder, unlike the code being all built into a case structure.

These were issues that I saw repeatedly causing problems in user code. Any downsides to the message classes of the AF are, in my opinion, completely dwarfed by the downsides of the "one message for everything" approach.

Message 4 of 12
(4,515 Views)

AQ's response is actually the best concise description I've heard of the value of actor framework over the clustersaurus.  This is getting copied & pasted...

Message 5 of 12
(4,515 Views)

Awesome reply AQ, I'll use that in some of my teaching the AF as well.  Its a common question.  And Ben, I am definitely going to borrow your term of clustersaurus, I using call them the mothercluster, but some people take that a bit too negatively, even though I like it.

0 Kudos
Message 6 of 12
(4,515 Views)

AristosQueue wrote:

Or you use a variant instead of the giant cluster, which means you have substantial memory copy overhead and the performance hit of testing the type to cast it back to its original data (not a cheap operation).

Side question (as I mostly uses Variant messages): what "substantial memory copy overhead"?  And why would one be "testing the type"?

0 Kudos
Message 7 of 12
(4,515 Views)

AristosQueue wrote:

  • You lose the independence of the Do.vis on large projects where multiple developers are editing. When everything is one VI, you have to make changes to that one VI and you can't selectively roll back the changes to a single message.
  • You are restricted to a fixed set of messages -- you can only handle those messages whose strings are pre-defined for you. A third party creating a custom message with its own handling routine is really tricky to do (it involves opening VI refnums in some weird ways).
  • If a given message isn't used in a project, its code can be eliminated during AppBuilder, unlike the code being all built into a case structure.

I hadn't really appreciated this about the AF before.   In my string-message based actor-like processes, the set of possible strings is what I think of as the "API" of my actor, and that this API "belongs" to that actor code module.  But with the AF, it is really the public methods of the Actor's class that is the API, and the messages that can be sent to the actor are really code blocks that can belong to the components comunicating to the actor.

A Poll:  How to people who use the AF mentally view the messages they send to an actor?  As "part" of the receiving actor, or as part of the sending code?

0 Kudos
Message 8 of 12
(4,515 Views)

Being able to route messages to dispatch handlers on other message contents than just type is highly desirable, as is having dynamically-typed message payloads (or no payloads at all, for a significant if not majority set of messages). For this reason, I fully endorse the sentiment, though not necessarily the implementation (cluster of string/LVVariant as the Message), of the original post.

Though, there are merits to statically typed messages and dispatching on type. Application domain might dictate which is clearly more desirable, though I can say for my applications >90% messages are dynamically-typed, where codebase agility is reason enough to justify loss of static type checking, etc...

0 Kudos
Message 9 of 12
(4,515 Views)

drjdpowell wrote:

A Poll:  How to people who use the AF mentally view the messages they send to an actor?  As "part" of the receiving actor, or as part of the sending code?

I don't use AF for production code, but I view messages as being "part of" the documentation of an API, which then has the concrete implementation of business logic on the receiver-side and the concrete implementation of message construction client-side.

Sometimes this message type manifests itself as a data structure defined in the language's type system, and sometimes the client of that API is in the same language and can use that type. It's awkward in LabVIEW to designate "ownership" of this message to the API, especially if they are both encompassed by an LVLIB. Briefly, namespacing in LabVIEW is broken, since it also forces static linking (e.g., it's highly undesirable to statically link API business logic to the API's calling clients).

In this case, it's best to construct that message in the "global namespace" (e.g., none at all, by not being in a library), or through a dynamic type (such as a stringly-typed structure such as JSON or XML) to promote decoupling. These are fundamental problems with LabVIEW today, currently irreconcilable in an "ideal" way.

0 Kudos
Message 10 of 12
(4,515 Views)