Jump to content

Delacor Queued Message Handler (DQMH) available via LVTN


Recommended Posts

TLDR: Delacor has some cool stuff, and I had some cool stuff.

 

Wow very cool Fab.  

 

I'm starting to wonder if everyone has developed something like this in secret and just not published it.  I didn't really get around to getting permission to post my version publicly, but I talked about it and even named it Glued.

 

Lots of Glued's functionality is mirrored in your QMH but here's a few of the differences I see so far.

 

DQMH and Glued both had scripting for adding new modules, and messages.  Glued didn't have one for removing messages so good on you.  Glued also had the ability to create global messages, which is a message all modules listen and react to.  This makes messaging 1:1, and 1:N, I never came up with a good N:1 scheme but then again I didn't really need it.

 

When doing a Do Something Wait for Reply, you use a user event to send the message and a notifier to wait on the reply.  I found this to be a bit problematic when doing a shutdown.  If I have a sequencer running that is requesting analog data and waiting on the reply, but at some point the user closes the software.  That close is going to be a global event telling the whole application to shutdown.  If my analog actor loop shuts down, but my sequencer doesn't get the request to shutdown, before requesting a read, then all actors will shutdown except the sequence, which will be waiting for the reply from the analog.  

 

In Glued a user event sends the request, and a user event is used for sending the reply.  The reason for this is because when waiting for the reply we also register for the quit event.  This way if the quit event is fired while waiting for a reply, we will also stop waiting for the reply and shutdown.  DQMH has a timeout where Glued by default had a -1 timeout and with this change I didn't see any kind of issue.

 

For the messaging there are essentially three functions you need to have.  Sending the request, convert the request variant to the request type def, and send the reply.  There were also two type defs, one for the request data one for the reply.  In Glued this was all contained in one polymorphic VI.  The purpose of this was to quickly find where in the code a request was being sent, or a reply was being sent by right clicking on the polymorphic instance and selecting Find All Instances.  Then I could find all places I was requesting data, where I was acting on that, and where I was sending that data back.  The Request, or the Request and wait functions were in the same VI, and there was a boolean input for Wait For Reply.

 

In Glued modules has the ability to send a message to itself using the same polymorphic request VI mentioned before.

 

There existed a manual screen module.  This module was a place for all other modules that had manual panels to be seen.  It basically was a listbox of modules, and a subpanel to insert into it.  This is where sending messages to itself would come in handy because the buttons on the FP of the module invoked the same code as that message would coming from any other module.  In this manual screen actors could be undocked, which would just make floating windows of each.

 

If a module performed a request and waited on the reply, the reply would contain the data and the error from the request.  So say you send a request to read an analog and wait on the reply.  The DAQmx calls perform the operation and the error out is sent back with the reply data.  So from the caller it has a single VI with a request in, reply out, and error out.  This helped make the caller handle errors when it could instead of the module.  As mentioned before the state machine was an array of strings so having this information would help track down the case where the error happened.

 

The request and reply data used a variant, but used variant attributed combined with the Variant Repository so data like who sent the request, where it was going, the payload, and the error could be also sent if desired.

 

I prefer state machines that have the ability to have multiple cases queued up.  Either a multi-line string like JKI, or an array of string, or even an array of enums if you want.  I'm sure you are familiar with the pros and cons.  Glued used an array of string, but I've been using a modified JKI lately and think I prefer that.

 

There existed an error control module.  All modules that gets an error in continuous operation would just send that error to the error actor which would log it, prompt, and try to act.  In practice this wasn't very helpful because it was an asynchronous process, but it was nice to have a single log for errors.  Another benefit of this is it would keep track of what module the error originated from, and the state machine states that lead up to the error.  Because the state machine used an array of string it logged this information too.

 

There existed a config module.  This module was a central place for setting all application settings and would publish data the config data as a second level variant repository, and would send out a global event when settings were updated.  This would cause all modules to go and read the new data and perform any operation it needed to with this new data.  Like if a new COM port was selected, we might want to close the current port and re-open a new one.  Changing settings while running a test were limited to prevent issues with this.

 

