Module Format Preference

BlitzMax Forums/BlitzMax Programming/Module Format Preference

Gabriel(Posted 2006) [#1]
Dodgy thread subject, I know, but I can't find a better way to describe it in brief. What I'd like to know is the following..

In a user module, a lot of the functions return custom types. However, the custom types are Blitz versions of C++ Structs, so they do not automatically hold the same field values. Clearly there's an overhead involved in transferring data back and forth between struct and type. So, which would you prefer?

1) Module automatically transfers data from Struct to Type when a Struct is returned or data in one is changed, and vice versa with data from Type to Struct.

Advantages: Seamless operation. Cleaner code.
Disadvantages : Could occasionally be transferring data unnecessarily. Will mean a lot more work for me ( Don't count this :P )

2) Module manually transfers data from Struct to Type. You get a set of functions to do it yourself.

Advantages : Absolutely no unnecessary calls.
Disadvantages : Your code is a lot longer with a lot of calls to keep passing data back and forth. A single function call might end up being 3 or 4 commands instead of one.

3) Module never transfers data from Struct to Type. BMax types contain no fields, but instead have getters and setters to set and retrieve the values directly to and from the C++ struct.

Advantages : Absolutely no unnecessary calls. Will be faster than option 2 when you onlu need to get or set one or two fields in a type.
Disadvantages : Your code is a lot longer with a lot of calls to keep passing data back and forth. A single function call might end up being 3 or 4 commands instead of one. Will be slower than option 2 when you need to get all fields at a time.


Cards on the table, I think option 1 is the best. I believe the speed difference between 1 and 2/3 is negligible and the convenience and increased readability of your code is well worth it. It does mean a lot more work for me, but if I'm going to do this, I want to do it right.

Be interested to hear your preferences though.


Dreamora(Posted 2006) [#2]
3) This definitely reminds me of how Eiffel works with its "you have to write classes to handle anything you want to include from outside sources so it can be handled typesafely by the GC

I think this is the way that will bring the most success but from experience I can say it is the way with the by far most work as well. But it will reward you with something that is totally under your control (which would not be the case when using structs and transfering data as BM is GC controlled and C / C++ isn't)


Gabriel(Posted 2006) [#3]
Actually 3) leaves me with very little work. 1) gives me much more to do than 3)

The thing I dislike about 3) is that if you retrieve the position of an object, you then get the overhead of three extra function calls to get the x,y, and z values. If you only need one of them, that's great, but if you need all three, that's 2 unnecessary calls every time.


Dreamora(Posted 2006) [#4]
Why?

You can use

GetPosition(x:float var, y:float var, z:float var)

and then read all 3 out and assign to x,y,z :-)

Still one call :-)


Gabriel(Posted 2006) [#5]
No you can't, because that's not what the module returns. As I said, the module returns a custom struct/type with multiple fields. So it might return a 3d vector type with x, y and z coordinates.

If I do #1, you can simply say

MyVec=GetPosition()
Debuglog MyVec.x
Debuglog MyVec.y
Debuglog MyVec.z

If I do #2, you'll have to do

MyVec=GetPosition()
MyVec.PopulateFromStruct()
Debuglog MyVec.x
Debuglog MyVec.y
Debuglog MyVec.z


If I do #3, you'll have to do

MyVec=GetPosition()
Debuglog MyVec.GetX()
Debuglog MyVec.GetY()
Debuglog MyVec.GetZ()

Which is three function calls, each of which calls the wrapped C++ function as well. So that's 6 calls instead of 2.

With method #1 you get 1 call and it's done for you, whether you need it or not. ( 99/100 you will need it ) abd you transfer all fields even if you only need 1 or 2.

With method #2 you get 2 calls, but you're transferring all fields even if you only need 1 or 2.


Dreamora(Posted 2006) [#6]
I thought of the module as a functionality wrapper to the C / C++ source which will return something that you can use within BM in a usefull way which makes much much more sense.

Didn't think you meant that it returns this stuff.

And still you could make a method GetCoordinates(x:int var, y:int var, z:int var)

->

MyVec = GetPosition()
local x:int, y:int, z:int
MyVec.GetCoordinates(x,y,z)
Debuglog x
debuglog y
debuglog z


Gabriel(Posted 2006) [#7]
It's an interface to a DLL which is not normally accessible from BlitzMax. The point of the exercise is to return the exact same thing you get if you use the DLL in any other language. If I change all the return values, existing code for the DLL is horribly broken and everyone has to learn my syntax instead of the engine's syntax. Besides, you need to be able to pass and return the vectors.

In the position example, suppose you want to Get the position vector, add another vector to it and then use it to set the position. That's gonna be a horrible mess in separate coordinates.

Yes, I could make a GetCoordinates method, but I'm not going to, because option number 2 already does exactly that, albeit with a slightly modified syntax and the ability to use all the included vector operations on the return value, like dot, length, and vector maths.

The module will be open source, so if anyone wanted a GetCoordinates method, they can write it themselves. I plan on writing my own functions when it's done too. I'm talking about the pure wrap of the DLL classes.