Techniques for componentizing code
#41
Posted 30 October 2011 - 11:05 PM
Not entirely following the latest part of the discussion, but there may be some confusion between what Daklu was doing, extending the message identifier with "Slave1:", and the common method of adding parameters into a text command (as, for example, in the JKI statemachine with its ">>" separator). Parameters have to be parsed out of the command when received, thus the need to decide on separating characters and write subVIs to do the parsing. But Daklu's "Slave1:ActionDone" never needs to be parsed, as it is an indivisible, parameterless command that triggers a specific case in his "Master" case structure (see his example diagram).
Now, if he did want to separate the "Slave1" and "ActionDone" parts (for example, to use the same "ActionDone" code with messages from both slaves using the slave name as a parameter) then he could parse the message name on the ":" or other separator. But there is an alternate possibility that avoids any possibility of an error in parsing (Shaun, stop reading, this is getting OOP-y; there's even a pattern used, "Decorator"). Instead of using a "PrefixedMessageQueue", use a variation of that idea that I might call an "OuterEnvelopeMessageQueue". The later queue takes every message enqueued and encloses it as the data of another message with the enclosing messages all having the name specified by the Master ("Slave1" for example). When the Master receives any "Slave1" message, it extracts the internal message and then acts on it, with the knowledge of which slave the message came from.
You can use "OuterEnvelopes" to accomplish the same things as prefixes, though it is more work to read the message (though not more work than parsing a prefixed message) and less human-readable (unless you make a custom probe). It may useful, though.
-- James
Note: I put an OuterEnvelope ability in my messaging design, but I've never actually used it yet, so I'm speaking theoretically.
#42
Posted 31 October 2011 - 12:04 AM
Ok I'll shut up then. Obviously completely over my headHello,
Shaun, stop reading, this is getting OOP-y
Founder and general mischief maker on www.labview-tools.com.
SQlite aficionado and websocket zealot.
If it 'aint in LabVIEW, then you 'aint got a clue!
#43
Posted 31 October 2011 - 09:48 AM
Not over your head, I'm sure, but I know you don't like getting POOP-yOk I'll shut up then. Obviously completely over my head
#44
Posted 31 October 2011 - 05:11 PM
Actually, in rare situations I do parse the sender name from the rest of the message. Since the master can't exit until it receives exit messages from the slaves, sometimes I'll combine all the exit messages into a single case and keep track of who has sent exit messages via a feedback loop. It's contains the functionality a little more than having separate handlers for each slave's exit message.Now, if he did want to separate the "Slave1" and "ActionDone" parts (for example, to use the same "ActionDone" code with messages from both slaves using the slave name as a parameter) then he could parse the message name on the ":" or other separator.
Structurally what you're describing is, if I'm understanding correctly, similar to the decorator pattern but it is not (imo) a decorator. Patterns are defined by their intent, not their structure. Decorators are optional composable bits of functionality. An object can be wrapped in 0..n decorators and still behave correctly. I don't think what you're describing quite fits.there's even a pattern used, "Decorator"
All problems in computer science can be solved by another level of indirection... except for the problem of too many layers of indirection.Instead of using a "PrefixedMessageQueue", use a variation of that idea that I might call an "OuterEnvelopeMessageQueue". The later queue takes every message enqueued and encloses it as the data of another message with the enclosing messages all having the name specified by the Master ("Slave1" for example). When the Master receives any "Slave1" message, it extracts the internal message and then acts on it, with the knowledge of which slave the message came from.
Forgive me for saying so, but applying that in this particular case smells of too much indirection. I don't see that it provides any real benefit in this use case. One place where I have considered boxing messages in other messages is with errors. It's just something I've thought about though... haven't tried implementing anything yet.
Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.
Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.
There are two secrets to success:
Secret #1 - Never tell everything you know.
#45
Posted 31 October 2011 - 05:37 PM
You're right, it doesn't really fit the intention of the "Decorator pattern", but structurally it is very similar.Structurally what you're describing is, if I'm understanding correctly, similar to the decorator pattern but it is not (imo) a decorator.
In the mental image I use for my messages, envelops with contents inside and a label on the outside, having the Messenger place the received envelope inside another envelop and labeling it "This is a message from from Slave1" doesn't seem confusing to me. Not much more than altering the label of the original message and then feeding into a parser, anyway.Forgive me for saying so, but applying that in this particular case smells of too much indirection. I don't see that it provides any real benefit in this use case.
Just an idea; as I said, I have never used it yet.
-- James
#46
Posted 03 January 2012 - 12:24 PM
FYI from a couple of months later: I have now made use of "outer envelopes". They were very useful in the writing of TCP Messengers for my message-sending reuse framework, allowing the sent messages to be packaged inside outer envelopes carrying labels that mean something to the "Client" and "Connection" actors that run the TCP communication. Using the outer envelope label obviated the need for any parsing or inspecting of a message to determine what to do with it, and led to clearer code. For example, the "Client" receives envelopes labelled "Send Via TCP", while replies to messages, to be routed back through the TCP connection, are received by the "Connection" actor in envelopes labelled "Route Back Message".Just an idea; as I said, I have never used it yet.
Note: all use of these outer envelopes is internal to the TCP messaging structure, and are completely transparent to the processes at each end of the connection, which do not need to do any marking of messages themselves.
-- James
Part of "TCP Client Actor" where messages to be sent through TCP are received inside "outer envelopes" marked "Send Via TCP" (the marking is done by the "RemoteTCPMessenger" class to which the messages are initially "sent").
#47
Posted 16 February 2012 - 01:19 AM
Hey Daklu,
Yeah it is probably possible. Right now I'm sipping my morning coffee and going over your Slave Loops concept. I feel that it's probably very similar to what I'm trying to do with my code but implemented in an OOP sense. Hopefully I can draw some parallels and a light will click. I'm particularly interested in the idea of launching and shutting down a slave process as needed.
I've gone through a really torturous route of wrapping each process inside a message handler framework, with an FGV pertinent to each process which is solely responsible for passing the stop message from the message handler to its process. The "process-nested-inside-message-handler" is in turn launched by a master message handler which handles input from the user to determine what tests should take place. I just had a blinding realisation as I wrote this that I could have handled this much simpler with a 0 time out queue in each process that listened for a stop message and if timed out did whatever the process was trying to do. One of the key assumptions that led me down my torturous path was that I must have a default case that handles messages which don't correspond to real messages. *Realisation* In fact, I could just use the timeout line on the queue to nest another case structure and still handle the default (incorrect message) case, gah, so much time wasted.
From looking at your slave loops template posted in this thread, am I right in assuming that if you wanted a different slave behaviour (a new plug in if you will), that you would merely make a new execute method in the SlaveLoop class? Or would you instantiate a whole new child class of SlaveLoop.lvclass with its own execute method?
Following on from my confession of my own wrangling efforts, how would you formulate one of your slave loops that needed to be a continuous process but also accept stop commands, would you use the timeout method I thought of above, or something else?
What would you do if you wanted to be able to close and reopen your slave loop without locking your code up? What I'm getting at here is, what is the OOP equivalent to launching a sub-vi using a property node with "Wait Until Done" set false?
Thank you for the opportunity to pick your brains! Your posts are always amazingly informative, even if it does take me months for things to finally click into place...
Edited by AlexA, 16 February 2012 - 01:20 AM.
#48
Posted 16 February 2012 - 06:07 PM
Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.
Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.
There are two secrets to success:
Secret #1 - Never tell everything you know.
#49
Posted 18 February 2012 - 03:28 AM
Grrr, I know what you mean, I just lost a post
Anyway, I was saying that I've figured out that new slave loops should be children of your parent class with different execution loops (blindingly obvious in retrospect). I've struck something strange though. The children don't seem to actually inherit the parents data type (the messenger queues). The same messenger queue types need to be placed into the child data.ctl file manually or else the childs execution loop, which I've copied from your parent and exchagned the object type from parent to child, is broken.
From my own experimentation and understanding, children should always inherit all the data fields of their parents, even if they're not visible on the child data.ctl front panel, correct me if I'm wrong.
Here are some pictures showing what I mean.
With inheritance checked in the class properties but the data not manually moved onto the child data.ctl file:

With inheritance checked and the data moved in manually:

Your thoughts?
Cheers,
Alex
Edited by AlexA, 18 February 2012 - 03:28 AM.
#50
Posted 18 February 2012 - 10:36 AM
One slightly annoying thing at first about LVOOP child classes is that they cannot directly access their own “parent” data via “unbundle”. All child objects have the parent private-data cluster, but methods of the child class need to access it via methods of the parent class. If you create VIs in the parent that return InputQ and OutputQ, then the child class VIs can use them instead of unbundle. Creating “accessor” VIs like this is automated, so it takes less than a minute to make several. One can even make them be usable in a Property Node structure to access several things at once.
The reason for this, I believe, is to allow the designer of the parent class to have a well-defined public interface, and thus he/she can change the internal private structure without breaking any children written by other developers.
Edited by drjdpowell, 18 February 2012 - 10:38 AM.
#51
Posted 18 February 2012 - 04:20 PM
Another battle in the never ending war between safety and flexibility.One slightly annoying thing at first about LVOOP child classes is that they cannot directly access their own “parent” data via “unbundle”.
Actually, I use it as a template, not a parent class. When creating a new slave loop class I copy the template and customize it for the specific task. That's why there are no accessor methods for children.Anyway, I was saying that I've figured out that new slave loops should be children of your parent class with different execution loops (blindingly obvious in retrospect).
Why not use it as a parent class? Primarily because the parent-child relationship creates a dependency, and I think it's more important to manage/limit dependencies between various application components (lvlibs.) If the parent is in one library and the child is in another, then the library with the child class is dependent on the parent's library. If I want to reuse the child's library in another app I have to drag the parent's library along with it.
Also, there are really only 3 methods in the class: Create, Execute, and Destroy. My convention is that Creators are not overridable, since they have to accept all the data that is unique to a specific class. Execute must be overridden by each child class, so there's no opportunity for reuse there either. Destroy can be reused, but there's not much savings in doing it. It takes maybe a minute to write it. In short, there's no benefit to making a SlaveLoop parent class and it requires more effort to manage.
I can envision scenarios where it would make sense, but I haven't encountered them in the real world.
[Still need to respond to your earlier post...]
Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.
Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.
There are two secrets to success:
Secret #1 - Never tell everything you know.
#52
Posted 15 April 2012 - 10:19 PM
I imagine you're busy but I was wondering if you could weigh in on the following question (from an earlier post).
What would you do if you wanted to be able to close and reopen your slave loop without locking your code up? What I'm getting at here is, what is the OOP equivalent to launching a sub-vi using a Run VI method with "Wait Until Done" set false? Or, as an even more abstract question, how does one implement a plug-in type code structure where the functionality is determined at run-time?
Also, if you're slave process should be continuous except when handling messages, do you utilise a timeout method, or do you separate the behaviours within the slave by adding another layer via a separate message handler?
Thanks for your insight!
Edited by AlexA, 15 April 2012 - 10:21 PM.
#53
Posted 17 April 2012 - 05:28 PM
Three questions, three answers.What would you do if you wanted to be able to close and reopen your slave loop without locking your code up? What I'm getting at here is, what is the OOP equivalent to launching a sub-vi using a Run VI method with "Wait Until Done" set false? Or, as an even more abstract question, how does one implement a plug-in type code structure where the functionality is determined at run-time?
Close & Reopen
The simplest implementation doesn't allow exiting and restarting a slave loop. Since most slaves are idle unless they are handling a message, this design is adequate for many situations. If you have a continuous-process slave that consumes a lot of resources and want to be able to shut it down when it's not being used, I'd build an internal state machine with "Active" and "Standby" states. In the Standby state the slave simply monitors messages. In the Active state it's monitoring messages and doing the resource consuming processes.
OOP Run VI
There is no "OOP equivalent." If you want to dynamically launch a slave loop you still need to use that function. (Or the Call Async VI function introduced in 2011.) When I wrap a slave loop in a class, the class usually has three methods: Create MySlave, ExecutionLoop, and Destroy. If I need dynamic launching I'll add a fourth method, Launch. Launch simply loads the ExecutionLoop vi and launches it using the mechanism of your choice. (Note: Dynamic launching adds complexity to the code, so I'll only use it if I need a large or unknown number of identical slave loops.)
Plug-ins
To me, a "plug-in" is the ability to add functionality to an application without recompiling any of the original source code. When the application starts, it searches the plug-in directory, finds the installed plug-ins, and hooks into them. If that's what you're looking for, then you'd probably need to launch each plug-in slave loop dynamically unless there's a known upper limit on the number of plug-ins that will be running at any one time. I've never done plug-ins with slave loops so I'm not sure what issues you'll run into, but it seems like it'd be fairly straightforward.
I occasionally use a queue timeout case for very simple situations, but I consider it code debt because there's no way to guarantee the timeout case will ever be called. I'll usually refactor it into something more robust the next time I'm adding functionality to that loop. There are two ways I've dealt with "continuous process" slaves in the past: Heartbeats and DVRs.Also, if you're slave process should be continuous except when handling messages, do you utilise a timeout method, or do you separate the behaviours within the slave by adding another layer via a separate message handler?
Using Heartbeats for Continuous Slave Loops
A heartbeat is a simple timer that sends out a single message at specific intervals. (I've also called them "watchdogs," "timers," and in a fit of lyrical excessiveness, "single task producers.") In the example below, every 20 ms the heartbeat loop sends a RefreshDisplay message to the Image Display Loop, ensuring the display will be refreshed regularly regardless of the timing of other messages it might receive. However, it's still possible for the timing to get out of whack if the queue were backed up.
[In this example the image display slave loop is not wrapped in an ExecutionLoop vi--it's on the main UI block diagram with several other slave loops and a mediator loop to handle message routing. A heartbeat can be put on a slave's ExecutionLoop block diagram if it is an inherent part of the slave's functionality, but usually setting up the heartbeat on the calling vi is more flexible. Either way the heartbeat is set up to automatically exit when the slave loop exits.]
Using DVRs for Continuous Slave Loops
When a simple heartbeat isn't an adequate solution, I'll refactor to use a DVR instead. This is the ExecutionLoop of an ImageComposerSlave class. In this particular case the SetOverlay message comes in bursts--a few seconds of high volume messages followed by relatively long periods of no messages, so there was a risk of the message queue getting backed up and throwing the timing off.
The ImgCmp object (containing all the relevant information needed to compose an image) is unbundled from the ImgComposerSlave object and immediately put into a DVR. The DVR is branched, with one branch going to the message handling loop and the other going to the image rendering loop. When the message handling loop receives a message that changes a value related to image rendering, it locks the DVR, changes the value in the ImgCmp object, and unlocks it again.
The image rendering loop executes at regular intervals, ensuring the rendered image gets produced on time. In principle the rendering loop can block for an excessive time waiting for the message handling loop to release the DVR. However, because the DVR never leaves this block diagram it is easy for me to verify there are no lengthy processes locking the DVR.
Does that help?
-Dave
Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.
Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.
There are two secrets to success:
Secret #1 - Never tell everything you know.
#54
Posted 17 April 2012 - 08:16 PM
Also, if you're slave process should be continuous except when handling messages, do you utilise a timeout method, or do you separate the behaviours within the slave by adding another layer via a separate message handler?
I had a similar issue recently that I tried a different way with. A fourth option to consider with Timeouts, Heartbeats and DVRs (never thought of the last one).There are two ways I've dealt with "continuous process" slaves in the past: Heartbeats and DVRs.
I was writing software to log to an SQLite database; each individual SQLite transaction to disk takes a large amount of time, so it is best to store up log messages and save them as a batch periodically. I solved it with a “Scheduled Tasks” VI shown below (in a background process in the “Command Pattern” OOP style):
“Scheduled Tasks” is called after each message and outputs a timeout that feeds back into the dequeue. Internally, “Scheduled Tasks” checks to see if it is time to write the accumulated log messages to disk, and if not, calculates the remaining milliseconds, which is output. Thus, the task always gets done on time, regardless of how many messages are incoming. A disadvantage is that the timeout calculation has to be done after each message, but it isn’t a big calculation. An advantage is that “Scheduled Tasks” outputs −1 (no timeout) after it flushes all waiting messages to disk; thus if log messages arrive very rarely, this loop is spending most of its time just waiting.
It worked out quite well in this application, so I thought I’d mention it.
— James
#55
Posted 17 April 2012 - 09:56 PM
Heartbeat and Timeout Shifting are two ways to get an actor (i.e. slave loop) to perform relatively short process at regular intervals. Intuitively I think the DVR is more suitable when the process is more or less continuous. I noticed a couple other things about Timeout Shifting compared to the Heartbeat. (Not to be down on your solution...)
-I believe the temporal separation of the dequeue timeout occurance and the next timeout being calculated will cause the absolute error to grow over time with Timeout Shifting. If you have something that has to execute every 5 seconds, it may start by executing at 0, 5, 10, etc., but after 10 minutes it may be executing at 1, 6, 11, etc.
-I don't think Timeout Shifting will scale as well as a Heartbeat. To add multiple periodic task on different intervals to a slave using a Heartbeat, just drop another loop with the message and interval. To do it with Timeout Shifting requires more internal shift registers and logic to make sure only the task to execute next passes its time to the timeout terminal. More importantly, with each additional periodic task to perform, not only does that sub vi get called more frequently, but the percentage of wasted processing time with each execution increases, making the scheme less and less efficient. For practical purposes this may not matter.
But as long as the developer understands these consequences I don't think there's anything wrong with them. Thanks for sharing!
Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.
Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.
There are two secrets to success:
Secret #1 - Never tell everything you know.
#56
Posted 17 April 2012 - 10:20 PM
I keep the last timestamp in the object data. Yes, “Do.vi” is no-op for the parent message class.Do you keep the timestamp of the last flush in an internal shift register? I assume Do.vi is a no-op if the queue timed out?
One can get around that by making the calculation like a metronome. Using the scheduled last time rather than the actual last execution time. Though in this application I didn’t, as true periodicity is not desired. Instead, I just need a minimal time between writes to disk, and doing it this way works better than a periodic heartbeat.-I believe the temporal separation of the dequeue timeout occurance and the next timeout being calculated will cause the absolute error to grow over time with Timeout Shifting. If you have something that has to execute every 5 seconds, it may start by executing at 0, 5, 10, etc., but after 10 minutes it may be executing at 1, 6, 11, etc.
True. I’ve been meaning to think how to generalize this to multiple tasks. Perhaps an array of “tasks” that each output a timeout, with the minimum timeout being used, or an array of tasks sorted by next one scheduled, with only the first element actually checked.-I don't think Timeout Shifting will scale as well as a Heartbeat. To add multiple periodic task on different intervals to a slave using a Heartbeat, just drop another loop with the message and interval. To do it with Timeout Shifting requires more internal shift registers and logic to make sure only the task to execute next passes its time to the timeout terminal. More importantly, with each additional periodic task to perform, not only does that sub vi get called more frequently, but the percentage of wasted processing time with each execution increases, making the scheme less and less efficient. For practical purposes this may not matter.
— James
#57
Posted 17 April 2012 - 11:02 PM
Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.
Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.
There are two secrets to success:
Secret #1 - Never tell everything you know.
#58
Posted 18 April 2012 - 04:56 AM
Very interesting discussion, lots of insightful stuff. Thanks Daklu for your reply, yes in answer to your question, it was extremely helpful!
The following is tangentially related to the discussion at hand, just musings on my part with any insight very welcome:
I've spent a few hours trying to figure out how best to build a database of different queue types, and have come up with the idea of using a Class (Object Queue Class) whose private data is a Queue Reference to a queue of LV Objs. This Class has methods "Init Queue" and "Get Queue Ref" at the moment, Init queue takes an Object as input, where the object is whatever Data Class I want to make the queue.
Get Queue Ref gives me the reference, then I can enqueue an element of type Data Class and dequeue, cast to more specific then read.
This works for my test case, I was musing on whether it makes more sense to create an individual Object Queue class for each data type, haven't tested it but I imagine it would allow me to see mis-wirings at edit time rather than at run time which the current case does.
Anyway, the whole point of the exercise is that encapsulating the queue references allows me to store them in an array and I guess search it for a specific reference by trying to cast to the reference and handling errors, though there may be an even better way to do this taking advantage of inheritance.
More play to come.
#59
Posted 18 April 2012 - 09:19 AM
I have a reusable “Actor” that does the same thing:I actually have a class laying around somewhere I prototyped a couple years ago specifically to send periodic messages to slaves. It's one of those things I've been meaning to add to LapDog....
It’s one of the more useful things to have in the toolkit.
Doesn’t sound that great to me. Personally, all my “Queues” (actually anything to which I can send a message, via queue, User Event, TCP server, notifier, etc.; my parent class is called “Send") use the same base “MSG” class, and I keep track of what is what by holding them in a cluster in shift register, and unbundling by name when I want to send something to one. I never put them in an array unless I mean to send the same message to everybody.Anyway, the whole point of the exercise is that encapsulating the queue references allows me to store them in an array and I guess search it for a specific reference by trying to cast to the reference and handling errors, though there may be an even better way to do this taking advantage of inheritance.
So I never search through an array of “Send” objects. In fact, the container I use for multiple “Send”s, called “Observer”, deliberately doesn’t provide the ability to access individual elements.
— James
#60
Posted 20 April 2012 - 12:28 AM
My initial reaction is no, it doesn't make much sense, but if anyone proposes a valid use case then I could be persuaded. Off the top of my head there are a couple issues with this idea:This works for my test case, I was musing on whether it makes more sense to create an individual Object Queue class for each data type, haven't tested it but I imagine it would allow me to see mis-wirings at edit time rather than at run time which the current case does.
1. The receiver has to monitor several queues simultaneously. This is possible (the Priority Queue in Mercer's Actor Framework is the first implementation that does it well) but it does add unnecessary complexity in most cases. In most cases each actor/loop should only be listening to a single queue.
2. Type safety on the sending side doesn't gain you anything. All the different queue types will be going to the same receiver, so having to pick the correct queue from the collection is just a hassle.
3. Type safety on the receiving side doesn't gain you anything either. After you pass the message out of your dequeue sub vi you'll still need to downcast to a specific class to get any information from the message itself.
Type safety is helpful in detecting programming errors, but sometimes it requires an inordinate amount of extra effort to maintain type safety while a non-type safe solution will be faster to implement and easier to understand.
Tell me again why you're developing all your own stuff instead of joining LapDog?I have a reusable “Actor” that does the same thing
Certified LabVIEW Architect
Dak's First Law of Problem Solving: If the solution looks simple, I don't know enough about the problem.
Yes, the QSM is flexible. So is Jello. That doesn't make it good construction material.
There are two secrets to success:
Secret #1 - Never tell everything you know.












