It has been proposed that ValueObjects should be immutable in order to avoid the aliasing problems that would occur if two objects held references to a single, mutable, instance of a value object. Recall that ValueObjects derive their identity from their state. As a result changing the state of a ValueObject is tantamount to changing its identity out from under its reference. Changing the state of a ValueObject that is held by reference by two different objects effectively changes the identity of both of the objects so held even when the intent is generally to change only one. Making value objects immutable solves this problem by forcing the developer to create a new object every time some aspect of the ValueObject's state changes. This is certainly a viable solution but it is not the only one available.
Another solution to the same problem is to hold ValueObjects, not by reference, but by value. This comes naturally in a language such as C++ where the distinction between values and references is explicit. If two objects hold the same ValueObject by value it means that there are two separate instances of the same state and that changing state of one instance is not tantamount to changing the state of the other. This solution trades the convenience of holding all objects by reference for the convenience of being able to change any aspect of a ValueObject's state without having to create an entirely new object to do so. It is generally implemented by defining a copy constructor and an assignment operator that copy the state of one ValueObject over to another and one or more comparison operators (==, !=, >, <, >= and <=) that compare the state of one ValueObject to another. This strategy has the happy side effect of allowing aliasing when it is desired simply by holding ValueObject-s by reference instead of by value.
The lack of garbage collection in C++ makes the immutable ValueObject strategy somewhat more inconvenient so it is seldom seen in that language in its pure form. However, the existence of constant references in C++ does allow for a compelling combination of these two strategies. With this strategy ValueObject parameters and return values are passed by constant reference. These local variables are references to immutable ValueObjects and have the same properties as described in ValueObjectsShouldBeImmutable. However, member variables are typically held by value. When one of these constant references is assigned to a member variable the state of the object that it refers to is copied into the member variable thereby allowing the member variable to change without causing aliasing problems between it and the referred-to object.
On the ValueObject page DirkRiehle makes reference to a strategy that involved a combination of reference-counting and copy-on-write semantics. In this scheme reference-counting replaces garbage-collection and is specific to C++. The implementation of copy-on-write semantics, however, is applicable to multiple languages and provides a portable strategy for allowing ValueObject-s to be mutable (or at least appear to be mutable). It can be thought of as automating the process of creating a new instance whenever the state of the ValueObject changes so that clients don't have to remember to do it themselves. To accomplish this a reference to an immutable ValueObject is held by the mutable ValueObject. All non-mutating calls are simply forwarded to the immutable ValueObject. Mutating calls are intercepted and implemented by creating a new immutable ValueObject with the correct new state. Instances of the mutable ValueObject must be passed by value (in Java that means making a copy through "clone" in C++ it just means not passing by pointer or reference) to avoid aliasing problems. Since the only member of the mutable ValueObject is a reference this is a very cheap operation. -- PhilGoodwin
Phil, I think I see where you are going with this, but I think that the immutability of ValueObjects is really part of their nature. The old saw "is a date changed the same date or another date?" illustrates the issue. Something like 12/4/98 is a pure value. A variable can have that value, but the value itself can not be changed. Imagine a class with a variable "numberOfWheels" It may have the value 4 at times. You can change the value of numberOfWheels, but you can not change the value of 4. 4 is a value. To me, a ValueObject is something which represents a pure value. -- MichaelFeathers
But you can change the value of a variable that has been set to 4. You haven't changed the value of 4 but you have changed the value of the variable. The key issue is not whether the values themselves are immutable (we are agreed that they are) but whether the containers for those values should be immutable. What I am saying is that if you pass the values around by making copies of their representations into containers for those representations then the containers don't have to be immutable. If, on the other hand, you pass the values around by copying references to those containers then the containers do have to be immutable. The difference is that in the first case the containers hold the values and in the second the containers are the values. -- PhilGoodwin
It seems to me that you are confusing variables (l-values) and objects (r-values). It is true that a variable can be constant, but that is not what we are talking about when we speak of a ValueObject. There is nothing wrong with a variable holding one immutable ValueObject and then another. But in that case, it is the variable (container) which has changed, not the ValueObject. -- RussellGold
Actually, I think that the confusion is not at my end. It seems to me that people are confusing references to an object with the object itself. In Java all objects are held by reference so the difference can't really be exploited. In C++, however, you can hold an object by value. In that case the variable is the object. I think that the confusion might be between variables (l-values), values (r-values) and objects (either). A variable can either be an object-by-value or a reference to an object. ValueSemantics for objects-by-value are preserved by copying values between objects. ValueSemantics for objects-by-reference are preserved by using a CopyOnWrite mechanism. I had always thought that the story ended there. Are ValueObjects simply objects that preserve ValueSemantics or is there something more to them? -- PhilGoodwin
Actually, in Java you can emulate C++'s constant values and constant references. The former, as already discussed, is done using immutable objects. The latter is achieved using final (object reference) variables. You can use both in combination to emulate something akin to C++ typedefs in Java (though in a somewhat kludgy way) -- PeterSwords
ValueObjects, logically, should be immutable. If we assume that, the following can be stated: