Jump to content

jon_mcbee

Members
  • Posts

    25
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by jon_mcbee

  1. I am using git submodules + some custom tooling as a package management system for reuse code and I have found myself wanting to remove VIs associated with a given project from the compiled object cache.  Anyone gone down this road and found anything useful?  I am expecting to need to take the next step and just start building my submodules into PPLs and depending on those, but since I am here I thought I would ask if anyone has had any fun experiences with manually manipulating the compiled object cache.

  2. 51 minutes ago, ShaunR said:

    Even by that definition, learning the API interface may be the cost in a larger Venn diagram but then the API *is* the functionality and code to support that interface is still the cost (code size, memory size, load times, execution times, compile times etc). The over-arching benefit for an API is simplification of complexity and complexity always has a cost. If you are lucky, the underlying complexity cost grows linearly as the API grows. If you are unlucky it is exponential. At some point it becomes unusable either because the underlying code is too complex to warrant the cost (e.g. labview build times for classes) or the underlying code is unmanageable/unmaintainable often with side effects (e.g. the "God" Class).

    So I still maintain that the API is a benefit (that being reducing interface complexity and also reducing the learning required to achieve a goal) and, the underlying code is the cost of that benefit ... even from the  consumers point of view. The ancillory benefits of an API are reuse and parallelism which can alleviate the consumers' project cost but are not guaranteed for any and all APIs and is dependent on the underlying code; usually by adding complexity (thread safety as an example).

    I think that we are saying pretty similar things.  The only reason you would ever chose to consume a package is that the API hides complexity in a way that simplifies your application.  If the cost of consuming the API is high then you probably will decide not to consume it.  If the cost of the implementation behind the API is high you definitely will decide not to consume it (because what is the point?).  That said I suppose I should update the slides to explicitly show that cost/benefit is a sliding scale, something with low cost probably has high benefit, and something with high cost probably has low benefit, and that is true for both the API and the functionality behind it.

  3. 44 minutes ago, drjdpowell said:

    How does MVA relate to your STREAM framework that you've blogged about? 

    So Stream is a mediator-ish message/data bus with transport abstraction, so two parts of the code can publish/subscribe to data/message by type and name and not be concerned with how the data/message moves.  MVA takes what Stream does and uses it to extend the Actor Framework, while also building in extension points for Views, View Management, Models, and a ViewModel (so MVVM as an extension of the AF with a built in message/data bus to help decouple Views from Models).  Over the past two and a half years we have only used MVA for project code, so it is under active development/maintenance while Stream is not and has not been used in project code.  I am working on ramping back up with the blogging, been too busy with business lately unfortunately, and MVA will be featured more prominently in the new blog entries.

  4. On 10/1/2019 at 6:57 AM, ShaunR said:

    IMO. For the API he has the cost and benefits reversed. The interface is the benefit. The hidden functionality to achieve the interface is the cost.

    So what I was going for was that the API has a cost associated with learning and using it as a consumer of the component, while the functionality encapsulated within the component is the benefit that you get when you pay the cost to consume the API.  As a consumer of the component you don't pay a cost for the functionality hidden behind the API, I suppose that if you find yourself paying a cost for the functionality hidden behind the component you would probably stop using the component because it isn't adding any value.

  5. As Michael mentioned above we (Composed Systems) primarily use the MVA Framework (which is an extension of the Actor Framework).  One note is that MVA is our separation of concerns focused framework that we use for decoupling of UI and Business Logic and the messaging between them, but we also use other frameworks that are not messaging frameworks for other aspects of development.  After a few years of building up our tool chain we have MVA for messaging, a sequencing framework (Test Executive), and an event logging framework.  We use each of these frameworks in each of our projects and extend each for application specific needs.  

    I had lunch with a customer last week that we have been working with for coming up on two years, and he was saying that from his point of view he doesn't program in LabVIEW anymore, he just uses our tools (frameworks).  I think this is great, I'd be curious if other people agree or are horrified by it.

  6. I dont know if this will help you or not, but would love to get feedback from you on its usefulness.  I have attached an example project that compares a very simple piece of code written with a QMH, written with an LVOOP approach, and written with the Actor Framework.  I used this as a demo at a recent CLA/CLD summit.  It is intended to be an apples to apples to apples comparison for someone who is looking to learn LVOOP/Actor Framework.  It was originally posted on the NI Community Forums, but I apparently cant link to the page from LAVA(?) (Thanks Todd).

     

     

    EDIT: Replaced attached files with link to files on the NI Community Forums so that I only have to maintain one set of files: https://decibel.ni.com/content/docs/DOC-32600

     

     

  7. Is it possible to call the oldest ancestors implementation of a dynamic dispatch VI?  

     

    Lets say that I have an inheritance hierarchy where the oldest ancestor is called DUT and has three abstract dynamic dispatch methods (to be overridden and not extended by children): Read Torque, Read Trip, Read Serial Number.  DUT has a child class called Mindbender3000, and Mindbender3000 overrides all of the parent dynamic dispatch methods: Read Torque, Read Trip, and Read Serial Number.  Somewhere down the road an upgrade is made to the Mindbender3000 product, and Mindbender5000 is born.  The upgrade incorporated two main improvements, a clock was added to the new hardware that we can now query using a Read Clock method, and the ability to Read Trip was removed from the device.

     

    To account for these changes, a new abstract dynamic dispatch method is added to the DUT class, Read Clock, and a child class of MindBender3000 is created, named Mindbender5000.  Mindbender5000 uses its parents implementation of the Read Torque, and Read Serial Number override methods, and overrides the DUT classes dynamic dispatch method for Read Clock.  Ideally, Mindbender5000 would use the DUT classes implementation of the Read Trip method, as it is abstract and doesn't really do anything.  However, because Mindbender 3000 has already overridden the Read Trip method, the Mindbender5000 product wants to use its implementation.

     

    Is there a way to call DUTs Read Trip dynamic dispatch method from the Mindbender5000 class?

     

    Lets assume that DUT has other children that need to be able to override these dynamic dispatch methods, including the new Read Clock method.

     

    Thanks!

  8. I see.  The Message parent class is abstract and its implementation of the "Execute Message" dynamic-dispatch method does nothing.  Message's children override (not extend) the "Execute Message".  An extra input is added to the "Execute Message" method for DUT class.  The DUT parent class has a dynamic-dispatch method for every child of the Message class.  The DUT dynamic-dispatch methods are embedded in their corresponding Message child override "Execute Message" method.

     

    The trick to making this work is that the DUT parent class must have an abstract dynamic-dispatch method for every child class of the Method Message class, and the corresponding DUT dynamic-dispatch method must be embedded into the "Execute Message" override method of each Message child class.

     

    Is there a name for this pattern?  Is this a pattern?  Or is this just common knowledge?

  9. I have a problem I am trying to solve using LVOOP, it seems like there should be an established way to solve it but I have been unable to think of/find anything that works.  Here is a description, I dont have any code mocked up that I can attach, but if it would be helpful I can put some together.  I am writing a test executive that will test multiple families of devices.  Each family has the same set of commands, but the commands may be implemented differently (don't have to be though).

     

    I have an abstract parent class called DUT, and have children for each device family.  I also have an abstract parent class called Message, with a child message class for each command in my command set.  This is where I am getting stuck.  All devices have the same messages, certain devices implement (structure and parse) certain messages differently.  It smells like I want to override based on both device type and individual message, but this is not possible.

     

    I am hoping that someone can point out either where I went wrong, or what the logical next step would be.  If more information is needed, please ask questions and I will do my best to answer.

     

    Thanks!

  10. I found the problem, it was a timing issue that had nothing do with how many subpanels I had running at once, i just had the same problem in each plugin.

    I am working on a GUI that is modeled off of this post by DFGray http://forums.ni.com...=526816#M466872 on the NI forums. I am using the same LVOOP structure to create plugins that are launched into subpanels. I have five subpanels on my GUI, each subpanel is a different size and functions are launched into the appropriate subpanel based on their minimum window size. The problem i am seeing is that a plugin launched into a subpanel runs much more slowly than a when it is run by itself, I thought I must have left highlight execution turned on in one of the subVI's. As a test I called one of the plugins, without the LVOOP using the Simple Subpanel shipping example and it loads just fine. This makes me wonder if the problem is either the LVOOP, which doesn't make sense to me as it has nothing to do with the VI once launched into a subpanel, or with having multiple subpanels on my GUI running at once. Any thoughts on this?

    Regards

  11. I am working on a GUI that is modeled off of this post by DFGray http://forums.ni.com/ni/board/message?board.id=170&message.id=466872&query.id=526816#M466872 on the NI forums. I am using the same LVOOP structure to create plugins that are launched into subpanels. I have five subpanels on my GUI, each subpanel is a different size and functions are launched into the appropriate subpanel based on their minimum window size. The problem i am seeing is that a plugin launched into a subpanel runs much more slowly than a when it is run by itself, I thought I must have left highlight execution turned on in one of the subVI's. As a test I called one of the plugins, without the LVOOP using the Simple Subpanel shipping example and it loads just fine. This makes me wonder if the problem is either the LVOOP, which doesn't make sense to me as it has nothing to do with the VI once launched into a subpanel, or with having multiple subpanels on my GUI running at once. Any thoughts on this?

    Regards

  12. You can use an event driven queued state machine (or better described as message handler). You will capture all events in the event structure, but instead of processing them there, you enqueue them as commands. You either can use the enqueue elements at opposite for priority events, or you use multiple queues for several priorities. The processing is handled inside the seperate consumer loop of that queue(s).

    Felix

    Thank you both for the response. I plan on using the queued message

    handler inside my modules, using dynamic events to pass commands

    from a controlling VI to the modules. I was hoping I could find a way to

    assign priority levels to these events, so i could broadcast an abort command

    to all modules registered at a higher priority. I think the solution will have to

    be that I have a seperate event struct only registered for a high priority event

    that can take control of the producer/consumer that drives the module.

    Regards

  13. Is there a way to get access to the queue that holds events that need to be handled by the event structure? I think that there can be multiple queues if the structure is registered for multiple events, but I assume that at some point they are all loaded onto a single queue for handling. I would like to be able to insert an event at the front of the queue in certain situations to ensure that it is handled immediately. All thoughts appreciated.

    Regards!

  14. In the thread that Tomi M started to demo the dynamic event feature he included a demo that let you drop square circles etc.

    Latter in that thread I followed-up and he posted a modified demo that showed how to do it in an exe.

    In a nutwacko.gif shell...

    You search for all LV classes that can be cast as the parent type without errors. The parents don't have to know about the children at compile time.

    Ben

    Hi Ben,

    Can you provide a link to the Tomi M thread? I looked for it but couldnt find it.

    Regards

  15. QUOTE (normandinf @ May 13 2009, 08:17 AM)

    It's part of the OpenG Application Control Tools. (see pic)

    As PJM mentioned, there are other ways to pass input data to your plugin VI. (including Queues, Events, LV2 globals, ...) But the way I describe below is quite simple and fast. If you build your plugins with standardized control names (as long as you don't change them in the future) you will get a good way to use your plugin but I'd add that it's a good way only if you plan to initialize values and don't change them from the outside anymore. In the screenshot, I simply spawn a VI that will gather error and system messages from all the VIs that run in my app and will concatenate and display in one location. Very simple but not the sharpest design for scalability.

    It looks like this is the same method used to launch daemons. I am thinking of using the plugin architecture as a way to distribute a main code base with a different set of sub VI's, the sub VI's being the plugins, to our customers. In the past we have modified our code base per a customers request and then shipped them the code, this leaves us with countless different versions of code to support, not to mention that we have been doing it for 15 years and the code base is getting difficult to manage because it so many pieces have been hacked in over time. We are now ready to rewrite the code base and I thought that the plugin architecture may help us to avoid recreating the same problem we are fixing with the current rewrite. It seems that by breaking the code into as many plugin classes as possible and creating a generic main architecture all we have to do is ship the main architecture with the correct set of plugins to customers. In an ideal world all custom software would be developed as plugins and we would never have to touch the main code again, keeping it clean, readable and using the plugins for maintainability and scalability. I am starting to get the feeling that one mistake at the this point in development can ruin everything, and the amount of forthought necessary seems daunting. So I want to be sure that I have considered all available options before I get going.

    It seems that other people must have gone down this road, assuming that what I want to do is possible. I would like to take it as far as being able to create a plugin to modify the execution of a state machine. It seems that a plugin could be created to add states to a state machine. But I am worried that what I want to do and what is possible aren't going to match up in the end.

  16. QUOTE (normandinf @ May 12 2009, 08:02 PM)

    And you can set input values using the OpenG tools before using the "Run VI" method. That's the way I use my plugin VIs.

    In my hunting around I had not come across using OpenG with the "Run VI" method as a way to implement the plugin architecture. Could you point me towards an example, I don't know which OpenG tools you are referring to. In fact, if anyone has any good resources for the plugin type of architecture (other posts, or KB articles...) I would love to take a look at them. I literally stumbled across this architecture and have been trying to fill in the gaps as I go, if there was one place that presented all I need to know about the plugin architecture I would be beside myself with joy. I appreciate all the feedback, and welcome more if anyone has any tips they think may be useful. In the meantime I will look into using the "Run VI" method with OpenG as another way to attack this problem.

    Regards

  17. I am trying to implement a plugin architecture and am starting to feel like I am missing something. I want to be able to drop a vi in a folder and incorporate it programmatically. To do this I have to use a strict type def to the plugin vi so that I can call it using a call by reference node. This seems to defeat the purpose of the plugin architecture because I have to know what the strictly type defined vi ref is in the main code. What I would like to do is to see a vi in the plugin directory, and be able to get the strictly type defined vi ref from the vi programmatically. I cannot figure out how to do this. What/where am I going wrong?

×
×
  • Create New...

Important Information

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