Value Objects Should Be Passed By Value

I've been reading the ValueObject discussions, and having problems. This talk is far enough out of my frame of reference, out of my mindset, that I have a great difficulty understanding what is being said, even though the code should make it clear. I look at the code, and it just radiates wrongness. (Uh, no, my CodeSmells aren't always among the five standard senses, when they are, they're frequently tactile.)

It seems to me that by ValueObject, you are referring to something that works like an integer. This, to me, means that you want PassByValue.

x = 2 + 3

doesn't change the value of 2 or 3. More importantly, it doesn't change the value of the number stored in x, but rather overwrites it.

This is, in my opinion, one of the biggest failings of many object oriented languages - integers, characters, and floats are all passed by value by default, while objects are either passed by reference or pointer. This happens because most object oriented languages don't internally define assignment. In C++, the programmer can explicitly define assignment, and get around this. In some languages, you can get around this by only assigning variables on creation, where these languages give you slightly better control of how the value is treated.

How does this fix things? Well, the prime example problem piece of code was to deal with points

class Point {

  public:
Point( int x, int y ): _x(x), _y(y) {}

int getX() const { return _x; } int getY() const { return _y; } void setX( int x ) { _x = x; } void setY( int y ) { _y = y; }

private: int _x; int _y; }

which is all just fine, until you use this in another class, and give that other class a getPoint routine, which returns a reference to this object. That's still not a problem, until you change that reference. If it passed back a value instead, that problem would go away.

A fix for that problem, ValueObjectsShouldBeImmutable, breaks the usefulness of retrieving the value. You can look at it, you can use it as is, but you can't do anything. They fix that by making a Mutable interface, but that Mutable interface still has the original problem. This, IMHO, fixes nothing, and creates a hard, pointy mess.

Another fix for that problem, ReturnNewObjectsFromAccessorMethods, creates a bulging, uncomfortable garbage collection problem, because it allocates new memory at virtually every access. This fixes the problem, while making very potential memory leaks.

In my opinion, PassByValue fixes that problem cleanly - you don't allocate new memory, unless you make a new variable. If you want to make a variable which only refers to the original, you should be able to do that. It avoids the SideEffect problem of passing by reference, it avoids the garbage collection of RNOFAM, it avoids the crystalizing effect of VOSBI. It takes more resources than pass by reference, but fewer than RNOFAM. More importantly to me, it works the way I'd expect. I ask for the value of X's point, I get the value of X's point.

Can someone tell me how I'm wrong? (I know I'm wrong, at least to some extent, because this looks very black & white to me, yet I know there are both greys and colors in the world.)

--EdGrimm

If you're confused because of the ValueObjectHypotheses page then I'd like to apologize. I started that page to fish for examples and to evolve some modelling principles for using ValueObject s.

Two points from the above:

1. A fix for that problem, ValueObjectsShouldBeImmutable, breaks the usefulness of retrieving the value. You can look at it, you can use it...

You decide early on when you model a class whether its a ReferenceObject or a ValueObject. If you never need to change the (logical) attributes of any instance of the class after construction, you are creating a ValueObject class - otherwise you are creating a ReferenceObject class. The ValueObject/ReferenceObject distinction is not about preventing certain other classes from changing its state - Facade or the InterfaceSegregationPrinciple would be more appropriate.

2. Another fix for that problem, ReturnNewObjectsFromAccessorMethods, creates a bulging, uncomfortable garbage collection problem...

But then the FlyweightPattern is ideally suited for pooling ValueObjects because the unique identity of each ValueObject is never tested in code.


One interesting thing about value objects. You'll often see them in models like this: | O | * ----> 1 | V |.Every one value can be associated with many objects by the association, but each object can only have one value associated with it by the association. You can see this sort of thing in MartinFowler's AnalysisPatterns book. Let's assume O is a person class and V is a date class. A person o can have a hire date v. Theoretically, if instances of V are immutable, there could be only one instance of, say, 4/1/97 in the system. That instance could be shared by reference across the whole system. The only reason this would work is because values are immutable.

The conceptual test goes: "if I change an X do I have another X or the same X changed?" Substitute date for X. What does it mean to change a date? One can never change 4/1/97. If you change it to 4/2/97 it is another date, not the same date changed. Think about the Cartesian plane. There is nothing in the world you can do to make point (3,4) turn into point (12,5). You can change a variable referring to a point, but never the point itself.

To me, immutability is part of valueness. Nicely, if you have immutability, you can pass values by reference or not and always be safe.

--MichaelFeathers


I use ValueObject a lot, and always pass them by reference. Or by value. I use Smalltalk, and Smalltalk has no distinction. Everything is an object, objects are your only values. From a C point of view, the only way to refer to an object is by its reference, so you could say that everything in Smalltalk is by reference. In any case, ValueObject works very well in Smalltalk. I am sure that some of your problems are due to having to worry about memory management. If you had an efficient garbage collector then you could just always refer to a reference, use an equality function to compare values, and not care whether they were the same reference or not.

Java is like Smalltalk in this regard. It will be interesting to see how ValueObject expresses itself in Java. It should be more like Smalltalk than C++.

