I have a class Vector2 (which contains a double "x", a double "y" and some methods), which is widely used by my game. At the moment some methods that use it accept/return a clone, and some a reference. This is confusing and inconsistent, so I want to change it. Now, however I don't know which system to choose:

- Make the class immutable and always pass a reference++ Good for memory-- Many new allocations if a vector needs to be changed every frame (because it can't be modified)

OR

- Keep the class mutable, but always make a clone when accepting/returning an instance of it++ It can be modified directly (for example, the position of an object which changes every frame-- Every copy takes memory, and clones need to be made every time it's passed to another method

Try both, profile the code and compare the results? I doubt there will be any big difference in performance. I would choose the one which produces cleaner code.

AFAIK, the JVM can optimize unnecessary defensive copies away, so using return new Vector2(v); might not allocate a new object if the returned object is not modified by the caller. Could somebody verify this assumption?

Not sure what you mean by 'and some a reference', everything is passed by value in java - even references...

Do you mean that some of your methods mutate their parameters, and others return a new object, leaving the paramters unchanged?

A common approach to this is to add an additional 'target' (output) parameter into which the results of the operation will be stored.This approach eliminates both the object creation overhead, and the mutating of method input parameters.

If getPosition() is going to return a reference to the encapsulatede member, then setPosition(...) must not re-assign the object to which said member refers.The above should be changed to something like:-

there are more problems in my current approach. for example:- getposition returns a reference so it can be modified directly (e.g. to move an object)- however, an unaware programmer might store the return value somewhere, then later modify it (not knowing that this is the original instance) and get inexplainable bugs

The most 'correct' way would be to make Vector2 immutable because it has value-type semantics - like String, Integer etc... As opposed to reference-type semantics like Player, Level etc.

This will impose some performance overhead, but then we do ok with String, Integers being immutable.

But you're not making 1,000's of string calculations per frame and for larger operations of concatenating strings you would instead use a string buffer! And what benefit is there to making a vector immutable? It is a type of object that is referred back to, so it's usage does not encourage immutability and instead encourages mutability.

I "solved" this problem by having Vector2f (etc) implement two interfaces, ReadableVector2f and WriteableVector2f. When I don't want people to think they can edit the vector directly I return a ReadableVector or pass a ReadableVector in and copy it into an existing Vector2f. I use this consistently throughout nearly all of my code.

The technique is not foolproof (a cast will thwart it) but it avoids cloning and avoids garbage, and so it's good and fast.

This will impose some performance overhead, but then we do ok with String, Integers being immutable.

Strings get special handling by the VM though (both from object pooling and operator overloads). Without them the overhead of your custom vector class is going to be larger, and the syntax to manipulate them is considerably more unweildy.

I use the same method as Cas, it might not be foolproof (especially if you hang on to an ImmutableVector2f for longer than expected) but it does a very good job of signally the intentional use. Bung in a simple copy c'tor to create a mutable version from an immutable vector and it's quite clean syntactically too.

I "solved" this problem by having Vector2f (etc) implement two interfaces, ReadableVector2f and WriteableVector2f. When I don't want people to think they can edit the vector directly I return a ReadableVector or pass a ReadableVector in and copy it into an existing Vector2f. I use this consistently throughout nearly all of my code.

The technique is not foolproof (a cast will thwart it) but it avoids cloning and avoids garbage, and so it's good and fast.

Cas

I used that too, but in comparison to immutable types I think it's still too mutable. It works fine for types you create and return (which shouldn't be changed by clients), but it doesn't free you completely from making defensive copies and it doesn't make those objects threadsafe.

I used that too, but in comparison to immutable types I think it's still too mutable. It works fine for types you create and return (which shouldn't be changed by clients), but it doesn't free you completely from making defensive copies and it doesn't make those objects threadsafe.

Correct. If you receive an object the interface semantics of which indicate immutability then that doesn't say anything about what could happen in reality. Which is why immutable types must be final.

There's certainly a case for either approach, but immutable objects are usually easier to live with and less problematic, whereas mutable objects are usually somewhat faster (and maybe a bit more convenient in some situations of limited scope).

A side note on value types in C#, they're probably kinda nice with regards to performance, but they're one reason why C# is quite a bit more complex to use than Java.

But you're not making 1,000's of string calculations per frame and for larger operations of concatenating strings you would instead use a string buffer! And what benefit is there to making a vector immutable? It is a type of object that is referred back to, so it's usage does not encourage immutability and instead encourages mutability.

The main benefit is robustness, particularly in a multithreaded environment.

Ultimately it's an OO *guideline* that classes with reference semantics should be immutable. There will be a performance penalty (particularly if there are more reads than writes, although if many more writes than reads, immutability can be faster because of less need of synchronization) and games are a perfomance sensitive domain, so it may be a good decision to make them mutable. Your choice.

The main benefit is robustness, particularly in a multithreaded environment.

Ultimately it's an OO *guideline* that classes with reference semantics should be immutable. There will be a performance penalty (particularly if there are more reads than writes, although if many more writes than reads, immutability can be faster because of less need of synchronization) and games are a perfomance sensitive domain, so it may be a good decision to make them mutable. Your choice.

thanks, D.

Well that's not entirely true since there are many cases where synchronization is not needed. One thing that many people tend to do is over synchronize ensure thread safety for things that will not be used in such a way where they will be of any concern. Bad design can make you enforce strategies in the wrong time, like overusing design patterns!

Just be careful not to give unclear advice, or misleading ones. Mutable structures have their uses and has served the professional gaming industry fine for years. Read "to mutate or not to mutate" by IBM. It is a programming approach, so whether it turns out to be the be all end all solution to data storage you must know why you are not using a mutable data structure.

Having said that I am involved in GBA programming so you tend to have to learn to work without many OO design practices in favour of something that can actually run in real time. I do design and prototype for readability and simplicity and only change the implementation when need be, but see patterns as tools and not parts of your body.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org