For debug I had an actor probe which registers for all events, request, reply, and global events, and has a central place to see all the events, and their data in the order they are generated.  Here is a post talking a bit about it and showing it.

 

And lastly Glued had no cloning of actors.  In my design I haven't really had a need for it.  So if I needed a CAN actor for doing CAN communication, I would make that actor and call it in parallel with all the other actors.  They all started at the same time, and all stopped at the same time.  No actor ever shutdown, without sending a message to shutdown he other actors.  This again might be because I focused on request reply more and sending a request to an actor that doesn't exist, had issues.  Actors not being clones makes debug a lot easier.  At any point in the software I could go to the main VI, hold CTRL and double click the actor, which would open the BD of the actor VI that was running, and start probing wires.  If I had N CAN cards it would be handled by having one CAN actor with with an array of hardware references to work with.

 

Oh and I noticed this is for 2014 and newer only Glued was 2011 and newer, but I think that held it back a bit because of some of the improvements in 2012, and 2013.

 

Wow wall of text so sorry, can't wait to meet up with you next week and we can talk more if you are interested.  Thanks again.

  • Like 1
Link to comment

 

TLDR: Delacor has some cool stuff, and I had some cool stuff.

 

Wow very cool Fab.  

 

 

Glad you liked it, this has been a Delacor team effort: we had 3 CLAs involved in architectural design decisions, design reviews and implementation. We also have been using this in several projects and gathering feedback from customers and Delacor team members. I don't want to take all the credit.

 

 

 

I'm starting to wonder if everyone has developed something like this in secret and just not published it.  I didn't really get around to getting permission to post my version publicly, but I talked about it and even named it Glued.

 

I am sure there are lots of versions of this architecture out there. The community has been using variations of QMH architectures for a long, long, long time. Delacor team members have been using variations of the DQMH for at least 10 years. We decided to publish ours, because it is easier to ask our customers to use something available from the LabVIEW Tools Network that has the "LabVIEW compatible" logo and it is more convenient for us instead of having to reinvent the wheel for every project, or worse, a flatten tire, because we forgot one little detail here and there.

 

 

 

DQMH and Glued both had scripting for adding new modules, and messages.  Glued didn't have one for removing messages so good on you.  Glued also had the ability to create global messages, which is a message all modules listen and react to.  This makes messaging 1:1, and 1:N, I never came up with a good N:1 scheme but then again I didn't really need it.

 

IMHO, the scripting tools are the biggest feature in DQMH. I still smile every time I create an event or add a DQMH module. BTW, if there are features missing or people would like to add similar scripting tools to their existing architectures, please talk to us, we might be able to make this happen for you.

We didn't think about adding global messages, we will give it some thought, although I believe this would go against our goal of keeping DQMH modules as stand alone modules to reduce coupling between modules.

 

 

 

When doing a Do Something Wait for Reply, you use a user event to send the message and a notifier to wait on the reply.  I found this to be a bit problematic when doing a shutdown.  If I have a sequencer running that is requesting analog data and waiting on the reply, but at some point the user closes the software.  That close is going to be a global event telling the whole application to shutdown.  If my analog actor loop shuts down, but my sequencer doesn't get the request to shutdown, before requesting a read, then all actors will shutdown except the sequence, which will be waiting for the reply from the analog.

 

We realized we were not covering 100% of the use cases for "Request and Wait for Reply" events. We went for the template that would answer 80% of the cases with a very short timeout. In the future we will have a blog post with some of the alternatives we have for this type of event. We even hesitated to include this type of event, because of the potential for deadlock. This type of event is very rare in our current applications. Some of the comments/feedback we got from the CLA summit was that we should have used a SEQ instead of a notifier, because for large data sets the notifier will result in a data copy and the Queue would not. We decided that the notifier was more readable and again it covered 80% of the usage. If the reply requires large datasets, the argument of the notifier reply could be wrapped in a DVR.

 

 

 

