Jump to content

K-node

Members
  • Posts

    90
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by K-node

  1. I love to add to my personal collection of books, but at $100US list, this is a bit pricey for my own library (I like buying the cheaper used ones). I might get my employer to purchase, but I am interested to know if anyone has looked at it. Here is the publiisers link:

    http://www.crcpress.com/product/isbn/9781439839812

    It was published Dec 12, 2011.

    I am not familiar with the authors or contributors and the table of contents does not have me chomping at the bit, but I might be too focused:

    Excel ActiveX Automation Using LabVIEW, Steffan Benamou

    Interacting with Windows Applications, Bill VanArsdale

    A General Architecture for Image Processing, Craig Moore

    Radio Frequency Identification Read/Write in Sports Science, Ian Fairweather

    Pachube: Sensing the World through the Internet, Anne Brumfield

    Power System Applications in LabVIEW, Nesimi Ertugrul

    Recursive Computation of Discrete Wavelet Transform, Nasser Kehtarnavaz, Vanishree Gopalakrishna, and Philipos Loizou

    Solar Energy, Pedro Ponce, Brian MacCleery, Hiram Ponce, and Arturo Molina

    -Kurt

  2. Hey AQ,

    I had a look over AF, but I just don't think I'm ready (no free time atm) to battle with the OOP concepts. I'm pretty sure I can achieve what I'm trying to achieve with a regular labview architecture and proper hand-shaking or queue exchanges.

    Cheers,

    Alex

    Alex (and others interested),

    I have ported the AFv3.0.6 to LV2010. I am testing it now, but I am willing to share the code. Please PM me with your email address so I can keep track of the users and send updates.

    Kurt

  3. So I thought I'd reopen this discussion as I searched the forum for using classes as clusters. I'm working on a state machine which does the typical thing of passing constants, inside a cluster, around on a shift register. I've read that mimicing this behaviour using classes is a good way to start getting into OOP. I've broken up all the constants into categories that I think make sense (such as FPGA initlisation constants and Messenger Queue Refs). What is the best way of passing these classes on one wire? Similar to the way the data cluster is one wire. Conceptually, it's nice to break the constants up into areas of responsibility and initialise them using methods and such, but I don't want to pass a class wire for every set of constants. I also don't want to group all my constants into one Class as it seems yucky to me. What's the best solution?

    AlexA,

    If you want a single or reduced set of wires, you could make a cluster of the classes you have identified or even Class with the set of classes you identified as private data. I find the latter a bit overkill as you will need lots of accessor (Read/Write) vi's. So I would vote for making a cluster of classes.

    Kurt

  4. I would like to print the PDF of the conference program but on many of the pages, the links that get you to the previous page and next page show a thumbnail image as if my mouse was hovering over that. Does anyone know how to turn that off for printing? I have Adobe Reader 9.4.1.

    Thanks,

    Kurt

  5. I'm reviving this thread to ask for ideas on how I can prove that using an Event Structure as State Machine (ESSM) using Value Signalling of Booleans (VSB) to change states is a bad idea using objective evidence.

    Ideally I'm after ideas that I can code up in LV which show how an ESMM+VSB saturates one core on a CPU (making the FP unresponsive to user interaction). Its performance is then to be compared to an alternative architecture such as a Queued State Machine. All comparative tests to be run at say 1kHz in order to give a worst case scenario. One can easily achieve 1kHz by running 10 loops in parallel at 10ms loop time each, where each loop sets the value signalling property of a different boolean on the FP. I did this test at 1kHz and it surprised me when the UI was still responsive to my mouse presses.

    I had one idea while I was typing this up. I am going to run say 10 of these ESSM+VSB in parallel sub-vi's to see how problematic it is. Up until now I only had just one ESSM+VSB and was trying to break it at 1kHz. Rather than show you the code right now, can you come up with an idea for me to try along these lines ?

    My agenda is to discredit the idea of an ESSM+VSB because there are many reasons I don't like it, and I am declaring my bias against it. The reason I'm seeking this evidence is that I am being asked by my colleague to demonstrate using objective evidence why it is an unsuitable architecture to employ before enshrining it into a template/design pattern here at work for any size (small and large) project .

    Here is my list of Cons:

    • Changing states causes a context switch into the UI thread.
      ("so ?" comes the reply to my concern, "LV is efficient enough and today's CPUs fast enough to cope with this" !). My counter to this is in the next point.
    • The UI thread(s?) only run on one core, and processor speeds aren't increasing much these days, but the # of cores are. So with many of these ESSMs running in a program (in multiple parallel tasks all in sub-vis) , the UI thread will get hammered and saturated, having no option to offload to the other cores. (note that code in an ES state doesn't necessarily run in the UI thread, but the act of changing to a new state causes a switch to the UI thread)
    • Parallel programming is therefore discouraged as eventually the state changing requests will saturate the UI thread(s?)
    • It looks unprofessional to have your FP/GUI activity (i.e. graphs/leds/text etc) stammer/freeeze/get jerky when one moves ANY window on the desktop.
    • One can't probe states queued into the Event Structure (ES) prior to each state being transitioned to.
    • Upon an error condition, to prevent already queued states from executing one must have a case structure in every event case to bypass code on error because one can't enqueue an Error State at the front of the ES queue and then flush the remaining queued states.

    rgds

    I am no expert on this, but wanted to point out AQ's response to where Event Queues run. In short, it is not necessarily in the UI Thread.

  6. Named queues are especially bad. We have some control over the scope of the other constructs and can limit where they're used, but once we create a named queue there's no way to limit who interacts with it.

    I am not disagreeing with this point, but I always struggle on how to exchange queue information. How does object A tell object B to send me a message when criteria X has been achieved when A and B have been created independently. This is a classic Publish-Subscribe scenario. While I do not use the name parameter in my queue creation for this purpose, I do have a look-up table that is effectively the same thing.

    So, what is the best way to share queue references in a network of queues? Or perhaps you don't really share queues. Object A simply tells some message clearing house component that is it interested in knowing about 'criteria X' and Object B tells the same message clearing house component that it can generate a message on 'criteria X'. So, potentially, neither Object A or B now about each other, only the message clearing house component.

  7. So does anyone know If I can pay at the door or not? Do I have to pay through paypal?

    I have no idea, but Justin might respond to a PM if he is not watching this thread. I copied this link from the OP:

    PM Justin here for info.

    As we are still a bit away from the date, he might take a check. I expect he needs to commit $s to the restaurant.

    Good luck. Hope to see you there!

  8. OK, I am in. This is my first NIWeek. I am ready to say been there, done that, got the t-shirt and will do it again!

    Most of the time I lurk and learn from you folks, occasionally chiming in on the OO stuff - perhaps too rambling on some posts according to Daklu :rolleyes:.

    Anyway, this is going to be a long month until Austin.

    See ya' there!

  9. Ok, I have spent some time reviewing your code. From what I can tell, you have taken the functionality of the channel class and moved some of it into the message parent class or modifed it to be specific to a particular message class. The channel class now has nothing to do. We could simply eliminate it at this point. The only thing it does do in your version is carry the state data for the process. This could easily be replaced with a SR carrying a variant.

    Actually it carries nothing. At moment state data is in the ChannelProcess shift registers or derived classes. There may be reasons to keep it for the future. Suppose you would like every channel to have a name or a keep track of how many messages it correctly handled. I would add those as private data to the Channel class. Remember Channel_A and Channel_B both derive from Channel class. These children will have access to that data. In my opinion, it should keep track of its own queue, but that is debatable. Currently it is held by MessageQ and I can get it by creating a Channel_A_Message queue and I did not want to change your system. ALSO, and mos importantly, it is the common Channel class that is giving you the DynamicDispatch - what you refer to as the automatic channel selection.

    I see how splitting the messageQ class off on it's own simplifies the class hierarchy a bit, but as you acknowledged, it eliminates the automatic channel selection of the original architecture. But as you point out, the dev should know what channel they want to place a message one.

    It does not eliminate the 'automatic' channel selection. The channel selection you see is the design time resolution of a DynamicDispatch. Solely for the convenience of some lame programmers did you put these methods where they did not really belong. Think about the intent of the class and the methods it should publish. What is the intent of the MessageQ class? Despite its name, it really only keeps track of a list messages. What is a Channel class? It operates on a queue, but it does not hold the entire list of queues. What is a Message class? It holds data and actions that manipulate channels. They are distinct and do not have any hierarchical relationship to each other.

    With that change, why should the MessageQ be a class at all? Why not just have it be a DVR. That is all it is now. Having data accessors is not reason enough to use OOP in my opinion.

    You could do that. Actually, I can see MessageQ class being enhanced. I could send it a Channel_A_Message and it could return the queue for all Channel_A_Message derivations. This would isolate that loop that determines this and is implemented in multiple places.

    One other problem I see is your design allows the dev to put a message on a channel that is not designed to accept that message. So, if you are worried about runtime errors, that is a big one. The original architecture would not allow this. In fact, as pointed out, it automatically chose the proper channel for you. If you were to eliminated the channel class and simply have a custom message class for each parallel process, you could enforce the rule of sending a message only to a receiver that can execute it.

    I do not see what you say. Drag a B derived message down and attach it the Channel_A.SendMessage. It seems to change to Channel_B.SendMessage for me. Am I missing something? Again you are not seeing anything but the compiler resolving the call, not selecting what channel. You may think it is really the same thing, but it is the SendMessage implementation that actually selects the channel at runtime. I can change Channel_A.SendMessage implementation. I do think I lost any functionality, I simply moved it to a new base class called Channel. All I did was move the commands that did nothing in MessageQ class to the Channel class.

    Also noticed that the release channel will not work because you based the queue type on the message class, not the channel class. Why not move the Create and Release into the message class since that is where you get the type to set the queue from? Seems like if you are going to move the Send there, you should move all of it. Wyt have them in the channel class at all if you just need to override them or rewrite them for each channel you create. That was one of the benefits of the original design: you could simply copy and rename the channel class and you were done. No need to touch any the the VIs.

    I created the queues using the Channel_X_Message classes not the Channel_X classes. This seemed more appropriate to me. I missed the ReleaseQ method. The queue used to test against the list should be created using the Message_A class. Yes, you could move these things around. My goal was not to make so many changes that it would be confusing. Frankly, I would not search for a queue by trying to cast all of them into the one I desire, but I did not want to go down that path. Personally I would rather use some sort of look up table. Since each Channel_X class will have a queue, you could use the class name. The Create and Release methods do not belong in the message class. I would not find it natural to as a message for a queue. I would consider the Create and Release to be in the MessageQ class since it is the one keeping track of those anyway, but you would have to use some other scheme to identify the queue.

    Yes, I see by creating the queue from the Channel_X class you do not have to make any changes. I don't have an alternative for that but I am not a fan of your message type specific queues anyway, but that is just me.

    Overall, I understand you want to disconnect the classes from each other for 'good OOP design' reasons, but doing so in this case eliminates the functionality of the original design. I just don't see how it is better this way.

    I am still not sure you lost much that can't possibly be resolved in other ways. For the most part I moved methods to other base classes. What would be needed is an alternate approach to the identification of message queues based on message or class type.

    My original intention was to encapsulate a parallel process and all it functionality into a single entity and then allow other similar processes to communicate with it without the need to modify the architecture when extending it. That is why in my view a channel and its messages are already linked together and there is no need to separate them.

    Realize that you do have more than one entitiy, right? And the instantiation of a derived class as a new entity brings along with it all of its parents footprint. I would find it confusing as a developer to see methods available to me in the message class that really do nothing. So when I implement the Channel_A_Count.ExecuteMessage method and I connect the Write Count to the message wire the Channel_A count did not change. There is nothing stopping the developer from doing that.

    Perhaps it would be better to create explicit processes, like 'Database' and 'Display Driver' then attach child functions/messages to them, then have each create a queue and place it in a DVR that is passed around. That way, there is no master parent class and each process is not tied to the others, except when they want to pass a message in one of their functions using the queues in the DVR.

    I guess is all comes down to what should dynamic dispatch be used for? Should it be a way of enforcing a message passing system or is it only ok to use it for customizing functionality of a less specific class? I guess since I am new to this, I see this new tool and want to try using it for some purposes it might not have been intended for.

    I am not a fan of passing around a DVR. Actually you do not need to pass around the DVR but once. Once I have the DVR (as a true DVR not dereferenced) I have access to that memory and all of its updates that anyone does. That is the cool thing about DVRs. Publishing the list of queues does get to be a problem and I do not have a great solution yet.

    More experienced folks than I should answer the best ways to use DynamicDispatch. Your approach has its merits for your requirements. Not all systems have 7 unique channels. Some systems have hundreds of channels but not all of a unique type. Look at texting and cell phones. Cell phones are pretty much the same and they can send and receive a string. I would hate to create a unique Channel_X class for every phone - that's a lot of classes that are identical. I'd rather instantiate the same class for every phone.

    Oh, one more thing, with the changes you made, the Tube no longer 'knows'. Perhaps we should change the thread's subject?

    You are right. The message in my case determines where to be sent. But that seems normal to me. I like modeling behavior around the physical.

    Does anyone get my reference in the first place?

    Simpsons, Episode 407 at ~10:50.

    http://www.watchcart...arge-gets-a-job

    tongue.gif

    Sorry, I did not remember that episode.

    -kugr

  10. I'm not sure I understand how I can change this and maintain the functionality. By having channel inherit from messageQ and message inherit from channel, I can drop the 'send message' method from messageQ on the diagram, wire any message object into it, and the 'send message' will automatically change to the proper channel 'send message' method based on the hierarchy.

    Taking that to the extreme in a large system, you will have every possible method needed in every possible class with a Dynamic Dispatch vi originating from the base object. And all objects inheriting the memory footprint of the data (not the actual data of any instance) from all of its parent. So, what would I get if Channel_A_Count.ExecuteMethod 'called' its 'Read Channels' method. But Channel_A_Count does not have that property you say. It does from inheritance. So what stops the developer from selecting potentially wrong methods that might cause runtime errors? Nothing in this scheme. What is easier to fix - compile time or runtime errors - I would vote compile time. So a properly constructed hierarchy reduces these potential runtime errors.

    This seems to make it easier for the dev since they don.t need to know what channel to choose.

    You got me there, but perhaps they should not be programming :yes: The actually do not need to know what channel to select, only that they need to select from the base channel class as it has the abstract methods that would have been in your MessageQ. There was a thread in this forum sometime ago about right clicking on a terminal or wire and selecting from a valid list of methods for that terminal/wire type. That would help a developer. I think somebody implemented some add-in - sciware or black pearl perhaps, maybe a jki person.

    Also, the generic channel code only uses methods from messageQ that will be overriden by channel methods based on what type of channel is wired into the subvi. That makes the code to support a channel loop reusable. I can make as many channels as I want by simply copying this sub-vi and wiring in different channel objects.

    True, but my point is that those methods it uses do not belong in MessageQ since it has no use for them. They belong in the abstract Channel class including the process loop.

    Also, channel needs access to messageQ data to find the proper queue. By having this data common to all channels, any channel can put an object in the queue of any other channel.

    Yes, but it access the data via the MessageQ object passed into it, not from any internal representation of the MessageQ. In your implementation, the Channel does have the memory footprint (yes, a small DVR), but it is uninitialized. You are retrieving the data via a property call which has nothing to do with the base object of the channel.

    I would like to simplify this but being new to LVOOP, I am not sure I see how to. Can you make a simple example of what you think can be done?

    Funny you should ask. I did break up your example to see if what I was thinking would work. I am not sure you would call it simplified, but it encapsulates behavior in appropriate ways and perhaps it is better said as more understandable.

    For the most part it does work though I have some issues with the Stop not being a derived message. Not quite sure of that yet but I will, as they say, leave it to the reader. I did not clean up the folders and there is an abstract class called SuperClass that does nothing but it helped me dissect your initial hierarchy.

    Being new to LVOOP and asking questions on a forum such as this is a good thing. I am still learning and LVOOP is still forces me to think differently than traditional OOP.

    Have fun with it.

    -kugr

    p.s. Daklu, too much?:P

    MessageQ_krg.zip

  11. 1. Eliminated the need for a stop message. I changed the channel execute method to set stop to true. Now, if you send the channel object as the message, it will stop the channel's loop. good idea or bad? seems cleaner to me.

    I am OK with it as it seems that what your are doing is some default behavior for the execute method. Realize that 'Call Parent Method' from a child message will get you true for the Stop terminal.

    I still don't see the advantage of your single hierarchy. The MessageQ class in your implementation really only needs the Read and Write property for the list of queues and the ReleaseMessageQ. The channel or message classes do not to derive from MessageQ.

    The abstract Channel Class has a CreateQ, GetMessage and ReleaseChannel methods. Children of Channel would have additional property methods, etc. I would also put the ChannelProcess method as a part of the Channel class.

    The abstract Message class has the Send and Execute methods. To support your message routing scheme you would have abstract Channel_A_Message and Channel_B_Message. From there you would derive additional messages for specific actions.

    Clearly, as you have demonstrated, you can make a single hierarchy but a derived class should be some 'enhancement' on its parent. Your Channel class, derived from MessageQ, does not require anything MessageQ provides and does not add to anything MessageQ could do. MessageQ is really only a list keeper. It can do more, but it would not necessarily be channel or message specific. Similarly, your message classes do not use anything that its base classes provide with the exception of identifying the queue based on the parent Channel class. To me that is not sufficient (and can be done differently as stated above), and the extra baggage the channel adds to the derived message class with its member data and method vtable for no gain within the message class is, well, a red flag.

    In the end, if it works for you, that is fine. But if I had to maintain the code, it would irritate me.

    -kugr

  12. On second thought, is this really all that bad? Since they will not contain any data, how much performance penalty will there really be?

    Assuming you mean the message carries around uninitialized data, it probably is not that bad from a performance perspective. Still I have a problem with the hierarchy but I am no expert.

    I took a look at AQ's project you mentioned. While I am not sure I totally understand it

    Feel free to ask questions. I have pm'd AQ on the NI site and he has been very helpful. You can ask here too. I am using a derivation of this framework, but it is virtually unchanged from a fundamental aspect. Most of my changes were from deriving off of the classes. The biggest confusion is the creation of Actors. They are launched as opposed to having VIs with loops on the top level VI. And they have to exchange queue references - it is very clever, but takes a while to understand fully. Daklu's has a framework that looks great (there was an earlier thread about this) and actually can evolve into this if he ever desired to do that. His is simpler to understand from the contruction of 'actors' perspective. It uses strings, I think, to differentiate messages. The other 'challenge' with launching Actors is debugging. Good golly it can get confusing. I have started naming my queues solely to see who sent the message to who not to use in searching for a queue by name. I do need to keep track of queues, but I do that on my own.

    it does seem to have one thing in common with mine: every message is a class. Is this a bad idea? Is having a large class hierarchy a bad thing if the hierarchy is what controls the execution of your application?

    I hope not. It does make for a huge project and some maintenance issues when I find out I need to change something fundamental. For instance, I decided to wrap the LV queue object in a class - much like Daklu's message class. Ouch - every message had to be changed along with a number of other items including AQ's original framework. My biggest issue is the dependency between messages and actors. I have not been as careful as I should have in making sure about this. The dependencies make it hard to separate actors into independent projects - one actor sends a message and the message operates on another actor. So now sending actor's project will require the receiving actor's project. It is a hard thing to split.

    Overall, it has worked well for me. My Actors are set up to be observed so they keep track of who is 'watching'. They don't care who the observers are and will send an Update message to all of its observers. The observer does have to 'register' with the observed and this is done via a message. Actors that need to command other actors do so through a Proxy (a wrapper that handles sending the message for a specific command). This is not part of the AQ's original framework. The proxy adds a bit of complexity to the developer of an actor, but makes it easier for a user of an actor. Sine the actual message is hidden inside the proxy, a message really becomes calling a method. To set up a proxy, you do need to get the queue for a specific Actor so you've got some DB type stuff to handle there (some 'global' object needs to be able to resolve this request). I am not happy with my implementation of that, but it works.

    -kugr

  13. As daklu will attest, I rarely get involved in these discussions. Yes, dak, this is almost a monthly thing now! Anyway, my two cents...

    Is there a better solution to eliminate the need to modify the architecture to extend it?

    Have you checked out AQ's Actor framework? It does not perform auto-routing based on message type (I suppose there is some way it could be done) and it does not have the single hierarchy you might desire. But, each message has a Do (Execute) method. One of the terminals is the Actor (equivalent to your Channel class). Actor properties can be made public, so I can implement the all code in Message.Do.

    This is easily remedied. All I need to do is pass the channel object thru the execute and store it in a shift register. Here is an updated version of the project that does this.

    So now your message when passed around carries a potential boat load of uninitialized data that is got from deriving from the parent class. OK, fine, you can make it a DVR but now you have added a complexity to the problem and put yourself further from the dataflow paradigm.

    Why is the single hierarchy a requirement? There are really three distinct entities - messages, queues, and (for lack of a better word) actors. You can add a fourth, if you wish, as a message controller which your MessageQ class really seems to be. I am uncomfortable with making a a message a subclass of an actor which is a subclass of a message controller which is how I see your hierarchy.

    -kugr

  14. kugr, I'm not sure I follow your post entirely. However, an integral part of the fix for that CAR in 2010 SP1 requires you to recompile any VIs that use class property nodes. Deleting and replacing the property nodes would have caused it to recompile. If you can still reproduce the issue, please post your exact steps.

    I'm sorry that my features caused you so much frustration. Me right now --> :frusty:

    Thanks Mr Mike, Jon and JG.

    There is no way I can reproduce what I did. I moved a lot of files around and rearranged classes in a variety of new and existing libraries.

    Today I did put the Property capability back into the class that had the problem and used the Property Node in the VI was the last to execute before LabVIEW tanked. Not surprisingly, LV handled it this time.

    -kugr

  15. So, as my development normally goes, I end up refactoring the file and library structures in preparation for a cleaner release. Frequently (um, always), I break something and sometimes LabVIEW breaks something.

    Yesterday, I spent too many hours on a problem that caused LabVIEW to terminate unexpectedly and without warning or go into a hung state where task manager came to the rescue. In the end, the 'block' that caused my problem was setting two properties on a class using the Class Property Node capability in LV2010. I am using SP1. It seems that executing that function 'confused' LV. This approach was working until I made organizational changes to file locations and project libraries. I am pretty sure that this was the only place I used a Write property node where the class was inside a library (just an lvlib not packed). It could be that all I had to do was to remove the property node and add it again, but I was so frustrated by this problem that I got rid of class properties completely.

    When I finally realized where it died, I kind of remember reading about a problem like this on LAVA. I recall AQ indicating he was disappointed in how testing of this release missed this error. I cannot find that post though.

    Does anyone remember this? AQ, am I putting words in your post?

  16. Somewhere, on some website, maybe even this forum, there was listed a collection of native LV functions that operated even when the ErrorCluster indicated an error. This was not a bad thing as I think one of the VIs was perhaps the Close reference. Did anyone else remember reading that and where it was? I am remembering a collection of about 7 or so VIs were listed.

  17. Recently in this thread http://lavag.org/top...nentizing-code/ Daklu discussed his approach to error handling. This is toward the end of page 1.

    Those familiar with the standard templates for creating VIs for Static and Dynamic Dispatch and Data Member Access are already too aware of the big green box you are presented with in the block diagram wit the ominous command: "Wire the error cluster across even in the "No Error" case so that warnings get propagated." But is wrapping all of your code inside this block necessary? Daklu provided some thoughts that I thought deserved a thread of their own.

    Taken directly from one of Daklu's posts:

    First, I've ditched the rule of wrapping all sub-vi code in an error case structure. (Blasphemy! Burn me at the stake!) About 9 months ago AQ and I had a discussion about this. He termed it, "hyper-reactionary error handling" and talked about the impact it has on the cpu's resources. He said,

    Quote

    Since the common case is "no error", all that extraneous error checking *has* to hurt performance... I mean, in many VIs, several registers must be permanently allocated to the error cluster because it is constantly in your "most recently used" cache.

    These days I almost never wrap an entire code block in an error case. Many of my sub vis don't have an error case at all. The questions I ask myself when deciding about an error case are:

    1. Do I need the sub vi outputs to be different if there is an error on the input terminal? If so, then I'll use a switch prim or case structure somewhere on the block diagram, though it may not wrap the entire code block.

    2. Will the sub vi exit significantly faster by skipping the code on the block diagram when an error is on the input terminal? Yes? Then I'll wrap at least that section of code in an error case. The code I'm looking at here are things like For Loops containing primitive operations that don't have error terminals. String operations, array operations, cpu intesive math, etc. If a sub vi or prim has an error input terminal I don't worry about it's processing time. It will respond to the error input terminal appropriately and I assume (for simplicity) that its execution time = 0 if there is an error in.

    index.php?app=core&module=attach&section=attach&attach_rel_module=post&attach_id=4025

    In the diagram above I'm doing a lot of data compilation to gather the information necessary to create a GutStep object. However, the only primitive operations on this bd are Search Array and Index Array. Is the time saved in those rare instances where there is an error in worth the cost of error checking the other 99.9% of the time when there isn't? Nope, not in my opinion. In fact, this entire block diagram and all the sub vis execute exactly the same code regardless of the error in condition. (I know the sub vis ignore the error in terminal because of the green triangle in the lower left corner.)

    But low level performance isn't the main reason I've ditched it. I found it adds a lot of complexity and causes more problems than it solves, like the issue you've run into. You've wrapped your accessor method code in an error case because that's what we're "supposed" to do. Why does the accessor method care about the error in terminal? Is unbundling a cluster so expensive that it should be skipped? Nope. Is it the accessor method's responsibility to say, "I saw an error so I'm not returning a real queue refnum because some of you downstream vis might not handle it correctly?" Nope. Each sub vi is responsible for it's own actions when there is an error on its input terminal.

    In pratical terms that means my accessor methods never have an error case. They set/get what's been requested, each and every time. My object "creator" methods almost never have an error case, also passing the error wire through. Most of my "processing" method don't have an error case either. In the diagram I have 3 different "Lookup" methods. Each of those encapsulates some processing based on the inputs and returns an appropriate output. None of them change their behavior based on the error in terminal's state.

    However, each of the three Lookup methods are capable of raising an error on their own (I know this because the lower right corner doesn't have a colored triangle,) which would ulitmately result in an invalid GutStep object being sent out. Is it the factory method's responsibility to try and prevent downstream code from accidentally using an invalid GutStep object? Nope. It's the factory method's responsibility to create GutStep object to the best of it's ability. If an error occurs in this method or upstream of this method that might cause the data used to create the GutStep object to be something other than expected, this method lets the calling vi know via the error wire. It's the responsiblity of the calling code to check the error wire and respond according to it's own specific requirements.

    That's a little bit more about my general approach to error handling. It's more geared around responsibilities--who should be making the decision? (Responsibility-based thinking permeates all my dev work.) I've found that, in general, much of the time I don't really care if there's an error on the wire or not. Many of the primitive functions and structures already know how to handle errors. What do I gain by blindly adding more layers on top of it? Complexity in the form of more possible execution paths, each of which needs to be tested or inspected to verify it is working correctly. Thanks, but I'll pass. ;)

    ============================================================= END OF EXCERPT=============================================================

    All, I can say is 'Damn I wish I had thought about this' and then thought about the importance of this information buried in a thread about Componentizing code. So, with his permission I decided to generate this thread. Your comments are always appreciated.

    -kugr

  18. Kugr! Dropping by for your bi-yearly check in? ;)

    Ha Ha! :D

    Yup, I am pretty much a voyeur on this this site. I do enjoy your contributions though.

    I am not full time on LabVIEW programming but I do want to get a common framework that I can use on systems here. AQ's ActorFramework fit that bill for me with some enhancements on the derived Actor classes. For instance, my Actors have a name and know their receive queue - sometimes an actor will send itself a message. Actors also retain the queues of Observers. It seems the intent of the ActorFramework (especially for stability) was that an Actor that created another Actor was the only one that could communicate with that new Actor. AQ can correct me here but that was my take. There was nothing inherent in the framework that restricted this, it was just my understanding. I did not like that restriction and I generally allow a full network of messaging, though I do have the concept of retaining what Actors another created.

    The biggest change to AQ's framework was to make the Message:Do.vi re-entrant. Within an actor, the queue will keep processing to one message at a time. I was OK to have all actors processing messages in parallel though this does make debugging crazy at times. And I just added queue names to make my debugging a bit easier - now I can see the name of the actor who sent the message. Oh, yes, all of my messages allow the sender to add it's reply queue. Generally the Do.vi only gets the creator's queue, but sometimes I want to reply directly back. This is an added property in my derived message.

    I have added an ActorFacade class that can be derived to hide the nuances of all of the messages. A message is essentially wrapped in a method of an ActorFacade. The ActorFacade is not an actor though and cannot receive messages. It is usually contained within an Observer. The ActorFacade actually becomes very useful in updating UI controls via CtlRefnums. So it is a bit more than just a Facade with respect to a design pattern, but I am not sure what to call it.

    I also have ManagerActor (creates new actors via a message), a UIActor (an easy way to put a user interface on an actor), and a PollingActor (for those times when I need to watch for something to change that does not generate events).

    From there the derivations continue to my specific requirements. I deal with moving fluids so there are generally valves, pressures and temperatures to deal with. They boil down to analog and digital IO.

    Not sure this was very helpful but it is what I am up to.

    I will set the thread up shortly for Error Handling.

    -kugr

  19. First, I've ditched the rule of wrapping all sub-vi code in an error case structure. (Blasphemy! Burn me at the stake!) About 9 months ago AQ and I had a discussion about this...

    Hey Daklu,

    This thread has been great. I am starting to use AQ's Actor Framework with success on my systems. My derived classes add some features that probably break the proof of stability, but it is a risk that I accept. One of the latest things I did was to not propagate an error up into 'ActorCore.vi'. Once that happens, the Actor is dead.

    That is not why I am posting however. Your last two posts on Error handling, I think, deserve a thread of its own. Those coming into the top of this thread for the first time may never get to this gem of insight. I can start it if you want.

    -kugr

×
×
  • Create New...

Important Information

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