tags:

views:

247

answers:

11

I have an object that I'm passing in a method call. Say I'm using a language that only allows you to pass objects by reference, like Java or PHP. If the method makes changes to the object, it will affect the caller. I don't want this to happen. So it seems like I need to make a copy of the object.

My question is: whose responsibility is it to clone the object? The caller, before it calls the method? Or the callee, before it changes the object?

EDIT: Just to clarify, I want this to be part of the contract of this method -- that it never modifies the original object. So it seems like it should be up to the method to make the copy. But then the caller has no protection from a method that doesn't do this properly. I guess that's acceptable -- the only other alternative seems to be to have this built into the language.

A: 

Depends, is there any reason that the method could be called in the future where you want the change to be seen by the caller? If so then the caller should make the copy. Otherwise the callee should make it. I would say that the second case is probably more common.

tloach
+3  A: 

Generally, the caller should make the copy if it is concerned about changes. If the caller doesn't care, the method should make the copy if it needs to do something that it knows shouldn't persist.

Joe Skora
A: 

If you have the caller clone the object, it gives you the flexibility to not use a copy (by not cloning it first), and also means you don't have to return a new object, you can just operate on the reference passed in.

Greg
A: 

My first reaction would be that it is the caller's responsibility, but I think it actually depends.

It depends on the contract defined between the two methods. The method that is making changes should explicitly identify that fact and let the caller make the decision. OR, The method that is making the changes should explicitly identify that it will NOT make any changes to the passed object and then it would be responsible for making the copy.

Scott W
+1  A: 

The caller. Because, sometimes you want to make changes to the objects themselves and other times to a copy.

Although, I consider it a bad practice for callee to modify passed objects (at least in object oriented languages). This can cause many unwanted side effects.

(after your) EDIT: In that case it is callee's responsibility to enforce the contract, so there are two options:

  • The callee simply does not modify the object
  • or the callee copies the object and works with the copy afterwards
Marko Dumic
This sounds right, that it's the callee's contract, and therefore it's responsibility. But then aren't we giving it too much power, and not encapsulating it? Now it can do damage outside of itself.
JW
If it fulfills the contract by ensuring no passed objects are modified then there are no side effects and no damage is done.
Marko Dumic
+1  A: 

So you want to do something like

MyObject m = new MyObject(); MyObject n = MyObjectProcessor.process(m);?

It seems simpler to me to do something like MyObject n = MyObjectProcessor.alter(m.clone());

where it's clear who's doing what to who. You could make the argument that the processor class function should be free of side effects, i.e. it should return a new object any time it's going to change state, but (AFAIK) that's not so consistently followed in OO as opposed to functional programming.

Something like the above is probably harmless, as long as it's clearly named and documented.

Steve B.
+1  A: 

We could look at ruby for guidance. They use a ! symbol to indicate that an object is modified in-place. So, salary.add(10000) returns a new object but salary.add!(10000) returns the original object but modified. You could use the same idea in Java or PHP by using a local naming convention.

David Medinets
A: 

I would say the callee: it simplifies calls and caller won't have to worry for the integrity of the given objects. It is the responsibility of the callee to preserve the integrity.

PhiLho
A: 

I assume you would have something like const declaration. This would be compiler enforced and would be more efficient than creating copies of your objects.

A: 

I think the caller should make the clone, just to make the naming easier. You can name your method Foo() instead of CloneBarAndFooClone().

Compare:

void RemoveZeroDollarPayments(Order order)

vs.

Order CloneOrderAndRemoveZeroDollarPaymentsFromClone(Order order)
Jeffrey L Whitledge
A: 

If not changing the object is part of the method contract, the only possibility is having the copy made inside the method. Otherwise you are lying to your client.

The fact that you actually need to modify an object exactly like the one given to you is just an implementation detail that should not put a burden on the caller. In fact, he does not even need to have visibility of that.

Gorpik