GregFreeman Posted April 3, 2020 Report Share Posted April 3, 2020 (edited) I have struggled with this for a long time, but haven't really come up with a solution. I actually found an old message I sent to AQ about 6 years ago (wow) which is related to this, but his response fell by the wayside and I want to revisit it. In that case, it was about dynamic events to reuse code that is part of a Dialog, much like Windows would use OnOK and OnCancel callbacks that were not coupled to a specific dialog, but instead took a dynamic reference to controls on the child dialog. Assume you have a parent class Base and a child class Child. Base has events A and B, Child has event C. You have dynamic dispatch VI's as event handlers in your Base class -- OnA and OnB. What I haven't figured out is, can I reuse OnA and OnB without having to register for Event A and Event B in the child class's event structure? It seems the general methodology would be to have your child class have an event structure, your parent class have a method called "RegisterForEvents" which returns a registration refnum for the A and B events, and then your child class register for these events in its own event structure. Inside the child's event structure, you would then drop the OnA and OnB methods in their respective event cases. Now assume you have Child1, Child2, and Child3, which all inherit from Base. They all have this duplicate registration code, duplicate event cases, and duplicate handler VIs dropped in those event cases. I would like to be able to pull that duplicate logic out. But the only way I can figure out to do that is to have a VI with an event structure in the Base class to encapsulate all the parent event logic, then another in the child class to encapsulate the child event handling. But, now I end up needing two event handling loops on a block diagram, and because classes are by value, I can't easily share state. Has anyone else battled with this problem? Hopefully this makes sense. I can draw up an example if needed. Edited April 3, 2020 by GregFreeman Quote Link to comment
LogMAN Posted April 4, 2020 Report Share Posted April 4, 2020 15 hours ago, GregFreeman said: What I haven't figured out is, can I reuse OnA and OnB without having to register for Event A and Event B in the child class's event structure? Yes you can. Have a dynamic dispatch EventHandler.vi that handles the events from Parent in Parent:EventHandler.vi and a Child:EventHandler.vi for every child. Use Call Parent Method in Child:EventHandler.vi parallel to the event loop of the child. Only the Stop event needs to be handled by each child. Here is an example I put together (saved for LabVIEW 2013): Reusable Events 13.0.zip Quote Link to comment
GregFreeman Posted April 4, 2020 Author Report Share Posted April 4, 2020 2 hours ago, LogMAN said: Yes you can. Have a dynamic dispatch EventHandler.vi that handles the events from Parent in Parent:EventHandler.vi and a Child:EventHandler.vi for every child. Use Call Parent Method in Child:EventHandler.vi parallel to the event loop of the child. Only the Stop event needs to be handled by each child. Here is an example I put together (saved for LabVIEW 2013): Reusable Events 13.0.zip Yes, this is the solution I keep wanting to land on except it doesn't cover the case where Event C wants to do something with parent state which is updated from an event. Using your example, assume event A is triggered and the string value becomes state that belongs to the parent. Now assume event C triggers writing that string to a file. The child event handler loop will not have access to the string that was updated in the parent event handler, since the wire was split. I am starting to think that I am trying to make what is more of a by-reference paradigm and fit it into a by value language, and the right solution if this is really needed is to use a by reference class. Quote Link to comment
LogMAN Posted April 4, 2020 Report Share Posted April 4, 2020 39 minutes ago, GregFreeman said: Yes, this is the solution I keep wanting to land on except it doesn't cover the case where Event C wants to do something with parent state which is updated from an event. Using your example, assume event A is triggered and the string value becomes state that belongs to the parent. Now assume event C triggers writing that string to a file. The child event handler loop will not have access to the string that was updated in the parent event handler, since the wire was split. I am starting to think that I am trying to make what is more of a by-reference paradigm and fit it into a by value language, and the right solution if this is really needed is to use a by reference class. Indeed, there is (to my knowledge) no way to achieve what you want with pure dataflow. You could put your string in a DVR and make it part of the parent state. As long as you keep the DVR contained inside the class, its behavior is well defined and can be documented. Of course, anyone who uses the class needs to be aware of the caveats. Quote Link to comment
Aristos Queue Posted April 5, 2020 Report Share Posted April 5, 2020 Actors in Actor Framework inherit from each other, and if the parent defines a message to be handled, then the children can handle that message. Put another way -- I built an entire framework to handle that exact problem. It doesn't use the Event Structure. The only solution I came up with that I liked that used the Event Structure was an entirely new conception of inheritance, a new fundamental type of VI, and a new editor. It not only solves the problem of event inheritance but also front panel inheritance. I have it all mocked up in PowerPoint to build someday (when LV NXG is mature enough). Quote Link to comment
Francois Normandin Posted April 5, 2020 Report Share Posted April 5, 2020 I don't think it differs from a traditional event-based architecture if one overwrites the Actor Core and adds a parallel loop, which is the equivalent of Gregory's problem statement. The child's Actor Core parallel loop will still need to interact with the parent, through a subscription (user event or message-based). I agree that Actor model solves this problem (AF or event-based): the way to avoid this registration duplication in each child is to refactor the application's architecture where the child does not provide a second parallel loop, but only implements a set of messages that extends the parent. I daresay that a child class that extends its parent, both by adding a parallel loop and by extending its API, is in conflict of the Single Responsibility Principle in that it has two reasons to change. If a second loop is needed, it could probably be handled through composition instead of inheritance. Quote Link to comment
Aristos Queue Posted April 5, 2020 Report Share Posted April 5, 2020 > If a second loop is needed, it could probably be handled through composition instead of inheritance. Agree in general. Composition can get complicated if that second loop needs to be a Timed Loop -- if the timed loop's operation sometimes needs to be reconfigured while it is running, messages may be needed that extend Actor's API, and avoiding that is just more complicated than I think is worth doing. It may be a technical conflict of SRP, but practicality does temper the principles sometimes. There may be additional cases. Quote Link to comment
GregFreeman Posted April 7, 2020 Author Report Share Posted April 7, 2020 (edited) On 4/4/2020 at 11:53 PM, Aristos Queue said: Actors in Actor Framework inherit from each other, and if the parent defines a message to be handled, then the children can handle that message. Put another way -- I built an entire framework to handle that exact problem. It doesn't use the Event Structure. The only solution I came up with that I liked that used the Event Structure was an entirely new conception of inheritance, a new fundamental type of VI, and a new editor. It not only solves the problem of event inheritance but also front panel inheritance. I have it all mocked up in PowerPoint to build someday (when LV NXG is mature enough). Sounds good. I have decided to just register for the events scoped to the parent, in the childrens' event structures. It does result in some duplicate event handling code between children, which I'd like to live in the parent, but it's not really that big a deal. I may refactor to use something more like the actor framework for this class, but I think with the minimal number of events I don't get a whole lot of lift from refactoring Edited April 7, 2020 by GregFreeman Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.