For the messaging there are essentially three functions you need to have.  Sending the request, convert the request variant to the request type def, and send the reply.  There were also two typedefs, one for the request data one for the reply.

 

This is not always the case, when using the Tools>Delacor> Create New DQMH Event... menu, you will see that there is an option of creating a "Round Trip (Request + Broadcast)". This option creates the Request Event and the Broadcast Event both sharing the same typedef for their argument.

 

 

In Glued this was all contained in one polymorphic VI.  The purpose of this was to quickly find where in the code a request was being sent, or a reply was being sent by right clicking on the polymorphic instance and selecting Find All Instances.  Then I could find all places I was requesting data, where I was acting on that, and where I was sending that data back.  The Request, or the Request and wait functions were in the same VI, and there was a boolean input for Wait For Reply.

 

 

In a DQMH module, the Requests can be found as part of the Public API virtual folder in the DQMH Module.lvlib. When finding where these functions are called, we can find what other code is making requests of the module.

The Broadcasts can be found as part of the Broadcasts Private folder in the DQMH Module.lvlib. These VIs should only be called by functions within the DQMH Module.lvlib.

In our case, we found that keeping these functions separated in this fashion resulted in the best Developer Experience. Especially when dealing with different levels of proficiency.  Some of the teams we work with, the architect would create the DQMH and a CLD or CLAD would just call the Public API VIs, they only care about using the Requests. In fact, some of our customers choose to lock the DQMH Module library so the junior developers have access only to the Public API VIs.

 

 

 

In Glued modules has the ability to send a message to itself using the same polymorphic request VI mentioned before.

 

In a DQMH module the Queue is private to each module and it is used to send messages within the module itself. The Events are used for any external communication handling.

 

 

There existed a manual screen module.  This module was a place for all other modules that had manual panels to be seen.  It basically was a listbox of modules, and a subpanel to insert into it.  This is where sending messages to itself would come in handy because the buttons on the FP of the module invoked the same code as that message would coming from any other module.  In this manual screen actors could be undocked, which would just make floating windows of each.

 

 

This is an interesting idea. It is really hard to draw the line on what is needed for every single application and what is needed only for some applications. We tried to keep the DQMH Project Template to the bare minimum we found ourselves and our customers using in all of their projects.

 

 

 

I prefer state machines that have the ability to have multiple cases queued up.  Either a multi-line string like JKI, or an array of string, or even an array of enums if you want.  I'm sure you are familiar with the pros and cons.  Glued used an array of string, but I've been using a modified JKI lately and think I prefer that.

 

The DQMH Enqueue Message is a polymorphic VI that has the option of enqueing a single message or an array of messages.

Also, the DQMH is a Queued Message Handler, not a state machine. Implementing a State Machine with a module that is asynchronous and can receive messages from a lot of different points in the application leads to getting messages in between the state machine states. If a true state machine is needed where none of its states can be interrupted, then we would code that case in the Message Handling Loop to call an actual State Machine. See my blog post on the NI QMH the section on Using a QMH as a State Machine: http://www.walkingthewires.com/2015/05/08/ni-qmh-template/

 

 

There existed a config module…

 

This is another example of us deciding to keep things to a minimum. We do have a DQMH Configuration Editor module that we use internally and gets modified to fit the needs of every application. So far this module has changed so much depending on the requirements of each customer, that we decided we couldn't include a version generic enough in the DQMH Project Template. Depending on how many people end up using DQMH, we might make modules like this one available in the future. Or maybe other members of the community decide to share their DQMH modules with the rest of the community.

 

 

For debug I had an actor probe which registers for all events, request, reply, and global events, and has a central place to see all the events, and their data in the order they are generated.  Here is a post talking a bit about it and showing it.

 

 

