OOP Design Patterns in Actor Framework Part 1

OOP Design Patterns in Actor Framework Part 1

Last week I wrote a review of the GOF Book on OOP Design Patterns. This week I would like to share some examples of these design patterns in action, so you can go look at them and see how they are implemented and used in LabVIEW. When I took Allen’s Actor Framework (AF) Class, Allen pointed out several places where he used some of the GOF design patterns while designing the AF. I thought those would make a good starting point.

Command Pattern

UML diagram showing Message Class. Note how children override Do.vi
Recieve Message.vi showing dynamic dispatch on Do.vi

One of the most obvious design patterns used in AF is the Command Pattern. Each of the messages is a command. Inside Recieve Message.vi the Do.vi is called to execute the command. Dynamic Dispatch determines exactly what each message does when it’s Do.vi is called.

Template

Another prevalent but less obvious pattern used in the Actor Framework is the template pattern. The template pattern allows the Actor class to define the order in which certain methods are called but allows children to override some of those methods. In order to determine exactly when those overrides are called, you have to dig into Actor Framework.lvlib.

Actor.vi

Actor.vi

Looking at Actor.vi shows the whole process for launching an Actor. First the Actor’s queue is created. Next Prelaunch Init (which is overrideable) is called before Actor Core (also override-able) is launched. An error in PreLaunch Init causes Actor Core not to launch. Once Actor Core stops, Any remaining messages are dropped (also override-able – per message). Using the Template Pattern, Actor.vi makes sure each step happens in the correct order, but allows for customizing the steps using overrides.

Actor Core.vi

Actor Core.vi


Actor Core.vi also uses the template pattern. First a message is dequeued. Then Receive Message is called (which can be overridden), then Handle Error (also override-able). After the Actor stops, Stop is called. Stop is not override-able, but if you dig into it, it calls Stop Core.vi which is.

Chain of Responsibility

The built in error handling strategy in AF is an example of the Chain of Responsibility pattern. The default error handling is for an Actor to stop and pass the error to its caller via a Last Ack Message. The caller then processes that error the exact same way. So the errors pass up the Actor Tree until they find an Actor that takes the responsibility to handle the error.

Proxy Pattern

A good example of a protection proxy is the Enqueuer Class. One of the fundamental ideas behind the AF is that each Actor owns its own queue. But other actors need to have a way to send messages to it. If an Actor were to pass its queue ref to another Actor, that Actor could close it, peek at the messages, flush it, or do any number of things other than simply enqueueing a message. By wrapping the queue in an Enqueuer Class and then passing that out, this can be prevented. Note that the Enqueuer wraps a Priority Queue class, and that the only methods allowed are to check if the queue is valid and to enqueue a message.

More Examples

This is post 1 in a 2 part series. In part 2 we will talk about even more examples found in some popular add-ons for the Actor Framework.