LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Organizing class inheritance combinations

Hi, all.

 

My users want classes that correspond to physical measuring devices. This is fine so long as the device does one thing: temperature measuring devices all inherit "GetTemperature.vi" from the parent "Thermometer" class, and same with pressure measuring devices. But what happens when a device measures both temperature and pressure (and the four or five other things)?

 

So far I've been shoving all types of measurements into a single parent class, and any measurement that the child doesn't support gives a runtime error through overriding the "Get___.vi" methods that it doesn't support. Not only is that clumsy to program (most devices are single-measurement devices), but it relies on a runtime error for something that's known at compile time!

 

How are other people handling this sort of situation?

0 Kudos
Message 1 of 65
(3,740 Views)

 

Parent: Device Class

Child class 1: Thermometer

Child class 2: Pressure gauge

Child class 3: Thermometer + Pressure gauge

 

VI Get_Temperarure must be defined twice, for child class 1 and 3.

 

I don't see any simpler solution.

Maybe you'd need multiple inheritance, but it's not handled by labview and probably never will.

 

Any other idea?

 

Marco

 

 

0 Kudos
Message 2 of 65
(3,715 Views)

As they say, down that road is madness 🙂

 

There are probably five or six measurement types: temperature, pressure, gas flow, voltage, current. Off the top of my head, I can think of nine different classes that would be needed for combinations of these measurements.

 

But the worst part is that the benefits of superclassing is lost: once my meter is of class temp+pressure it can no longer be in an array of temp objects or inherit code from either temp or pressure.

0 Kudos
Message 3 of 65
(3,708 Views)

You can have a class that have different classes as its private data. This is what you typically do when your class system does not allow for multiple inheritance.

 

Class Container

Data

    a <- Temperature

    b <- Pressure

 

Etc.

0 Kudos
Message 4 of 65
(3,694 Views)

Aggregation will be your friend in this case, as Joseph_Loo talks about, since multiple inheritance is not permitted. In this case, if your device is called "Molly", you can create a temperature measurement class called TempMolly and a pressure measurement class called PressMolly. Both of these will have an object "RealMolly" in their attributes (aggregation). RealMolly will represent the actual device while Temp and PressMolly will represent the measurements.

 

Now, RealMolly would ideally be the same object shared between TempMolly and PressMolly, hence this would need to a referenced object. There are a couple of techniques for this available. Alternatively you need to make sure that the data needed for RealMolly is shared between two standard ByValue objects.

 

When it comes to your Get____.vi, if your users only use the top level device class I would suggest that you implement the error generation in this class and leave the implementation out in those classes that don't have any implementation for the method. If an object then is called with a method it hasn't implemented the device class will generate the error (e.g. "call to abstract method"). 

 

There are more elaborate patterns for these cases as I'm sure you are aware of, but this could be a good starting point for your users.



CLA
www.dvel.se
0 Kudos
Message 5 of 65
(3,684 Views)

Thanks for the suggestions, guys, but so far none of these really fit the needs.

 

The container class pattern prevents both the bookkeeping of inheritance and the functionality of dynamic dispatch, while the "share object between classes" pattern prevents dynamic dispatch, requires a lot more programming, and lets users commit what should be compile-time erros.

 

Right, LabVIEW does not and will not have multiple inheritance. Fine, but what is the National Instrument alternative?

0 Kudos
Message 6 of 65
(3,675 Views)

If I understand you correctly your users want one class per instrument, but are using the top "device" class for all interaction with these instruments, which leads to the possibility of calling e.g. "GetPressure.vi" on a temperature device, resulting in a runtime error. If this is the case, and you want to continue with the "a class is an instrument" paradigm, the use of the "device" class is the problem. If you could make your users use the classes "Thermometer" and "PressureSensor" instead you would be able to get edit time errors instead, while using the "device" class for methods and attributes that exist for all device classes.

 

Now this doesn't address your issue with the device of many measurements where you would need the multiple inheritance. In this case, the device does not fit in the design pattern of one class per instrument, so something needs to be done. NI:s alternative to multiple inheritance would be the same as for e.g. Java, it's a matter of how you design your application. If you or your users don't want to change the design you'll either have to live with the shortcomings of it and create a new family of devices, use a shoehorn to come up with a solution like using aggregation in this particular case, or refactor to a design that addresses this problem from the start. 



CLA
www.dvel.se
0 Kudos
Message 7 of 65
(3,644 Views)

Hi!

 

Interfaces could be a useful tool to achieve your goal.

(So we'd better Kudos this idea: http://forums.ni.com/t5/LabVIEW-Idea-Exchange/LVOOP-Interfaces/idi-p/960890)

 

 

 

 

Marco

 

0 Kudos
Message 8 of 65
(3,632 Views)

M_Peeker, I'd take exception to the suggestion that our paradigm is the problem here. The customer is always right! 🙂

 

Right, my users have specified that it must be one object per device. They aren't LabVIEW experts, and "you call call the same GetTemperature.vi on any temperature object" is about as far down the road they'll go since they see that as neat enough to ignore the confusion of how it actually works. Any design that involves multiple objects on the screen for a single physical device brings the confusion back (and gets me yelled at).

 

I see other forum threads and articles from NI saying multiple inheritance isn't needed because anything that requires it can be done in other ways. So, I was hoping I was missing something.

 

So it looks like here's an example of where LabVIEW is coming up short for not providing that functionality.

0 Kudos
Message 9 of 65
(3,607 Views)

@crcarlin wrote:

M_Peeker, I'd take exception to the suggestion that our paradigm is the problem here. The customer is always right! 🙂

 

Right, my users have specified that it must be one object per device. They aren't LabVIEW experts, and "you call call the same GetTemperature.vi on any temperature object" is about as far down the road they'll go since they see that as neat enough to ignore the confusion of how it actually works. Any design that involves multiple objects on the screen for a single physical device brings the confusion back (and gets me yelled at).

 


This statement may not be liked, but I disagree...the customer is not always right. You say it yourself, they aren't LabVIEW experts; they have hired you to be that. Why are they limiting your architecture? Why do they care about how your classes are defined? Normally the user is just concerned with functionality and what the UI looks like, but not how you get that functionality. You may find that having a candid discussion with them proves beneficial. I know this doesn't directly answer your question, but it is definitely something to consider. I often find customers can be very understanding if you can be confident and convince them that you are making the right decision. 

 

My initial thought is you are not differentiating between a device, and the measurement it takes. I think you need a device class, and a measurement class. Each device holds in its private data the different types of measurements that it can take. This doesn't give you an explicit, detailed answer but is this more in line what you are looking for?

 

I will also say sometimes we get so caught up in dynamic dispatching that we try and force it where it may not be the best choice. It seems great: you have all these measurements you need to take, just loop through them and call dynamic dispatching on each one...but when you start getting empty methods in parent classes just so a few children can DD them while other classes do nothing it can be a code smell that you are forcing something. Just something to consider, I'm not saying it's the case here.

0 Kudos
Message 10 of 65
(3,583 Views)