For debugging we went with the option of including a Test DQMH Module API.vi with every DQMH Module. It includes a status window that can be used to monitor what is going on with that particular DQMH module.  This tester can be used to test the DQMH module or as a sniffer when the main application is running to eavesdrop on the communication for that DQMH module.

 

 

 

And lastly Glued had no cloning of actors.  In my design I haven't really had a need for it.

 

We kept the Singleton and Cloneable modules separate, because we agree with you that most of the time cloning actors is not needed and we didn't want to burden the 90% of developers with the clone management needed just a few times.

 

 

 

So if I needed a CAN actor for doing CAN communication, I would make that actor and call it in parallel with all the other actors.  They all started at the same time, and all stopped at the same time.  No actor ever shutdown, without sending a message to shutdown the other actors.

 

We wanted to make it possible to restart a module without having to restart the entire application.

 

 

 

This again might be because I focused on request reply more and sending a request to an actor that doesn't exist, had issues.

 

The DQMH Module Public API VIs return an error if the module is not running. This can be tested via the Test DQMH Module API.vi, if any of the buttons are pressed before the Start Module is pressed, the error will be shown that the module is not running and the tester will stop.

 

 

 

Actors not being clones makes debug a lot easier.  At any point in the software I could go to the main VI, hold CTRL and double click the actor…

 

The Test DQMH Module API.vi includes a "Show Block Diagram for Troubleshooting" button, this works both in the Singleton DQMH module and the Cloneable module. In the cloneable module, the developer can choose to send the request to All clones or to an individual clone at a time. This is one of my favorite features. One that I thought at the beginning it was not needed, because my workaround of holding the CTRL and double clicking kind of worked, but if you have a chance, give this button a try… this is another feature that makes me smile every time I use it and prove that having a team to review your decisions leads (hopefully) to a better developer experience for all.

 

 

Wow wall of text so sorry, can't wait to meet up with you next week and we can talk more if you are interested.  Thanks again.

 

 

Even longer now with all my replies ;) I appreciate you taking the time to take a look at the DQMH toolkit. I am looking forward to meeting up with you next week and talking more about this.

 

Happy wiring,

Fab

  • Like 1
Link to comment

Fab,

 

This looks really cool, I look forward to digging into it.  I haven't looked through all of the sessions next week, any chance you will be presenting it during one?

 

Hi Jordan,

 

I will be using the DQMH shipping examples for the demos in the Reusable code presentation and we use DQMH for the project described in the Curing Cancer presentation, one of our customers will be presenting about his experience using our modular approach to his projects vs his old code & fix approach. Chris Roebuck will be using DQMH in his demos to show how to leave the coding and debugging in LabVIEW and call the public API from a DQMH via TestStand sequences during his LabVIEW Developers guide to TestStand presentation.

 

You can also watch some of the getting started videos that we have created for DQMH, there is a link to them at: http://delacor.com/products/

 

Here are the presentation details:

 

TS6420 - 5 Tips to Modularize, Reuse, and Organize Your Development Chaos

Fabiola De la Cueva, Delacor

Tuesday, August 4, 3:30 PM - 4:30 PM  Room 19A

 

TS7238 - Curing Cancer: Using a Modular Approach to Ensure the Safe and Repeatable Production of Medicine

Duncan MacIntosh, PerkinElmer

Fabiola De la Cueva, Delacor

Wednesday, August 5, 3:30 PM - 4:30 PM   Room 19A

 

TS6421 - Don't Panic: LabVIEW Developer's Guide to TestStand  

Chris Roebuck, Delacor

Thursday, August 6     2:00 PM - 3:00 PM  

Room 16B

 

Hope to see you there,

 

Fab

  • Like 1
Link to comment

There are two things I'd like to say about this thread.

 

