— Phil Goodwin: 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.<br> 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.
— Michael Feathers: 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.
— Phil Goodwin: 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.
— Russell Gold: 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.
— Phil Goodwin: 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?
No comments:
Post a Comment