LAVA Forums Buy cool LAVA gear Forums RSS Feed

Welcome Guest ( Log In | Register )

Tags
This content has not been tagged yet

> Related links

Check out our OOP Code Repository Files or visit the LabVIEW Wiki OOP Portal.


3 Pages V   1 2 3 >  
Reply to this topic Start new topic
> Critical Analysis and Alternative Implementation of Object Oriented Programming in LV 8.20
Tomi Maila
post Aug 16 2006, 08:39 PM
Post #1


Drawing Tool - LVOOP example application
*****

Premium Member
Posts: 1154
Joined: 29-January 06
From: Helsinki
Member No.: 4014
Using LabVIEW Since:2004
LV:8.5.1 ,8.2.1 ,7.1.1
Finland Nothing Selected Nothing Selected My Blog


Hi all,

I've written a critical analysis on the implementation of object oriented programming in LabVIEW 8.20. In the same document I propose what I think is a better way to implement object oriented programming in LabVIEW. Check the document out. I'd like to hear your comments.

It has been discussed that LabVIEW Object Oriented Programming should be based on objects by reference. I strongly disagree the objects-by-referense should be the basis of the implementation. The reason is that objects-by-value are much more efficient and allows utilizing the concurrecny capabilities of LabVIEW. However I think that even though objects-by-value should be the basis of the implementation, there must be a way to create by-reference objects to refer to objects of the outside LabVIEW world like files and windows and data-acquisition devices etc. I also think that the leaving out constructors, copy-constructors and destructors was a very bad decission. I also cover some other issues, but have left out a few important issues like exceptions due to time limitations (I'm currently on vacation...)

Link to the document

p.s. I don't have a PDF version of the document available yet. My primary computer suffered from heat and this laptop doesn't have PDF conversion software installed. If anybody is ready to provide the PDF, please email it to me. The contact information can be found from the link above. Edit: I added a RTF for the moment for those who cannot read Word documents.

-jimi-

This post has been edited by jimi: Aug 16 2006, 09:42 PM

--------------------
Tomi Maila



Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
Ad
post Aug 16 2006, 08:39 PM
Post #















Tags
This content has not been tagged yet
Go to the top of the page
Quote Post
Jim Kring
post Aug 17 2006, 02:38 AM
Post #2


Changing the world, one VI at a time.
*****

Premium Member
Posts: 1649
Joined: 22-October 02
From: San Francisco, CA
Member No.: 17
Using LabVIEW Since:1995
LV:8.2.1 ,8.5 ,7.1.1
United States us_california Nothing Selected My Blog My Gallery


I have attached your document to this thread, so that it will always be available. It seems that this document likes to play hide and seek wink.gif
Attached File(s)
Attached File  Implementation_of_Object_Oriented_Programming_in_LabVIEW_v.1.2.doc ( 395K ) Number of downloads: 498
Attached File  Implementation_of_OOP_in_LabVIEW_V12.pdf ( 228.79K ) Number of downloads: 508
 

--------------------
-----------------------------------------------------------------------------------------------------
| Book | OpenG | LAVA | Champion | VIPM | Builder | Blog | JKI |
-----------------------------------------------------------------------------------------------------


Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
didierj
post Aug 17 2006, 09:30 AM
Post #3


Extremely Active
****

Member
Posts: 391
Joined: 6-February 04
From: switzerland
Member No.: 253
Using LabVIEW Since:1997
LV:7.1.1 ,6.1 ,.
Switzerland France Nothing Selected


Wow, nice work you have done. I like your ideas.

I haven't made my oppinion on which OO method suits my needs better: LabVOOP or the various GOOP's. There is one thing that bugged me since the first 10 minutes I glanced into LabVOOP: how do one access object data in parallel loops?

So far I have on suggestion on your proposal:
On page 21 (constructor block diagram) you define a class constant and then you invoke explicitly the constructor of the parent class. But you could also replace the class constant with the parent constructor. In all my implementations I did in Delphi the first command of a constructor is a "inherited create" (calling of parent constructor).

Didier


Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
bsvingen
post Aug 17 2006, 10:34 AM
Post #4


Very Active
***

Member
Posts: 162
Joined: 28-April 06
Member No.: 4885
Using LabVIEW Since:1994
LV:8.0.1 ,8.20 ,7.1.1
Norway nor_north_trondelag Nothing Selected


IMO the LV8.2 objects are just strict type defs with their own sets of wires that only VIs "belonging" to the wires can act on. Or in other words, some sort of protected clusters, since they only can be called by value. However, they also have inheretance and overriding. All in all, considering that they shall be used in a data flow setup, and be consistent with all the other existing types as well as the data flow paradigm, i think NI has done a good job.

In a data flow language there are no need for explicit constructors/destructors and copy methods, because all this is an implicit part of the language (or rather a non-existing part, because there are no variables in the normal sence of the word).

I think LV8.2 objects function exactly as they should. The main problem is that LabVIEW is a is graphical DATAFLOW language, and not the GENERAL graphical language that most of us would like that it should be. What it lacks most is an effective way to store data, and effective pointers and references.


Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
Tomi Maila
post Aug 17 2006, 10:49 AM
Post #5


Drawing Tool - LVOOP example application
*****

Premium Member
Posts: 1154
Joined: 29-January 06
From: Helsinki
Member No.: 4014
Using LabVIEW Since:2004
LV:8.5.1 ,8.2.1 ,7.1.1
Finland Nothing Selected Nothing Selected My Blog


QUOTE (bsvingen @ Aug 17 2006, 01:34 PM) *
In a data flow language there are no need for explicit constructors/destructors and copy methods, because all this is an implicit part of the language (or rather a non-existing part, because there are no variables in the normal sence of the word).


This is an argument I've seen number of times, that is dataflow implies lack of constructors, copy-constructors and destructors (or implicit memory only constructors). I fail to see why dataflow would imply no need of constructors or inability to implement constructors.

One can always allow no constant objects on a block diagram nor on front panel i.e. require that all objects are properly constructed using constructor call. When ever an object is placed on a block diagram, a constructor creating the object is actually placed instead. When ever an object is placed on a front panel as a control, also constructor is placed instead, so that instead of private data elements, constructor parameters are visible on the block diagram. These front panel objects would differ from the block diagram objects in a sense that when the VI is called as a subVI then constructor is not called.

That is when ever object buffer is created, it is created not only by reserving a block of memory and initializing this block to default values but instead reserving a block of memory and calling some code to do the initialization. I see no reason what so ever that in dataflow paradigm would not allow this.

--------------------
Tomi Maila



Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
bsvingen
post Aug 17 2006, 11:17 AM
Post #6


Very Active
***

Member
Posts: 162
Joined: 28-April 06
Member No.: 4885
Using LabVIEW Since:1994
LV:8.0.1 ,8.20 ,7.1.1
Norway nor_north_trondelag Nothing Selected


QUOTE (jimi @ Aug 17 2006, 12:49 PM) *
That is when ever object buffer is created, it is created not only by reserving a block of memory and initializing this block to default values but instead reserving a block of memory and calling some code to do the initialization. I see no reason what so ever that in dataflow paradigm would not allow this.

I don't think anything prevent you from doing this, either by normal programming or by using XControl at those places where you need such functionality. But the main point is that in dataflow "objects" are created when data for the "object" (controls) arrives, or at branches (copies) and then everything is 100% determined.


Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
Tomi Maila
post Aug 17 2006, 11:42 AM
Post #7


Drawing Tool - LVOOP example application
*****

Premium Member
Posts: 1154
Joined: 29-January 06
From: Helsinki
Member No.: 4014
Using LabVIEW Since:2004
LV:8.5.1 ,8.2.1 ,7.1.1
Finland Nothing Selected Nothing Selected My Blog


QUOTE (bsvingen @ Aug 17 2006, 02:17 PM) *
I don't think anything prevent you from doing this, either by normal programming or by using XControl at those places where you need such functionality. But the main point is that in dataflow "objects" are created when data for the "object" (controls) arrives, or at branches (copies) and then everything is 100% determined.


An "empty cluster" is always "100% determined" but the problem is that it just cannot represent the data I'd like it to represent (well it represents nothing). Similarily uninitialized objects don't necessarily represent anything meaningful unless initialized with class programmer defined code. The code could do tricks such use opening a file. An object representing a file that doesn't point to a file isn't really 100% determined to me.

What we need to do is that we need to distinguish between the class developer and the class user. The class developer is responsible to develop such a class that is hard to use inproperly by the class user. When we have no constructors, it is fairly easy for the class user to create an object of that class that is not properly initialized.

Custom class methods are not a solution. If the language doesn't force their call, the class user can always forget to call them. Even if the user remebers to call the class initialization method, problems arise. A child class cannot override parent class method interface. That is child class cannot use the same initialization method name if it requires more parameters or different parameters than the parent class. Think of a class hierachy of ten levels. All of the levels would have different name for the initialization function. Do you think that the user really remembers to always call the right initialization function. I bet users would call the wrong functions quite often.

Then think of the situation you want to change the implementation of your class. You need to do some initialization stuff to create proper objects of the class. Let's say you want to open a file to store very large arrays that don't otherwise fit into the memory. The problem arises since LabVIEW doesn't force the call of default constructor. All the code using the class needs to be properly modified to call the custom initialization method. It's very hard to do this since the code looks like ok, there are no broken wires because calling the initialization mehtod is volontery.

I could go on this list.... The fundamental thing however is that in object-oriented programming, the objects should ALWAYS represent a valid entity, there should be no uninitialized objects, not even transient uninitialized objects. All objects should be properly initialized on creation or on copying. LabVIEW doesn't guarantee this, or well it guarantees it only for in-memory objects that do not interact with the surrounding word. With surrounding word I mean files, other programs, screen, acquisition devices, network or anything that is not only present in LabVIEW internal memory.

--------------------
Tomi Maila



Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
bsvingen
post Aug 17 2006, 03:24 PM
Post #8


Very Active
***

Member
Posts: 162
Joined: 28-April 06
Member No.: 4885
Using LabVIEW Since:1994
LV:8.0.1 ,8.20 ,7.1.1
Norway nor_north_trondelag Nothing Selected


I still think you are pointing to a shortcoming that does not really exist in a call by value - data flow "world". The object may not neccesarily be pointing to a file, rather it would be the file itself or more precisely the data in that file. The file path or ref may only be a part (input) of the method "write data" or "read data". Still, in that data object there may very well be a control for the file ref or path, so that the cluster looks like:

[DATA]
[file ref]

The "initial" or default values would be empty data and "not a ref". IMO it would be just as strange to initialize the file ref to anything else than "not a ref" as it would be to initialize the data to anything else than empty data (all objects are always 100% determined since they are call by value).

Now, if you want something else, you just write a member VI that initiates the object with whatever values you want. There is no need to create the object in any form upfront, the VI inputs all kinds of non-object data and output the object itself. A "read data" or "set data" method may therefore be all the constructor you need. If you use by ref, you will have to create the *ref* before you can create the object. And since a ref without an object is totally meaningless you will be 100% sure that all refs points to valid objects, and therefore you need a constructor.

The only time i see that this may in some strange cases cause problems is if the object is created as a constant and used directly with no other considerations, but this would be the same as opening a call by ref object with default parameters on the constructor, or use an arbitrary floating point constant in calculations.


Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
Tomi Maila
post Aug 17 2006, 04:15 PM
Post #9


Drawing Tool - LVOOP example application
*****

Premium Member
Posts: 1154
Joined: 29-January 06
From: Helsinki
Member No.: 4014
Using LabVIEW Since:2004
LV:8.5.1 ,8.2.1 ,7.1.1
Finland Nothing Selected Nothing Selected My Blog


I strongly disagree with bsvingen. Consider for example a class representing an employee with fields with private data members name, age, sex, email, salary etc. I don't think that an initial LabVIEW object of this class can be considered an object representing an employee. No static initial values can represent a valid employee. What would we mean by a default employee. What would be his or her salary. Would default employee be male or female. This just doesn't make sense. That is and init method is needed to initialize an object of class employee to validly represent an employee, let's call this method Init.

Consider now that you derive a class executive from the class employee. In addition to employee data members, let's add an object representing option program the executive belongs to. Now to initialize the executive class object, we cannot use the name Init anymore, since the front panel layout of this method is fixed and cannot be changed. We need more information to initialize the executive object. We need to create a new initialization method and call it InitExec.

What happens if class user accidentally calls Init instead of InitExec when he creates a new instance of executive. According to LabVIEW valid instance of executive class is created and no error is generated. However the object is not correctly initialized, since the option program data member points to some default option program. This mistake is more than likely to happen, if there is not a common name for initialization method (i.e. a constructor).

NI emphasizes that it made the design decissions it made with LabVOOP so that LabVIEW would stay simple and intuitive to use. I simply cannot see how allowing class users to use inproperly initialized objects makes it clear and intuitive for the class users. Constructors don't complicate the class development at all, but it simplifies the life of the class user. The class user doesn't need to always check what is the proper way to initialize the class.

However, I also think that the by-reference objects are needed and in this sense the whole discussion about if constructors are needed only for by-value objects is pointless if by-reference objects will be implemented.

--------------------
Tomi Maila



Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
bsvingen
post Aug 17 2006, 09:32 PM
Post #10


Very Active
***

Member
Posts: 162
Joined: 28-April 06
Member No.: 4885
Using LabVIEW Since:1994
LV:8.0.1 ,8.20 ,7.1.1
Norway nor_north_trondelag Nothing Selected


As long as the connector pane is the same, we still can use the same init name for the init method for all inherited members. I see that it will be a rather irritating restriction to keep the connector panes equal, especially when theres alot of inherited functions, and you want to change one of them, but it will work (you will have to wire a correct object constant to the init function though, and therefore i don't think it is vise to initialize objects this way, but use the overriding mechanism for other tasks such as plug-ins for instance). Another option is to use the "to more specific class" in the more specific init functions (with specific names and without dynamic dispatch), that way you cannot use the wrong init function, even by accident due to different connector panes, and you don't need to wire the correct object into the function, and you allways get the correct object out.

But the main point still remains, you do not need to explicitly initiate objects in an "init" function when all objects are call by value and inside a data flow paradigm environment like LV. The objects will be initiated at first use no matter how you look at it, because they aren't really initiated in the correct sence of the word, they are only given values since they already exist in the VIs as controls or indicators just like any other LabVIEW types. You just make a VI that takes the input you need, and out pops the correct object.


Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
Tomi Maila
post Aug 17 2006, 09:45 PM
Post #11


Drawing Tool - LVOOP example application
*****

Premium Member
Posts: 1154
Joined: 29-January 06
From: Helsinki
Member No.: 4014
Using LabVIEW Since:2004
LV:8.5.1 ,8.2.1 ,7.1.1
Finland Nothing Selected Nothing Selected My Blog


QUOTE (bsvingen @ Aug 18 2006, 12:32 AM) *
The objects will be initiated at first use no matter how you look at it, because they aren't really initiated in the correct sence of the word, they are only given values since they already exist in the VIs as controls or indicators just like any other LabVIEW types. You just make a VI that takes the input you need, and out pops the correct object.


Ok. I agree with this. We just seem to define concepts "initialize" and "100% determined" in different way. Whereas I look the issue from the "object as a meaningful entity" point-of-view, you have a more pragmatic "valid dataflow object" perspective.

--------------------
Tomi Maila



Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
didierj
post Aug 18 2006, 06:20 AM
Post #12


Extremely Active
****

Member
Posts: 391
Joined: 6-February 04
From: switzerland
Member No.: 253
Using LabVIEW Since:1997
LV:7.1.1 ,6.1 ,.
Switzerland France Nothing Selected


I agree that if initialisation is needed depends on the concept. In LabVIEW (and where it doesn't go to the outside world) there is no initialisation method of any datatype. But from the moment the outer world is concerned also NI always uses sort of initialisation/clean-up (see file, daq, visa, ...).

OO programming is not only a way to put fancy boxes around parameters and methods, but a concept where one tries to encapsulate everything that belongs to an object.
Inheritance in OO programming is a way to generalize the access to an object, just like IVI. You define a standardized interface for every oscilloscope, but in the background you have child classes specialied for e.g. leCroy, HP,... There is (at least) 1 Method in your code that is of the lowest class of your hierarchy in your code, and this is the constructor (at some point in your code you must choose which oscilloscope you want to work with).

To my oppinion LabVOOP lacks two main features to be usable in the sense of OO programming:
1. overloading: same vi with different conepane. At the point where you define which sub-class you want to use, you must be able to have overloading, since the different sub-classes might need different parameters.
2. get a ref to the data: It makes it much more complicated to write a program in the producer/consumer concept whithout the ability to access your object (the 1 and only instance of the class) from parallel loops. Let me explain: When you have 2 parallel loops, one with event-structure for UI interaction, another with your own states to do the measurement. If you have your Instrument driver packed in a class and you can access your class by reference, you can easily wire the ref into the event-structure and call e.g. the instrument configuration panel by mouse click without interfering your measurement-loop. On the other hand, in LabVOOP one has to define a state in the measurment loop that calls the configuration panel (since branching the class creates a copy) and therefore it interfers into your measurement and you might loose/miss data.

In conclusion I came to the point that the actual LabVOOP is good more for beginner to have an entry point into OO (similar to express-vi's), but when doing bigger programs that have multiple parallel running tasks (like one I did recently with >1000 vi's and 4-8 parallel tasks) LabVOOP is too much restricted to be used as your program structure concept.

Didier


Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
bsvingen
post Aug 18 2006, 07:12 AM
Post #13


Very Active
***

Member
Posts: 162
Joined: 28-April 06
Member No.: 4885
Using LabVIEW Since:1994
LV:8.0.1 ,8.20 ,7.1.1
Norway nor_north_trondelag Nothing Selected


To be more correct, it is an explicit constructor that is not needed because the objects are already made in the VIs as controls or indicators (you still can have "init" functions, but they won't work as constructor functions in ordinary languages, they are just ordinary VIs to fill the object with data).

I disagree with your point that LVOOP is good for beginners. Students today are seldom teached FORTRAN, C/C++ or Pascal. They are teached JAVA and Matlab. When you start with JAVA, OOP is learned from the start (the way OOP is meant to work). Then when they start using Labview i think they will scratch their head more than once trying to figure out how this call by value objects are going to be used. Personally i can see that LVOOP will protect data and make programs more organized (that is also very much due to the project builder), but i still don't see how LVOOP will make the program structure better.


Tags
This content has not been tagged yet
Go to the top of the page
+Quote Post
Tomi Maila