Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

NI needs to teach more actor-oriented programming principles

Just a suggestion if anyone were to write some material for teaching AOD, but I think it is useful to consider the ACID principles behind trasactional databases.  Often when we send a set of "commands" to a process we are really performing a transaction, and so if we have multiple writers we have the same concerns as databases with multiple users, and have to consider "Atomicity", "Consistency", and "Isolation".

Message 41 of 50
(1,970 Views)

Kurt Grice wrote:

So, in all of this, do we, the collective WE, the LabVIEW community that sees the benefits of AOD, have a list of what 'actor-oriented programming principles' are?

No, at least I don't have a list of easily digestible bullet points that explains all you need to know about AOD.  Sorry.  If I did I'd have already used it and we wouldn't be having this discussion.    I'm still learning the implications of AOD myself, and the tidbits I post here and on Lava reflect my understanding at that time.

However, I am confident "Deciding whether or not a message should be acted on is always the responsibility of the receiver" is not a principle of AOD.  It's true about any concurrent processing, not just the actor model.  (Unless the model includes transactions, like James mentioned.)

And to clarify my statement a bit, when I said "deciding whether or not a message should be acted on," I meant from the perspective of the actor itself, not the system as a whole.  If I write a LaunchNuke actor that is responsible for monitoring the missile's internal systems and launching it when the systems are ready, that's what it uses to decide if the "Launch" message should be acted on.  It doesn't go out and start asking for verification that the president authorized the launch and the target coordinates are correct.  Those responsibilities are handled by other actors.

I'll throw these out there as a starting point for discussion.  I'm specifically not claiming these are authoritative or complete.  As I said, I'm still learning it myself.

If I had to take a stab at saying what the fundamental principles of AOD are, I'd start with:

1. Actors are entirely in control of their own destiny.

2. All communication between actors is done via messages.

3. An actor can receive any message at any time.

The guidelines for implementing actors in Labview are derived from those principles:

1. The one decision every actor has to make is when to stop.  Make sure you have that nailed down.

2. Decide what an actor is responsible for, then make sure it gets the information it needs to fulfill its responsibilities.

3. Do not write an actor that relies on a specific sequence of messages for correct operation.

4. Manipulating messages on the message transport (i.e. queue) by anyone other than the actor who receives the messages is verboten.

5. ...

There are other practices I follow because it tends to simplify things for me, but as I understand it are not an inherent part of the actor model:

1. Be very wary of using multiple communication paths to send messages to an actor.  It is easiest to manage when all information arrives through a single path.

2. Don't let an actor send messages to itself.  This easily leads to sequential message dependencies.  Use sub vis instead.

3. Don't treat the message transport as a job queue.  Try to keep your message handling loop as fast as possible.

4. If your actor needs to periodically perform some action, use metronomes or time-delayed messages, not a timeout on the dequeue.

5. Use a hierarchical messaging topology if possible.  Use other topologies if necessary.

6. ...

Feel free to challenge any of these items or add more of your own.  Since this is an AF community, if anyone wants to add a guidelines for implementing AF actors category feel free to do so.  I'm not familiar enough with it to even start a list and I don't remember what guidelines Stephen has already published.

-----

@KALee

That is a very good video.  Todd posted it about a year ago and that is the video that made me realize the implementation patterns I had developed largely followed the ideas of the actor model.  I still learn something new every time I watch it.

Message 42 of 50
(1,970 Views)

Just to add my two cents, I am in complete agreement with Staab and Daklu. An actor without internal state that allows it to distinguish when it should and should not execute a given command is not much different from a Queued message Handler.

Fine for some simple things, without state, but pretty much inadequate for applications like machine control. Your NuclearReactorController Actor better not execute a ShutdownCoolantPump command while the reactor is in the "ControlRodsWithdrawn" state!!A QMH would excute a ShutdownCoolantPump message willy-nilly and next thing you know...

Anyways all facetiousness aside, I see the Actor Framework as a great and robust messaging system, but that it's up to me to make my actors behave such that messages are requests and don't just execute my methods that actually do things (NuclearReactorController:WithdrawControlRods, NuclearReactorController:RunCoolantPump)  without checking that it's allowable to do so.

How to nicely implement the "stateliness" of an Actor is something I have been mulling over lately. I don't want to involve enums.

0 Kudos
Message 43 of 50
(1,970 Views)

I think that a QMH has to keep track of its state and enqueue to try again later a message that can not be handled. What the Actor Framework does is set tight guildelines, enforces rules, etc so the developer makes sure this is in place. Where for the QMH, the developer needs to implement this.

So, a QMH can be used to implement an Actor type VI, but being an QMH is not equal with being an actor. 

When I teach QMH in the NI courses, I make sure to highlight the caveats and problems developers can get into if they don't:

* manage priority messages correctly (enqueue at the other end)