1. It underscores for me how often CLA-level "in-house" projects are undertaken that run more or less in parallel to other such projects.  In some ways this is a very good thing as it allows for diversity in approach and implementation but also a robust degree of competition that, hopefully, increases the overall qualitym usability, scalability and extensibility of the various offerings.  We have some very brilliant and creative people in this community! But there is also a downside to this diversity and that involves confustion to the populations end-customers who look for well done implementations of whatever "needs to be used" so that their requirements are met. I mentioned the idea of conmsidering some form of "steering committee" to at least somewhat coordinate all of these efforts so that there isn't just a glut of competing toolkits overwhelming the Tools Network.

 

2. The second point concerns this following specific exchange (just above):

 

Quote

 So if I needed a CAN actor for doing CAN communication, I would make that actor and call it in parallel with all the other actors.  They all started at the same time, and all stopped at the same time.  No actor ever shutdown, without sending a message to shutdown the other actors.

 

We wanted to make it possible to restart a module without having to restart the entire application.

 

I continue to work closely with Delacor and greatly appreciate this specific feature in the DQMH. My project calls other stand alone 3rd party software that can be separately shut down by an end-user and we need to be able to restart that separate EXE asynchronously when that happens, however it did happen.  To be clear, it is impossible to prevent or trap that end-user action (to preclude that 3rd party EXE from being shut down) so we have to be able to detect when that has occurred and then restart the previously shut down 3rd party application autonomously, without further input or interference from the end-user. The DQMH supports this essential functionality. Other approaches might well be more appropriate in other specific situations (as in “Your mileage may vary…â€) but overall I think this is an extremely well implemented Template.

 

 

 

​

  • Like 2
Link to comment

On mobile so quoting fails me. I never have an actor be killed unless they all did. But if I want an actor to restart I send a message to it telling it to restart and it is in a state machine so it just goes to the data cleanup case then the macro initialize.

Link to comment

On mobile so quoting fails me. I never have an actor be killed unless they all did. But if I want an actor to restart I send a message to it telling it to restart and it is in a state machine so it just goes to the data cleanup case then the macro initialize.

Have you never had the use case of an arbitrary number of actors?  â€œRestart†works if you want 0 or 1, but what about N, specified at run time?  I made a “Popout window†UI actor just today to support an arbitrary number of independent windows in an application.  The actors start as needed and shut down whenever the windows are closed.

Link to comment
  • 2 weeks later...

Have you never had the use case of an arbitrary number of actors?  â€œRestart†works if you want 0 or 1, but what about N, specified at run time?  I made a “Popout window†UI actor just today to support an arbitrary number of independent windows in an application.  The actors start as needed and shut down whenever the windows are closed.

With NI Week this fell off my radar sorry.  I never had a need for N floating windows.  But if I did I would handle it by having a single actor be the "Dialog Actor" or whatever, which would spawn new VIs asynchronously.  It would then keep track of all asynchronously running dialogs with an array of references.  Closing a window would send an event down to the Dialog Actor which would do whatever it is that it needed.  If the Dialog Actor got a message to close a particular window, or save or load control values it would be the one responsible for that.

 

I've also handled similar tasks by using a listbox of windows, which would insert them one at a time into a subpanel.  This handled the N instances of something in a single window.

 

The benefits of this type of design is the only thing that is asynchronous (and more difficult to debug) is the actual UI, not the actor it self handling all the messages.  Probing and opening that actor was easy because it was on the block diagram of my main running VI and I could hold CTRL and double click to open the BD.

Link to comment

Have you never had the use case of an arbitrary number of actors?  â€œRestart†works if you want 0 or 1, but what about N, specified at run time?  I made a “Popout window†UI actor just today to support an arbitrary number of independent windows in an application.  The actors start as needed and shut down whenever the windows are closed.

You mean like the MDI Toolkit? That just uses a list and adding it to the list instantiates the window. Or is it something different?

Link to comment

The “Popout Window†actor was a bad example; there are multiple ways to handle UI windows.   I meant a more generic “thing running in parallel that receives messagesâ€.  The same app with the popout windows has a reconfigurable-on-the-fly chain of analysis actors that pass data messages between them.  Actors are selectable from a list of plugins, and actors must be started and stopped as the User makes changes. 

 

