Jump to content

Reusable Events Between Parent and Child Classes


Recommended Posts

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 by GregFreeman
Link to comment
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

Link to comment
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.

Link to comment
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.

Link to comment

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).

Link to comment

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.

 

Link to comment

> 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.

Link to comment
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 by GregFreeman
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

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