* keep track of state (do not handle messages that can not be handled in certain state)

* protect your Queue.

Now, this is not part of the NI courses, this is me sharing with my students the mistakes that me and/or my customers have  made in the past.

For an opportunity to learn from experienced developers / entrepeneurs (Steve, Joerg, and Brian amongst them):
Check out DSH Pragmatic Software Development Workshop!

DQMH Lead Architect * DQMH Trusted Advisor * Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor

Have you been nice to future you?
Message 44 of 50
(1,970 Views)

FabiolaDelaCueva wrote:

So, a QMH can be used to implement an Actor type VI, but being an QMH is not equal with being an actor.

QFT.  +1.

FabiolaDelaCueva wrote:

* manage priority messages correctly (enqueue at the other end)

Enqueuing at the other end can work well in limited situations, but I've come to the conclusion that it doesn't scale well.  If you have only one priority message, like "Exit," I believe you'll be fine.  As soon as you add a second priority message you've built nondeterminism into your system.

Suppose you have a QMH you designed with two priority messages, Exit and HandleError.  Some other process puts an Exit message on the front of the queue expecting it to be the next message handled.  Before your QMH can dequeue that message, another process puts a HandleError message on the front of the queue, bumping the Exit message to position #2.  It's possible for other processes to continue putting HandleError messages on the front of the queue and prevent the Exit message from ever being processed.

IMO, enqueuing at the other end puts too much responsibility on the shoulders of the sender.  The sender is effectively saying, "my message is more important than every other message other processes are sending to you."  In the general case the sender can't know that without also knowing what messages the other processes are sending and why they are sending them.  The message sender has to have knowledge about the state of the entire system in order to justify putting a message on the front of the queue.

From a maintenance standpoint it also creates more work.  If your system uses enqueue at front for priority messages then you have to manually find all the places where that message is sent and verify it is being enqueued to the front.  (You can reduce that work by wrapping each priority message in a sub vi, though I don't think I've ever seen anyone actually do that.)

If you *have* to use priority messages, the only way to do it safely is to use Stephen's priority queue implementation from the AF.  (LapDog has one too, but Stephen's implementation is better.)  Personally I strongly question whether priority messages are even appropriate in a messaging system.  I think the whole system is easier to understand when you write your actors so all messages have equal priority.  It's up to the receiving actor to decide what order it wants to process the messages in.

(The need for priority messages arises when the message transport is being used as a job queue.  I posted a message last night listing that as one of the things I avoid.  Apparently NI's censors are still deciding if it's worthy of being shown to others.)

MarkCG wrote:

How to nicely implement the "stateliness" of an Actor is something I have been mulling over lately.  I don't want to involve enums.

Assuming you mean "behavioral state" and not "data state," there are lots ways you can do it.  The simplest implementation is to give your actor a boolean flag that it checks everytime before executing the message handling code.  That can get confusing if you have lots of different behavioral states, so you'd probably want to write a sub vi that takes the intended behavioral state as an input and sets the flags correctly.  Beyond that the implementations diverge depending on whether you're using command-pattern message handlers (like the AF) or case structure message handlers (like QMHs.)  Regardless of your implementation the most important thing is to create a state diagram modelling the behavior you want

An enum defining the different states actually works very well--it doesn't get exposed to anyone outside of the actor.  Remember, other actors aren't setting the state directly; they're sending messages requesting the actor to do something.  The actor itself decides when it changes states.

0 Kudos
Message 45 of 50
(1,970 Views)

I'm sorry to constantly play the policeman here, but this thread has gotten just as unwieldy and sprawling as the one it was branched from. Can you make the discussion of "what AOD best practices are" yet another branch to help encapsulate some of this discussion?

My sympathies to anyone trying to read through some of these discussions for the first time while learning the Actor Framework.

Message 46 of 50
(1,970 Views)

Sorry for the repost, then.  A year ago, I had no idea AF existed beyond the Angry Eagles demo I saw at NIWeek a few years back!  I've been climbing the learning curve for AF for the past few months now and am really grateful that there are experts out there who can conduct meaningful debates such as this.  I have learned a great deal from reading and considering all that has been said.  I know that there are differing objectives, goals, constraints, etc., but the back and forth on the topic of AOD and AF has been tremendously helpful in climbing the learning curve.

0 Kudos
Message 47 of 50
(1,970 Views)

I'm not saying our discussions are bad; I'm saying they should be organized better.

Message 48 of 50
(1,970 Views)

David Staab wrote:

Can you make the discussion of "what AOD best practices are" yet another branch to help encapsulate some of this discussion?

Hmm... apparently not.  I don't have any options available for branching a discussion.  Maybe it's only available to community owners?

0 Kudos
Message 49 of 50
(1,970 Views)

I would just start a new Discussion and re-post pertinent  comments from this one.to seed it.

0 Kudos
Message 50 of 50
(1,970 Views)