08-24-2010 07:53 AM
Ben and Felix, your thoughts tie in pretty closely with what I was envisioning. I, too, have been considering what it would take to make LabVIEW into a language which could be programmed solely with objects. But that is drifting abit afield of the original intent of the post.
At the moment, I am struggling with whether or not I would like the file objects to be almost fully interchangeable or simply to have interchangeable elements. My current thinking is that I would like an interchangeable layer, so you could dynamically dispatch and seamlessly switch between file formats, and a format specific layer, which exposed all the intricacies of the format and would be relatively easy for someone familiar with the format to pick up. This would allow code to read and write multiple formats relatively easily, but would also allow power users to tweak to their heart's content.
Thoughts?
08-24-2010 08:06 AM
@DFGray wrote:
Ben and Felix, your thoughts tie in pretty closely with what I was envisioning. I, too, have been considering what it would take to make LabVIEW into a language which could be programmed solely with objects. But that is drifting abit afield of the original intent of the post.
At the moment, I am struggling with whether or not I would like the file objects to be almost fully interchangeable or simply to have interchangeable elements. My current thinking is that I would like an interchangeable layer, so you could dynamically dispatch and seamlessly switch between file formats, and a format specific layer, which exposed all the intricacies of the format and would be relatively easy for someone familiar with the format to pick up. This would allow code to read and write multiple formats relatively easily, but would also allow power users to tweak to their heart's content.
Thoughts?
You are reading my mind or we are all reading from the same text.
Can we safely say that methods like "Set Path" "Open" "Close" will be common to all of the Classes so we can implement them high in the hierarchy with over-rides methods implemented in the children to realize each variation?"
UML question (Felix?)
What is the name of the diagram that shows inheritance and the methods implemented at each level?
Ben
08-24-2010 08:46 AM
Ben, I was planning on starting from a data perspective. All files have a path and are either open or closed. Read-Only, Write-Only, etc. will be set on open. I was planning to use the HDF5 perspective of breaking data into scalars and n-dimensional arrays. Scalars also go by names such as metadata, attributes, etc. Each piece of data has a location or path in the file. So the basis function set would look something like:
Set Path
Open
Close
Flush
Set Array Path
Set Scalar Path
Get Array
Get Scalar
Set Array
Set Scalar
Set Data Map (for simple binary file formats, so that text path names could be associated with file locations)
With these, you can do just about anything, although the execution may not be optimal for some file types. The Set/Get data pairs would need multiple implementations for the various data types. I will be exploring this a bit more thoroughly on my next post, but welcome suggestions, especially since you have done something like this already.
08-24-2010 08:56 AM
@DFGray wrote:
Ben, I was planning on starting from a data perspective. All files have a path and are either open or closed. Read-Only, Write-Only, etc. will be set on open. I was planning to use the HDF5 perspective of breaking data into scalars and n-dimensional arrays. Scalars also go by names such as metadata, attributes, etc. Each piece of data has a location or path in the file. So the basis function set would look something like:
Set Path
Open
Close
Flush
Set Array Path
Set Scalar Path
Get Array
Get Scalar
Set Array
Set Scalar
Set Data Map (for simple binary file formats, so that text path names could be associated with file locations)
With these, you can do just about anything, although the execution may not be optimal for some file types. The Set/Get data pairs would need multiple implementations for the various data types. I will be exploring this a bit more thoroughly on my next post, but welcome suggestions, especially since you have done something like this already.
Good you posted something that exposes my ignorance.
Some of those methods do not appear to have meaning for a simple text file (like Notpad). If I wanted to enuse I did not have issues with those "extra" methods I have two choices (I think)
1) implement "place-holders" in the Parent that are "no-ops" for Parent and are NOT over-riden in teh child's implementation since they don't mean anything in that context.
2) Implement the "special" functions at a lower level in the hierachy and restrict the those methods to only that level of the hierachy or below.
e.g.
Get Scalar Array seems to be one of those that would not apply to text files but can apply to TDMS or a spreadsheet.
So what kind of thought process can be applied to decide between "placeholders" and other approaches.
I hope that made sense!
Ben
08-24-2010 09:29 AM
@Ben wrote:
Some of those methods do not appear to have meaning for a simple text file (like Notpad). If I wanted to enuse I did not have issues with those "extra" methods I have two choices (I think)
1) implement "place-holders" in the Parent that are "no-ops" for Parent and are NOT over-riden in teh child's implementation since they don't mean anything in that context.
2) Implement the "special" functions at a lower level in the hierachy and restrict the those methods to only that level of the hierachy or below.
I was planning on option 1, in the spirit of a template-like class for the parent. I would group simple text files into the same category as simple binary files. With a map, you can go anywhere, but getting that map may be difficult, since, unlike binary, text fields can and do vary in length for the same scalar data type. Text files are hard to do well.
You also got me thinking about another issue, one which plagues almost all of programming. Is a string a scalar or an array? Would you expect to save a string as an attribute? I would say yes. Would you expect to be able to store an array of strings - again yes. Which makes it a "scalar" in this data scheme.
Maybe we would be better off having the concept of a link data type. In this case, strings would be saved as a string (array of integers) and attributes which are strings would be saved as a link (scalar) pointing to the string (array). This makes saving arrays of strings efficient, but may cause other issues.
08-24-2010 09:37 AM
@DFGray wrote:
...I was planning on option 1, in the spirit of a template-like class for the parent. ...
I have used that approach but i felt "dirty" since implementing those methods in the parent is not driven by the domain requirements but are there only to get around the LVOOP implementaion that requires there be a common bridge between the calls of two child classes for dynamic dispatch to work correctly (e.g. If Childern A and B have methods "read data" and the parent does not, then my diagrams will not automatically adapt when I change fro Class A to B. Adding a Place-holder in parent allows that to work.
Is there a Design Patten that tells me that approach is OK?
Like I said, I'm learning as I go.
Ben
08-24-2010 09:58 AM
Is there a design pattern for that? I don't know. I am but a lowly physicist. But I will find out...
08-24-2010 10:39 AM
Part 1: uml soapbox (in reply to Ben)
The diagram is called Class Diagram.
In uml there is the ValueSpecification class with method booleanValue. Only the (grand)child LiteralBoolean is overriding this to return it's boolean value. As you might guess, stringValue, integerValue also exist. So this seems to be a valid design. I was already thinking about this 'pattern' before Damien published his method list.
Part 2: my model
I wouldn't make it all a single class. Having more than one base class will resolve some of the conflicts.
File Class
Basically all File Functions such as Open, Read, Write, Close, Delete
Attributes such as isReadOnly, FileExtension, ...
ReaderAndWriter Class (not the best name)
In the childs of this class is the format specific code.
Methods: Load, Save, GetRawData, GetMetaData, GetHeader, GetFooter, GetData
Data Class
The ReaderAndWriter objects will return Data Objects, this allows to already define the methods in the parent class. AudioReader will return an AudioData Object, MeasurementReader will return a MeasurementData Object, ...
Note that ReaderAndWriter class could have some protected(?) methods for the format conversion which are called by the public GetData method, instead of overriding the complete GetData method.
Felix
08-24-2010 10:42 AM
@f. Schubert wrote:
Part 1: uml soapbox (in reply to Ben)
The diagram is called Class Diagram.
In uml there is the ValueSpecification class with method booleanValue. Only the (grand)child LiteralBoolean is overriding this to return it's boolean value. As you might guess, stringValue, integerValue also exist. So this seems to be a valid design. I was already thinking about this 'pattern' before Damien published his method list.
Part 2: my model
I wouldn't make it all a single class. Having more than one base class will resolve some of the conflicts.
File Class
Basically all File Functions such as Open, Read, Write, Close, Delete
Attributes such as isReadOnly, FileExtension, ...
ReaderAndWriter Class (not the best name)
In the childs of this class is the format specific code.
Methods: Load, Save, GetRawData, GetMetaData, GetHeader, GetFooter, GetData
Data Class
The ReaderAndWriter objects will return Data Objects, this allows to already define the methods in the parent class. AudioReader will return an AudioData Object, MeasurementReader will return a MeasurementData Object, ...
Note that ReaderAndWriter class could have some protected(?) methods for the format conversion which are called by the public GetData method, instead of overriding the complete GetData method.
Felix
I can sense some synaps growing after reviewing that post. I will return to this latter.
Ben
08-24-2010 02:35 PM
From my OO programming expert (AristosQueue) - my questions in black, his answers in blue.
Is it valid to have overrideable functions in a parent class which are not required because they make no sense in some of the possible children types?
That would be bad design.
Or should I create further children which are still templates containing the extra functionality?
This is strongly preferred. As far as names, it's just further specialization of the parent class, no different than when the first child inherited from the parent.
Now, having said the above, let me point out that sometimes it is hard to split your hierarchy -- you have two functions, and three child classes, and you want function A on two of them and function B on a different pair of them. There's no way to create intermediate children with the right set of functions. This triggers the classic desire for multiple inheritance or interfaces, and LabVIEW doesn't have these features, so you may decide the poorer design (putting everything on the base class) is the best strategy.
Another option is a variant of the Delegate pattern. You add to the parent a "Get Extension" VI that returns an internal object that has more functionality than the parent itself. That generally ends up with some type testing though.
Felix, thanks for pushing me back down the multiple object path again. I had considered it, but not really thought about it much. Thanks for the feedback.