LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Adding new LVOOP class methods without modifying the original class


@Mikejj wrote:

Hi Everyone,

 

Thanks for all the suggestions. My question at this point is how do I still make dynamic dispatch at runtime work with these solutions. For example, if I pick USB for DUT_Interface, my DUT_Interface factory will load the USB class into memory...is there anyway to then take this USB DUT_Interface class and have it dynamic dispatch something in my logging class (whether as an intermediate class or an interface class) to find the right concrete logging class (USB_logging, Serial_logging, etc).

 

This is what I was trying to do with my solution 2, I basically 

test.png

 

With the solutions y'all have given, it seems like I will still have to play setting up the factory a second time to get dispatching to work.


No. Dynamic dispatch should still work just fine. Just take the output of your factory and decorate it with the Logging decorator. 

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 11 of 16
(442 Views)

@Taggart wrote:

Lookup the GOF Decorator pattern. It will do exactly what you want.

 

Create a new child class that is logging enabled. Have it own an object of the parent type.

 

For each method call have it delegate to the owned object and before (or after) calling the parent node, have it log whatever you need to log.

 

Edited to add:

I didn't read down far enough to see that Shane had already suggested the decorator pattern. Great minds think alike.


You could consider adding the decorator to the parent. That way, all children will be logging enabled. The logging can have a 'virtual' parent that doesn't do anything.

 

If the delegate is added to the parent, all children must use "call parent".

 

If it isn't added to the parent, all children with logging get duplicate code to call the delegate.

 

Another option is to make the class use the logging (as an input to the methods requiring logging). That would require modifying the parent. But there will be slightly looser coupling.

0 Kudos
Message 12 of 16
(432 Views)

wiebe@CARYA wrote:

@Taggart wrote:

Lookup the GOF Decorator pattern. It will do exactly what you want.

 

Create a new child class that is logging enabled. Have it own an object of the parent type.

 

For each method call have it delegate to the owned object and before (or after) calling the parent node, have it log whatever you need to log.

 

Edited to add:

I didn't read down far enough to see that Shane had already suggested the decorator pattern. Great minds think alike.


You could consider adding the decorator to the parent. That way, all children will be logging enabled. The logging can have a 'virtual' parent that doesn't do anything.

 

If the delegate is added to the parent, all children must use "call parent".

 

If it isn't added to the parent, all children with logging get duplicate code to call the delegate.

 

Another option is to make the class use the logging (as an input to the methods requiring logging). That would require modifying the parent. But there will be slightly looser coupling.


I don't understand this post. I'm sure it's sound, but I can't follow.

 

In the typical DEcorator pattern, the decorator is a child of the parent but has a parent as data, similar to the "composite pattern". This way, the decorator and parent can be used interchangeably. If you put the parent in a decorator, you just added logging. If you then put THAT decorator in another decorator which encrypts the file, you now have encrypted logging. They can be stacked, added serially. This is because the decorator is a child of the actual parent you're looking to decorate. It's like layers, like onions as Shrek says. Or Parfait. Everyone loves Parfait.

 

A decorator class CONTAIN a parent class, not BE the parent class. It supports the methods, but does not actually do the work. It can help to think of an abstrace "parent" which exposes the connector panes, but contains no methods. Then one child is the "parent" we refer to in the text, but this change of course requires an adaptation of the original code.

 

Otherwise we can simply ignore the parent data internal to the decorator and offload everything to the data field contained within. By doing this, the "parent" data contained within the decorator (via composition, not inheretance) we can mix and stack decorators.

0 Kudos
Message 13 of 16
(420 Views)

@Intaris wrote:

wiebe@CARYA wrote:

@Taggart wrote:

Lookup the GOF Decorator pattern. It will do exactly what you want.

 

Create a new child class that is logging enabled. Have it own an object of the parent type.

 

For each method call have it delegate to the owned object and before (or after) calling the parent node, have it log whatever you need to log.

 

Edited to add:

I didn't read down far enough to see that Shane had already suggested the decorator pattern. Great minds think alike.


You could consider adding the decorator to the parent. That way, all children will be logging enabled. The logging can have a 'virtual' parent that doesn't do anything.

 

If the delegate is added to the parent, all children must use "call parent".

 

If it isn't added to the parent, all children with logging get duplicate code to call the delegate.

 

Another option is to make the class use the logging (as an input to the methods requiring logging). That would require modifying the parent. But there will be slightly looser coupling.


I don't understand this post. I'm sure it's sound, but I can't follow.

 

In the typical DEcorator pattern, the decorator is a child of the parent but has a parent as data, similar to the "composite pattern". This way, the decorator and parent can be used interchangeably. If you put the parent in a decorator, you just added logging. If you then put THAT decorator in another decorator which encrypts the file, you now have encrypted logging. They can be stacked, added serially. This is because the decorator is a child of the actual parent you're looking to decorate. It's like layers, like onions as Shrek says. Or Parfait. Everyone loves Parfait.

 

A decorator class CONTAIN a parent class, not BE the parent class. It supports the methods, but does not actually do the work. It can help to think of an abstrace "parent" which exposes the connector panes, but contains no methods. Then one child is the "parent" we refer to in the text, but this change of course requires an adaptation of the original code.

 

Otherwise we can simply ignore the parent data internal to the decorator and offload everything to the data field contained within. By doing this, the "parent" data contained within the decorator (via composition, not inheretance) we can mix and stack decorators.


It seems I've got confused about that one.

 

But with a decorator, you indeed don't have to change the parent, but you still need to change the code using the parent, if you want to benefit from the added methods, right?

 

I mean, the decorator can be used as a parent, but the parent won't magically act like the decorator. For existing methods the decorator could act like the parent, but to use the methods added to the decorator, you'd have to use the decorator.

 

EDIT: Seems like you mentioned that (Then one child is the "parent" we refer to in the text, but this change of course requires an adaptation of the original code.) Off day I guess.

 

I still wander why OP doesn't want to touch the parent.

0 Kudos
Message 14 of 16
(415 Views)

Hello All,

 

Thanks again for the updates.

 

@wiebe. Main reason I don't want to touch the parent is because in my cases, I find logging to not be a core function of the parent. Not all projects or DUT's require logging, but they all need init, query, and close. My though was logging should be something the user implements with the core functions of the parent.

0 Kudos
Message 15 of 16
(391 Views)

@Mikejj wrote:

@wiebe. Main reason I don't want to touch the parent is because in my cases, I find logging to not be a core function of the parent. Not all projects or DUT's require logging, but they all need init, query, and close. My though was logging should be something the user implements with the core functions of the parent.


I agree that the logging doesn't belong in a DAQ class. That definitely seems to defy the single responsibility principle.

 

However, there's a range of options between changing the parent to facilitate logging (in whatever way), and adding logging to the parent.

 

A very, very pragmatic solution would be to simply add the logging every where you use the DAQ class. I mean, don't add logging to the DAQ at all... Simply make a ILogging.lvclass parent and a Logging.lvclass, Then DAQ and logging are two completely separate things.

 

The DAQ classes that could get a Get Logging method, that return the ILogging.lvclass or the Logging.lvclass at initialization, or a simple Boolean, to specify which logging they want.

 

Optionally, give each DAQ method a logging string (or if you really want to fancy things up, a logging message.lvclass). This means DAQ has as little as possible coupling with the logging, but can still control what's logged.

 

A slight variation is to also use a logging method after the DAQ, and make some DAQ methods return a log message, while others return a void log message. 

0 Kudos
Message 16 of 16
(382 Views)