08-08-2021 12:17 PM
@drjdpowell wrote:
I used to use the JKI "State Machine" and developed a similar set of rules:
- It's not a State Machine! It's an Event Handler with an action execution machine. The "State Queue" is an "Action Execution Stack"
- "States" (actually actions) can be queued on back or stacked on front; always stack on front.
- Don't use "state looping" where a state calls itself indefinitely
- Handle an Event completely before starting handling the next Event (his means the "state queue" is empty before checking for the next Event). This is the same as your "messages are atomic" rule.
I developed my "DEV Template" message handler design from the JKI largely to make having these "Dos and Don'ts" unnecessary. (1) and (2) are addressed by new terminology and subVIs, so a user intuitively understands that this is an action stack, (3) is rendered impossible, and (4) happens automatically (unless you really want it, in which case it is explicit).
I think the DQMH would benefit from a similar attempt to make at least some of your painful experience unnecessary. And the significant but most straightforward and high-value change is to the combine Event and Queue handling loops into one single "brain", with access to all state data and direct access to incoming Events.
I do agree. Finding an engineering solution that makes it virtually impossible to do the wrong thing is a much better solution than relying on people memorizing and following a set of rules. It's also much harder and much more effort. But then again nothing good in life is free.
08-08-2021 01:24 PM - edited 08-08-2021 01:28 PM
Making it impossible to do the wrong thing is not itself possible. It's trivially easy to drop a global variable in any fancy architecture, or any one of an large number of quick shortcuts. Instead, one must make the right way (or, at least, a decent way) the natural and easy option.
So, combining the two loops in the DQMH would eliminate a lot of potential wrong things with no effort at all. In fact, everything woul be easier as you also eliminate all the boiler plate code between the two loops
08-08-2021 01:32 PM
I'm glad forum participants responded to my request to keep the discussion open. Thanks, this became a very informative topic!
08-08-2021 01:43 PM
@drjdpowell wrote:
Making it impossible to do the wrong thing is not itself possible. It's trivially easy to drop a global variable in any fancy architecture, or any one of an large number of quick shortcuts. Instead, one must make the right way (or, at least, a decent way) the natural and easy option.
Fair point. You can't prevent people from willfully circumventing things, but if you do make it easier to do things the intended way, most people will follow the path of least resistance.
Although at that point I have to ask, are you setting them up for failure? At that point they are doing things a certain way, simply because its the easiest thing to do (because we've intentionally made it that way), without understanding why or any of the tradeoffs. When they go off on their own, without anyone holding their hand or pointing them in the right direction, what will they do then?
08-08-2021 01:56 PM
@Taggart wrote:
Although at that point I have to ask, are you setting them up for failure? At that point they are doing things a certain way, simply because its the easiest thing to do (because we've intentionally made it that way), without understanding why or any of the tradeoffs. When they go off on their own, without anyone holding their hand or pointing them in the right direction, what will they do then?
That's a little like asking if designing safer cars is setting drivers up for failure. You don't have to give your 17-year old child a crappy car without airbags and poor steering in order to be able to teach them to drive.
08-09-2021 01:20 AM
@RTSLVU wrote:
But anytime I posted some code like this without those Shift Registers people would come out of the woodwork to tell me I MUST put Shift Registers on the Queue in my loops.
Example
The only thing that I can think of which would be relevant in code of this general structure would be if these were for loops, which can run 0 times, and which you therefore want to pass references through using shift registers (or not at all. Some people prefer not to output something which is an unchanged input, but that's a different direction altogether). If you're not changing the reference, then the shift register does nothing.
08-09-2021 03:21 AM
I realize I'm banging on about this, but it is because my point keeps getting misinterpreted. So to continue the car analogy:
08-09-2021 08:59 AM
@drjdpowell wrote:
I realize I'm banging on about this, but it is because my point keeps getting misinterpreted. So to continue the car analogy:
- You have a crappy car.
- We know there are more sophisticated and advanced cars out there, but this is a decent, simple, reliable car.
- No, that is a crappy car; it's not reliable, and it is not simple to use.
- We know one could add automatic transmission and even self-driving capability, but that is complex and expensive and wont allow young drivers to understand how cars work.
- No, it's a crappy car. It's basic steering and brakes have serious design flaws.
I'll give a different view on it.
Is walking obsolete now that we have bicycles?
Are bicycles obsolete because we have cars?
Are cars obsolete because we have planes?
Well, it depends on where you are, where you want to go and what you have available at the time.
But on topic: I personally don't view the QMH as obsolete at all. It's an important step in learning the basics so that you can possibly understand the reasons why other systems are set up differently. As this discussion shows, there is more than one way to fix the obvious problems with the QMH. Depends on where you want to go.
Having said that, I don't think I've ever used an NI template for actual code.
08-09-2021 09:51 AM
@drjdpowell wrote:
@Taggart wrote:
Although at that point I have to ask, are you setting them up for failure? At that point they are doing things a certain way, simply because its the easiest thing to do (because we've intentionally made it that way), without understanding why or any of the tradeoffs. When they go off on their own, without anyone holding their hand or pointing them in the right direction, what will they do then?That's a little like asking if designing safer cars is setting drivers up for failure. You don't have to give your 17-year old child a crappy car without airbags and poor steering in order to be able to teach them to drive.
I'm gonna "steer" away from the car analogy (ha, ha ha). If you tell novice developers "There's about 80 different ways to do this but this way is the best, so do it this way," but don't explain why it's easier, or less error prone, or more scalable, or just "fits" better for this specific use case, then IMO yeah you are setting them up for failure.
Saying "Thanks that fixed it" or "Thanks that answers my question" and not giving a Kudo or Marked Solution, is like telling your waiter they did a great job and not leaving a tip. Please, tip your waiters.
08-09-2021 10:37 AM - edited 08-09-2021 10:46 AM
@FireFist-Redhawk wrote:
If you tell novice developers "There's about 80 different ways to do this but this way is the best, so do it this way," but don't explain why it's easier, or less error prone, or more scalable, or just "fits" better for this specific use case, then IMO yeah you are setting them up for failure.
That's the problem: the NI version of a QMH has been "taught" to generations of LabVIEW programmers as "the QMH", with no explanation of any reason why it is the way it is. Since queued-message-handlers are extremely important, this very damaging. Note that no DQMH expert was able to explain why the NI-QMH is the way it is or what advantages it might have; they just use it because it is the rote way taught by NI. Groupthink.