Another example is a “TCP Connection†actor that is created for each connection made to a "TCP Listener†actor.

 

One can, of course, make custom code for each case, with an asynchronous call and the setup of some kind of communication, but using a well-tested “actor†template gets one up and running quicker and with perhaps fewer bugs.


The benefits of this type of design is the only thing that is asynchronous (and more difficult to debug) is the actual UI, not the actor it self handling all the messages.  Probing and opening that actor was easy because it was on the block diagram of my main running VI and I could hold CTRL and double click to open the BD.

 

I don’t really understand these benefits.  The major point of “actors†is to make async easier to debug, so why do I not want the actual UI to be an actor?  Every time I’ve tried making a custom async thing I’ve regretted not using my actor template.   And I’ve never found opening and probing async actors difficult (they have a “Show Front Panel†message)**.

 

— James

**Haven’t worked with actors on RealTime, so it might be different in that case.


You mean like the MDI Toolkit? That just uses a list and adding it to the list instantiates the window. Or is it something different?

No, they are just simple actors with a subpanel to hold a front panel.  They allow adding behavior like adding custom right-click menu options, highlighting the window when the User hovered over an icon the represents the window in the main app, notifying a managing actor when the User closes the window, etc.  All this could be done with dynamic event registration in a central component, which is why it is a poor example.

Link to comment

Another example is a “TCP Connection†actor that is created for each connection made to a "TCP Listener†actor.

So not TCP but I have had a case where I needed to monitor N CAN buses, from 1 to 6, across 1 to 3 PCI/PXI CAN cards.  I just had a single actor for CAN, which had an array of CAN port references.  I then had one UI that could show me the messages coming in from one port, or all of them with time synchronization.  

 

Similar situations with N DAQ devices.  One actor did AIO signals one for DIO but I could have gotten away with one DAQ actor I guess.  It got a message to read signals, then it would figure out based on what cards it was on, which tasks could be started in parallel, and it would do so creating an array of references that it kept track of.  Then the reply would send back the array of values that were requested.  The requester didn't care if it came from N actors, or were taken sequentially, or in parallel (unless specified), it just wanted data, and the AIO actor took care of it. 

 

The benefit in my mind was simple code.  Any LabVIEW developer with CLAD experience could open the code, find where actors were started in parallel (because they were just subVI calls) and find what was going on.  No nebulous cloud business, starting and stopping not knowing what is running or doing what.  Just open the VI and see.  I'm not saying it has to be this way but it was powerful and simple.  The next actor type framework I adopt is going to have those same requirements.

Link to comment

Any LabVIEW developer with CLAD experience could open the code, find where actors were started in parallel (because they were just subVI calls) and find what was going on.  No nebulous cloud business, starting and stopping not knowing what is running or doing what.  Just open the VI and see.  I'm not saying it has to be this way but it was powerful and simple.  The next actor type framework I adopt is going to have those same requirements.

 

This!!!!!

 

Welcome to my world. ;)

Link to comment

Have you never had the use case of an arbitrary number of actors?  â€œRestart†works if you want 0 or 1, but what about N, specified at run time?  I made a “Popout window†UI actor just today to support an arbitrary number of independent windows in an application.  The actors start as needed and shut down whenever the windows are closed.

 

We address this via the Cloneable DQMH Module. It already comes with clone management and at run time the N number of instances to launch can be selected. We have an example of this in the shipping example. The DUT is a cloneable module.

 

The benefits of this type of design is the only thing that is asynchronous (and more difficult to debug) is the actual UI, not the actor it self handling all the messages.  Probing and opening that actor was easy because it was on the block diagram of my main running VI and I could hold CTRL and double click to open the BD.

 

When a DQMH module is created, the tester comes with a button that shows the block diagram of the DQMH Module Main. If the DQMH module is cloneable, then it will show the block diagram for all instances if the ring is set to "All" or it shows the block diagram for the requested instance.

 

