09-13-2018 11:16 PM
Hi, I was wondering if anyone has ideas about the following.
My team has created several extensions to actor framework that inherit from the base actor class. For example, we have a logging extension that overrides the handle error VI and sends a log message. Another extension is a config manager actor that adds some messages and overrides the pre launch init VI to initialize the configuration. Each library is separate and individually inherits from the base actor class.
Now my problem is that I have a project where I want the capabilities of both extensions in my actor. I can't inherit from both, only one or the other. Only a couple ways I can think to do this.
1. Change the inheritance chain so that the config manager actor inherits from the logger actor, which inherits from the base actor. This seems bad because now my config manager has a dependency on the logger actor, which it doesn't actually need. And maybe I don't need the logger actor in a different project. Plus if I have more extensions my inheritance chain is going to be full of stuff I don't need.
2. Include both the logger actor and config actor classes in the private data of my actor. In VIs that each extension overrides, create a new override VI and manually call the extension VI. This seems bad since it creates a lot of extra plumbing and complexity. Plus I would need someway to forward messages to extension actor objects (maybe call each extension actor core from my actor's core).
Is there a better way that I'm not considering?
Solved! Go to Solution.
09-14-2018 01:09 AM
Consider using composition instead of inheritance.
09-14-2018 08:22 AM
@Taggart wrote:
Consider using composition instead of inheritance.
Sure, but that's what his Option #2 is about ...
To properly resolve this issue we need Traits in LabVIEW. We started discussing Traits at the CLA Summit yesterday. Perhaps would continue discussing today as well ...
09-14-2018 08:53 AM
09-14-2018 11:46 AM
on second thought here is a suggestion using inheritance:
Make a parent class that all your classes inherit from called Base Actor (except for the logger)
Make a logger actor. You just send it a message with a string and it logs it.
Then have all your other actors inherit from the Base Actor. Base Actor contains an enqueuer for the logger (NOT the actor itself) in its private data. Do your override to log all errors in this class as well. Just pass whatever you want to log by sending a message. Also give it a method which sends a string to the logger to log. Make it protected so any children of Base Actor can easily log and you don't expose the enqueuer to the logger, so noone can stop it or send it extraneous messages.
Then have your root actor launch the logger first (it can also be a child of Base Actor and store the enqueur in its own private data) and pass the enqueuer to each of your Actors before they get launched (ie. give Base Actor a method to set the Logger Enqueuer)
For configuring actors, I recommend putting all your config information in a file. Have a configure method in Base Actor that takes in a file path. Pass each actor the file before you launch it. Then each class in your heirarchy pulls whatever it needs out of the file.
You do run the risk that not every actor needs configured, and not every actor has something to log, but I think most do. So it does add a little bloat.
09-14-2018 11:48 AM
@Dmitry wrote:
@Taggart wrote:
Consider using composition instead of inheritance.
Sure, but that's what his Option #2 is about ...
To properly resolve this issue we need Traits in LabVIEW. We started discussing Traits at the CLA Summit yesterday. Perhaps would continue discussing today as well ...
To your point, yes traits would help.
to point 2 - I think you don't want to include the actor itself, but the enqueuer.
09-17-2018 03:16 AM
@mbremer wrote:
Hi, I was wondering if anyone has ideas about the following.
My team has created several extensions to actor framework that inherit from the base actor class. For example, we have a logging extension that overrides the handle error VI and sends a log message. Another extension is a config manager actor that adds some messages and overrides the pre launch init VI to initialize the configuration. Each library is separate and individually inherits from the base actor class.
Now my problem is that I have a project where I want the capabilities of both extensions in my actor. I can't inherit from both, only one or the other. Only a couple ways I can think to do this.
1. Change the inheritance chain so that the config manager actor inherits from the logger actor, which inherits from the base actor. This seems bad because now my config manager has a dependency on the logger actor, which it doesn't actually need. And maybe I don't need the logger actor in a different project. Plus if I have more extensions my inheritance chain is going to be full of stuff I don't need.
2. Include both the logger actor and config actor classes in the private data of my actor. In VIs that each extension overrides, create a new override VI and manually call the extension VI. This seems bad since it creates a lot of extra plumbing and complexity. Plus I would need someway to forward messages to extension actor objects (maybe call each extension actor core from my actor's core).
Is there a better way that I'm not considering?
In my opinion, inheritance should map always a “Is - a” relationship. For example: "Cat is an animal" is good. "Cat is a paw and a stomach and a fur" is bad. That's why I'm against the 1st option.
For 2nd option, I have created a small example. I have a child class inheriting from the father class. In addition, child should have properties of the mother. Because LV does not support multiple inheritance, one must use composition. That means to create a passive object of the mother class in the child class and some wrapper VIs for actions and member accessors. For a caller actor it should appears that it communicate with a child object. For this, I override the Receive Message.vi in the child class. There I check if a mother message arrives and call the corresponding child wrapper VI.
If Child action need some input parameters, downcast the message like in Do.vi and wire inputs with message data.
I may miss some complications, but at first glance that should work.
09-17-2018 01:06 PM
@p4keal In my opinion, inheritance should map always a “Is - a” relationship. For example: "Cat is an animal" is good. "Cat is a paw and a stomach and a fur" is bad. That's why I'm against the 1st option.
For 2nd option, I have created a small example. I have a child class inheriting from the father class. In addition, child should have properties of the mother. Because LV does not support multiple inheritance, one must use composition. That means to create a passive object of the mother class in the child class and some wrapper VIs for actions and member accessors. For a caller actor it should appears that it communicate with a child object. For this, I override the Receive Message.vi in the child class. There I check if a mother message arrives and call the corresponding child wrapper VI.
If Child action need some input parameters, downcast the message like in Do.vi and wire inputs with message data.
I may miss some complications, but at first glance that should work.
I think this solution makes the most sense, at least until (if?) traits or mixins are implemented in LabVIEW.
I wonder if it makes sense to create an AF extension class that inherits off the base actor and handles the composition plumbing for you. You would register a number of extension (passive) objects with the actor (add to object array), and it would handle calling the extension overrides for you (call override for each object in the array).
Another way to go would be to create extension classes and let the user place them in the appropriate locations (i.e. place "Log Error.vi" in the handle error override). Would be a lot of manual plumbing, but maybe you could use VI scripting to connect everything for you.
10-12-2018 08:26 AM - edited 10-12-2018 08:50 AM
Excuse me what is a trait or mixin?
Got it.
10-28-2021 09:30 AM - edited 10-28-2021 09:31 AM
I stumbled across my old post.... That's quite weird to check the class by its name in Receive Message.vi.
Meanwhile, I think there is a better way without having to override Receive Message.vi. We can use the new LV2020 feature interfaces. Define an interface for the class whose VIs should be called. Inherit the "child class" from the interface. Override the vis of the interface and call parent's vi inside. The updated example is attached.