Jump to content

Dynamic Loading Classes using Interfaces, this year I'm finally doing it...


Recommended Posts

Okay, this is it, I'm really going to figure out how to dynamically load my instrument classes using a factory without carrying every specific instrument class in memory when compiled. I've tried and failed in the past but this time I'm going to spend however much time it takes to get it working.

Someone critique this architecture and tell me how far off base I am.

I have a base Hardware class that has must overrides to instantiate the communication to the instrument, configuration of the instrument by passing in a JSON strong of config arguments, and deconstruction of the instrument. 

I then have interfaces to represent generic instrument types, DMM, Switch, Digital Input, etc, that have overrides for their API. Then I have specific hardware that inherits the appropriate interface(s). A keithley DMM inherits DMM, an NI MIO device inherits DI, DO, AI, AO... 

I have a hardware manager class that acts as a factory,  instantiating the classes using a config file that I want to include a key inside of that points to the specific class on disk. The hardware manager is passed to operations that use the instruments and they interact with them by casting to the type of interface they want.

Heres some hurdles I'm having trouble conceptualizing. I have some applications that run in different labs but perform the same task with different hardware. For example, in one lab they use a Kiethley DMM with a built-in switch card, in others they use a Kiethley DMM and an NI Switch card. In the first case it's one instrument that inherits DMM and Switch, in the other it's two instruments. I guess I could have two config entries, one for DMM and one for Switch and have the factory compare addresses on instantiation and if it's already initiated communication on an address it just points to the first instance?

And the biggest question, if the above is workable, any tips on how to get from a case structure containing every possible specific hardware class to dynamically loading them disk without putting them all into some subVI somewhere to guarantee they're loaded in memory during compile time?

Link to comment

see here for how to load stuff dynamically

https://www.sasworkshops.com/ppl-plugins/

That solves part of your problem. The other half is about organizing your object heirarchy. The GOF can help here.

You can buy the original, but this is better. 

https://refactoring.guru/design-patterns/book

I would envision using an interface for switch and an interface for DMM.

the DMM with a switch would implement both. You would need some way to discover that or hardcode it into a config file or something.

Sorry if that is a little vague, but I could envision several different ways to do it. I'd probably just sit down with LV and iterate until I found something that works. And then sit and stew and make sure I didn't miss anything. I'd still be prepared to throw away version 1 in favor of version 2 because you are sure to miss something.

Good luck.

Link to comment
On 4/11/2022 at 5:00 PM, IpsoFacto said:

I have a base Hardware class that has must overrides to instantiate the communication to the instrument, configuration of the instrument by passing in a JSON strong of config arguments, and deconstruction of the instrument. 

Perhaps consider using separate Hardware Configuration classes instead of JSON strings. That way your Hardware classes are independent of the configuration storage format (which may change in the future). All of your Hardware Configuration classes could inherit from a base class that is then cast by each Hardware at runtime.

On 4/11/2022 at 5:00 PM, IpsoFacto said:

I then have interfaces to represent generic instrument types, DMM, Switch, Digital Input, etc, that have overrides for their API. Then I have specific hardware that inherits the appropriate interface(s). A keithley DMM inherits DMM, an NI MIO device inherits DI, DO, AI, AO... 

Sounds reasonable.

On 4/11/2022 at 5:00 PM, IpsoFacto said:

I have a hardware manager class that acts as a factory,  instantiating the classes using a config file that I want to include a key inside of that points to the specific class on disk. The hardware manager is passed to operations that use the instruments and they interact with them by casting to the type of interface they want.

From what you describe, it sounds more like a registry than a manager. Could you imagine using a Map instead?

Your hardware manager also has a lot of responsibilities.

First of all, it should not be responsible for creating classes. This should be responsibility of a factory (Hardware Factory). If you want to load classes on-demand, then the factory should be passes to the manager. Otherwise, the factory should create all classes once on startup and pass the instances to the manager.

It also sounds as if the Hardware Factory should receive the configuration data. In this case, the configuration data could be a separate class or a simple cluster. In either case, the factory should not be responsible for loading the data (for the same reason as for the Hardware above).

On 4/11/2022 at 5:00 PM, IpsoFacto said:

Heres some hurdles I'm having trouble conceptualizing. I have some applications that run in different labs but perform the same task with different hardware. For example, in one lab they use a Kiethley DMM with a built-in switch card, in others they use a Kiethley DMM and an NI Switch card. In the first case it's one instrument that inherits DMM and Switch, in the other it's two instruments. I guess I could have two config entries, one for DMM and one for Switch and have the factory compare addresses on instantiation and if it's already initiated communication on an address it just points to the first instance?

A proxy could be useful here (a class that forwards calls to another class). In this case, "Kiethley DMM with a built-in switch card" could be passed directly to one of your operations. In the the case of "Kiethley DMM and a NI switch card", however, a proxy could hold the specific hardware instances and forward all calls to the appropriate hardware.

On 4/11/2022 at 5:00 PM, IpsoFacto said:

And the biggest question, if the above is workable, any tips on how to get from a case structure containing every possible specific hardware class to dynamically loading them disk without putting them all into some subVI somewhere to guarantee they're loaded in memory during compile time?

You can load a class from disk and cast it to a specific type. See Factory pattern - LabVIEW Wiki for more details.

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