This feature was not included in the shipping example, but you can see it in a project created via the DQMH Project template or by adding a DQMH module to your project.

 

The benefit in my mind was simple code.  Any LabVIEW developer with CLAD experience could open the code, find where actors were started in parallel (because they were just subVI calls) and find what was going on.  No nebulous cloud business, starting and stopping not knowing what is running or doing what.  Just open the VI and see.  I'm not saying it has to be this way but it was powerful and simple.  The next actor type framework I adopt is going to have those same requirements.

 

In our experience, junior developers get around via the DQMH API Tester to know what is running or pressing the "Show block diagram" button on the tester to see what is going on in the DQMH Main.

 

Most of the time they do not need to go that deep and having a simple API with simple API calls: Start, Show Panel, Hide Panel, Stop, etc means they can do simple VIs that just call a chain of these calls. If they need to debug, they just need to run the tester and use it as a sniffer.

  • Like 1
Link to comment

Just open the VI and see.

Is that how your CLAD programmer learns about your Xnodes?   :)

 

But your right, it is a problem.  Even though I could show someone what to do in minutes, it’s easy to have no idea what the first step to do is.  Fabiola is fighting that problem by providing several instructional videos for her new Delacor framework.

 

I’ve been trying to develop a way to make my actors easily switched between reentrant and non-reentrant, so I can leave single-instance actors as more “just open and seeâ€.  It hard, because I don’t want to give up other simplifying features, like auto-shutdown of actors.

 

 

The benefit in my mind was simple code. 

 

As Fab points out, one can also provide a junior developer simplicity via a simple API or set of tools that encapsulates complexity.  And personally, I think there is simplicity in standardization, since there is so much effort in learning code structure.

  • Like 1
Link to comment

Is that how your CLAD programmer learns about your Xnodes?   :)

I honestly don't know what you're talking about, I get that it is a joke but I don't get the joke.  You can't easily just open an XNode.  If there a template VI (like most of mine have) you can open that but actually opening the code generated requires some INI keys.

 

 

And personally, I think there is simplicity in standardization, since there is so much effort in learning code structure.

Yeah that's part of the problem, the only "standard" on making an actor design at the moment is the NI Actor Framework.  This standard is not catching on in the advanced developer community.  I can speculate why but the point is, if standardization is key to adoption, then all of these different designs might be adding to the noise.  Which is hard for me to say because lots of what i see in the DQMH, and JKI Objects I like a lot.  And will likely be using one of them over the Actor Framework.

 

The value of the DQMH videos, and scripting code should not be understated.  Conceptualizing, and designing actor based software is confusing at first.  Being able to say "Here watch this video for a few minutes, and you'll get the basics." is going to be a very valuable tool.

  • Like 2
Link to comment

 

But your right, it is a problem.  Even though I could show someone what to do in minutes, it’s easy to have no idea what the first step to do is.  Fabiola is fighting that problem by providing several instructional videos for her new Delacor framework.

...

 

As Fab points out, one can also provide a junior developer simplicity via a simple API or set of tools that encapsulates complexity.  And personally, I think there is simplicity in standardization, since there is so much effort in learning code structure.

 

We are also fighting the problem via the scripting tools. Automating the busy work and abstracting that away from junior developers. In our experience, explaining the concept of user events and how the information is transmitted from DQMH module to module has never been the problem. The problem is when the junior developer has to remember all the steps needed to create a user event. With the scripting tools we automate most of the busy work and let the junior developer do the final connection of editing the event structure case to handle the specific event, but they don't have to worry about remembering to add the new event to the typedef, to the destroy events, to the create event, etc, etc.

 

 

Yeah that's part of the problem, the only "standard" on making an actor design at the moment is the NI Actor Framework.  This standard is not catching on in the advanced developer community.  I can speculate why but the point is, if standardization is key to adoption, then all of these different designs might be adding to the noise.  Which is hard for me to say because lots of what i see in the DQMH, and JKI Objects I like a lot.  And will likely be using one of them over the Actor Framework.

 

