Leaderboard
Popular Content
Showing content with the highest reputation on 06/25/2010 in all areas
-
First thing that popped into my head reading this: "I'm Dr.T and I'm a Night-Elf Mohawk." Sorry to be off-topic on an off-topic topic but I couldn't help. BTW, I love this off-topic topic...2 points
-
Quite possibly true. I do continue to use the term QSM because that's the name the Labview community associates that pattern. However, when I recognized my own applications based on the QSM were becoming unmanagable I started searching online for information about how to design a program using a QSM. Couldn't find much of anything. So then I started reading about state machines in general and how they apply to software. None of that info made much sense in the context of applying it to a QSM in Labview. Why? Because a QSM isn't a state machine in any common understanding of what state machines are. Yeah? Then NI is wrong too. You hear that Dr. T!? I'm calling you out! (Albeit very quietly...) I could start calling an apple an "orangutan" and those who know me well would understand my meaning, but when somebody in an online forum asks for a dessert suggestion because the the in-laws are in town and I respond with "orangutan pie," it's bound to cause all sorts of trouble. (Especially when I recommend using peeled orangutans and removing the stem. ) I know I'm unlikely to change the world and get everyone to start calling it a "function machine." I'm sure there are those reading this (if anyone is left now that we've completely derailed the original topic) who dismiss this as a minor semantics issue. I disagree--what we choose to call things often conveys information about that thing. "QSM" implies that pattern is, in fact, a type of state machine when in reality it is not. If instead of "QSM" we referred to that pattern as "Hector," I would consider that a better (if rather arbitrary) name. "QSM" is an extremely poor name for the pattern. I do believe that once you recognize that it really is a function machine (or MFVI) and start thinking about it in those terms, the questions that follow will naturally lead to a more suitable pattern. The question that started me down that path was one I asked you earlier. "How do I decide if an arbitrary piece of functionality should be in a state or a sub vi?" What heuristics and guidelines would you give to a junior developer that asked you that question? Doesn't matter if the QSM is based on strings, variants, enums, or classes. It's the architecture itself that is flawed, not the data it passes. (I suppose it wouldn't surprise you that I'm not a fan of the QMH either.) I've not heard that phrase before. "Multi Functional VI" does more accurately describe what it is and, somewhat ironically, also perfectly explains why you shouldn't use it for applications. Code is easier to maintain over the long run when it is separated, not combined. This is known as separation of concerns. (QSM code is similar to procedural code, so read the sentence about C and Pascal.) I could use my favorite procedural programming language and write a generic function similar to this... DoEverything(str funcName, var funcArgs){ Select funcName { Case = "Func1" { Cast(funcArgs, string); // do stuff }; Case = "Func2" { Cast(funcArgs, int); // do other stuff DoEverything("Func1", varData); }; Case = "Func3" { Cast(funcArgs, string); // do stuff again DoEverything("Func1", varData); DoEverything("Func2", varData); // do even more stuff }; Case Else {}; };};Main(){ funcNames[] = {"Func1", "Func3", Func2"}; funcArgs[] = {"Foo", 42, "Bar"}; For i = 0 to 2 { DoEverything(funcNames, funcArgs; };}; (I'll be the first to admit this is an imperfect textual metaphor for the QSM. For one thing the above implementation uses a function stack (permitting a kind of recursion) instead of a function queue. For another it doesn't show many of the QSM features, such as capturing events/messages. Regardless, the metaphor is attempting to illustrate the code structure of the QSM, not the actual implementation.) The question is why do this? Doesn't it make much more sense to have Func1, Func2, and Func3 be their own functions instead of wrapped in an arbitrary DoEverything() function? Even if your functions didn't directly call into other functions, does DoEverything() strike you as good programming? I suspect the QMH and QSM came about from attempts to "keep all the code on one screen" and a general reluctance to create sub vis. I understand that--I used to hate having to make a bunch of sub vis too. (Still do if its only purpose is to reduce the amount of screen space requried.) There are practical advantages to using sub vis instead of states. Earlier I mentioned it is clearly (IMO) more readable when the program flow is defined by the block diagram instead of by the queue. There are other advantages too. Using sub vis instead of states is also much safer, especially when the application gets complex. Consider three sub vis which form a cycle by calling into each other like this: SubVI1 --> SubVI2 --> SubVI3 --> SubVI1 Labview throws a compiler error if you do this--you end up with a broken run arrow. If you use states that enqueue other states instead of sub vis Labview's compiler can't check your code for cycles. Unless your application is very simply it is unreasonable to expect to be able to write test cases for all code paths. In short, the only way to make sure any given change has not introduced this error is by inspection. Dunno about you but the thought of having to manually trace through all the state machine's execution paths for any non-trivial changes is decidedly unappealling. Another nice thing the compiler does for us when using sub vis instead of states is ensure type safety. When you're converting all your data to a string so it can be passed to the next state (function) you're preventing the compiler from doing that. All those edit time broken wires that would have appeared with sub vis have just turned into run time errors that may or may not be caught by your testing. Once again, the only way you can be sure you've got it right is by inspection. Code inspection has a place in programming for sure, but expecting it to be sufficient for anything other than simple algorithms is a mistake imo. (Speaking of type safety errors, there's a bug in the pseudo code I posted above. Did you notice it while looking over the code? How long did it take you to find it? Had each function been broken out on its own the compiler would have picked it up immediately.) Hate to break it to you Scooby, but their state machine pattern appears to be woefully inadequate for implementing state machines as well. I've spent far too much time on this reply as it is... I'll try to post more later. You're a Labview instructor? Very cool.2 points
-
1 point
-
1 point
-
Yes, I think you are taking the name too literal. They are called QSMs cause when you open up the NI manual it calls the design pattern a QSM (I don't know who came up with the name). As a side note the traditional name for the String Based QSM is the Queued Message Handler which is exactly what the JKI QSM is based on (string based). Now I understand what the "Function Machine" term was referring to. But I think NI have coined the phrase Multi Functional VI (MFVI) already (sorry mesmith!) which is basically the(their) State Machine pattern combined with a FGV pattern - which when you look at the QSM is fundamentally what it is (along with the ability to queue itself). I agree the terms are confusing, bear with me here: I hold state information in USR (FGV) and runs different States based what wired into the Case Structure. The JKI combines the User Event pattern as well (all of this is NI terminology). Now when I say state information this is really the state of the objects in the application. This is normally implemented as a cluster (or class) of objects - but it only just acts as a container. When I say States, I am really referring to Commands (so I agree with your expression of this). In terms of using States versus using SubVIs - I guess this goes back to our conversation about documentation in the CLD wrt MFVIs vs LVOOP: In that you can create single a single VI with many states or you can create a lot of subVIs (and I was discussing which would be faster/easier based on the time limit). So this is what I refer to by State and is why I talk about interchanging State with SubVI and when is the best time to use one of the other etc.... I find it comes down to management and how many different files I want to manage. I normally like to try to keep the QSM light on files (subVIs and typedefs) as long as its neat, whilst I prefer lotsa subVIs for my functionality and encapsulate that using LVOOP. So yes, maybe calling it a State Machine is bad? But it seems quite strongly part of the nomenclature of LabVIEW now to change it! But by all means go for it - although I have to teach it, so I will have to stick to it In terms of when you talk about State in this context - I usually try to encapsulate this inside an object. So in terms of your Soda Can example the Soda Can object would manage its own State. Having a QSM managing many objects' States would be very difficult. But these objects (may) needs to live inside a GUI - this is where I use QSM a lot - as the architecture for the GUI. But the QSM is not handling the Soda Can's State, it's simply calling and running the Commands from e.g. the User Interface. In some cases it will be up to the Soda Can what to do based on its internal State. I have found the QSM a great architecture for the GUI, and scalable too. From you images it looks like you have a string Command from a Queue wired into a case structure. Is this not some form of QSM (in the above sense)? It also seems you have taking messaging a step further and implemented the famous design pattern that Paul-At-Lowell raves about (he was threaten to post this recently, but this is the first LabVIEW example I have seen). So I am not familiar with it, and only know what I have read in HFDPs and wiki. But if you would like to, please feel free to post more on this as I am very interested in this as it seems you have a higher level of abstraction here. This raises the following question of interest about your style and application including: 1) How do you handle smaller GUIs. For example if you have a small application with a main GUI and 5 smaller dialogs (for data entry etc...) do you use this pattern (and separate GUI and Engine) for all of them? 2) What about really basic dialogs? 3) In the example you posted it seems like there is a great deal of work gone into the messaging, do you have a reusable framework to build from? Cheers -JG1 point