--RalphJohnson


ReferenceObject seems to refer to an object where one instance of the object changes whenever another instance of the object changes. That works via reference for free. ValueObject seems to refer to an object where, if you put a copy in another variable, then change that other variable, the original shouldn't change. Is this wrong?

Yeah, that is the confusion. You are thinking of reference vs. value semantics. ReferenceObject-s are true objects, representative of something that can change state. ValueObject-s represent values themselves, things like the number '4.' '4' will never magically become '5.' If it did all the arithmetic in the world would fail. Worse than Y2K. ValueObjectsShouldBeImmutable because they represent things that are immutable: values. -- mf

It seems to me that MichaelFeathers is arguing that a change to one variable containing a ValueObject shouldn't change another variable containing the same ValueObject, yet he's arguing that immutability should be used to prevent such altering, limiting his ability to then vary his variables. Why should I lose the ability to alter the contents of my variable simply because I don't want to alter the contents of other variables which may happen to be the same? Why should my language make me jump through hoops to vary something which, by its very name, was intended to vary?

The garbage collection issue doesn't come up in C until you ReturnNewObjectsFromAccessorMethods. That can become a garbage collection horror in just about any language, if the accessors are used too frequently. Passing by reference is one of the tricks used to *avoid* memory management. My problem is that all of the forms of ValueObject I've seen discussed here break things - either they break your code, when you vary a variable, and thus change another variable which shouldn't, or they break your ability to vary variables, or they stress-test (possibly breaking) your garbage collection. This just seems wrong to me. Can anyone see what I'm missing?

--EdGrimm


Yes, ValueObject does not mean that variables that contain a ValueObject are immutable, it means that the member variables of the ValueObject itself are immutable. Once you set them in a constructor, you never change them.


Well, making a local copy of the object can be pretty expensive too. You are incurring that cost always, even if the caller doesn't need to change his copy.

I regard mutable state as a complexity regardless. I try to think and write in terms of immutable objects and I mutate things primarily as an optimisation. As I rarely use setX(), I don't care that I'm not allowed to use it, so I am happy with an immutable object. And I am therefore happy to share it with other code, so I return references rather values where copying the value is significantly expensive.

> "you can't do anything" -- Yes you can. You can copy it, or make a new object with a slightly different value.

> "garbage collection problem" -- a good garbage collector has costs proportional to the amount of live data, not to the number of allocations. So small, temporary objects are cheap even if you have lots of them. -- DaveHarris


It seems to me that MichaelFeathers is arguing that a change to one variable containing a ValueObject shouldn't change another variable containing the same ValueObject, yet he's arguing that immutability should be used to prevent such altering, limitting his ability to then vary his variables.

You can alter your variable in any way you like. It's just that you have to create a new object and replace the existing one.

So instead of:

  myDate.incrementDay()

you say

  myDate = myDate.nextDay()

(I know this is not the real java.util.Date API)

Yes it would be nice if values were always passed by value. You can arrange this in C++ and IBM do this with SanFrancisco. But the reality is that this does not happen automatically, nor is it possible in Smalltalk or Java. So I find it easier make my values immutable.

--MartinFowler


This:

x = 2 + 3
might be implemented as:
x = new Integer( new Integer(2) + new Integer(3) );
In other words, the assignment to 'x' attaches a new value to it without changing the old value. The values '2', '3' and the old value of 'x' are in fact immutable. That being the case, you can't tell whether reference or value semantics are being used.

ValueObjectsShouldBeImmutable - in fact for me that is the definition of what a value object is. Then, whether it is are passed by value or by reference is only a question of efficiency. Small object use value, large ones use reference to save copying. -- DaveHarris


JamesGosling has drafted a proposal for extending the JavaLanguage so that certain classes can be written to be passed by value: http://java.sun.com/people/jag/FP.html#classes

It seems clear to me that the proposal is made on the grounds of efficiency when dealing with ValueObject classes.


There's a lot of talk here about how to think of a value "object" as the same kind of thing as a primitive (like 10 or 'a').

Maybe it's easier to think about the other way around. Try thinking of primitives as reference objects in disguise. A reference to a immutable value object is a pointer to a memory location somewhere in the heap. A reference to a primitive on the other hand, is a reference to a conceptual space, not inside the computer's memory. "00001010" is a reference to the object ten that doesn't exist in memory. Luckily the "class" byte is defined in such a way that it doesn't need to store any value information, it can figure out everything it needs from the object's reference.

So when you pass an object by value in C++, you can pretend you're passing an special kind of reference to an imaginary immutable object that does not exist in memory and maintains no state. You can pretend that any modifications you make to the variable are in reality just changes to the reference. You end up referring to a different imaginary immutable object of the same type.

--BenArnold

'' This is a brilliant analogy, thanks for taking the time to explain it. I've written script-language interpreters in the past where I took the decision to remove the value/reference distinction by having absolutely everything be a reference. I never found a satisfactory framework for thinking about the consequences of this at the time, but armed with this insight my thinking might have gone faster.


ValueObject


EditText of this page (last edited October 20, 2012) or FindPage with title or text search