The value of the DQMH videos, and scripting code should not be understated.  Conceptualizing, and designing actor based software is confusing at first.  Being able to say "Here watch this video for a few minutes, and you'll get the basics." is going to be a very valuable tool.

 

standardization was a big part for the Delacor team deciding to use the NI QMH as our springboard. The producer/consumer and QMH templates were the ones we realized most of the junior developers we encountered were familiar with. This is one of the reasons the Main module looks a lot like the NI QMH template, with minor exceptions. 

 

Glad to know that DQMH is one of your options for your future projects. Let us know if you decide to go with it. 

 

Also good to know that you find both the videos and the scripting tools useful. This inspires us to continue to create such tools for the community.

  • Like 2
Link to comment

 You can't easily just open an XNode. 

Exactly.  They seem to me to be much harder for a CLAD to get to grips with than my async-called, shared-reentrant actors (though I am an XNode novice).   

 

 

Yeah that's part of the problem, the only "standard" on making an actor design at the moment is the NI Actor Framework.  

 

Poor wording on my part.  I don’t mean community standardization;  I mean developer or team standardization on using a limited set of ways of doing things, so that one be expert in those techniques, and one can read and understand code quicker.  I use my actors extensively, at multiple levels in my code.  I don’t use techniques like “Action Engines†or any asynchronous calls of custom VIs, because I’m standardizing on Messenger Library actors.

 

The actor I did just today is a small, one-VI-API “helper†that adds functionality to a WaveformGraph.  It is based on the exact same actor template that is used by my “Top Level†main application, and is using the same standard techniques.  

Link to comment

Exactly.  They seem to me to be much harder for a CLAD to get to grips with than my async-called, shared-reentrant actors.

 

This is an apples and oranges comparison.  One is a framework intended to be developed and modified, the other is a more or less closed module that the user is never intended to open, just use it.  One is feature complete, the other is a shell of an application.  In that case I would say using an XNode is something a CLAD developer can do with no instructions.  You've probably used a few XNodes without even knowing it (NI slipped a few on the palette over the years).

 

Your comment about standards makes more sense now, and I agree with it.

Link to comment

One is a framework intended to be developed and modified, the other is a more or less closed module that the user is never intended to open, just use it.  One is feature complete, the other is a shell of an application. 

 

Well, the internals of the framework are not intended to be modified (or at least that would be a very advanced use).  Application-specific code is meant to just be simple message-handling loops, with an API for passing messages.  No LVOOP beyond copying a template class containing one “actor.vi†method.  That those “actor.viâ€s are forced to be shared reentrant, with a resulting learning curve, is a problem.  This conversation has lead me to reattempt a way to allow non-reentrant actors and I think I have a solution that works well, with the ability for a CLAD to more easily find his way through the code.  I’m going to try it out in my current projects.

Link to comment
  • 3 months later...

logo-delacor-unbalanced-300x129+copy.png


 


Delacor is thrilled to announce the release of the DQMH Toolkit 2.0 to the LabVIEW Tools Network (LVTN).


 


 


This 2.0 release brings a number of new features (they are awesome and worth the download alone) and improvements.


 


These changes were inspired by our desire to give you the best possible experience for rapid LabVIEW application development and by the great feedback we received from you.


 


 


We have incorporated some of this feedback into our 2.0 release and will continue to do so on future releases.  You can read the release notes for a full description of all of the changes.


 


 


At your convenience head on over to the LabVIEW Tools Network and grab the DQMH Toolkit 2.0 directly or upgrade by refreshing the package list in VI Package Manager.


 


 


If you are upgrading from an earlier version of the DQMH Toolkit please ensure that you upgrade the Delacor QMH package that will take care of upgrading all the toolkit required packages.


 


 


All that remains is to launch the DQMH and get to work!


 


 


Many thanks,


Team Delacor


Edited by Fab
  • Like 2
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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.

×
×
  • Create New...

Important Information

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