See also: Value Object Hypotheses, Value Objects Can Be Mutable, Value Objects Should Be Immutable, Value Objects Should Be Passed By Value, Value Object Framework, Java Value, Value Object Literature, Proto Value
Examples of value objects are things like numbers, dates, monies and strings. Usually, they are small objects which are used quite widely. Their identity is based on their state rather than on their object identity. This way, you can have multiple copies of the same conceptual value object. Every $5 note has its own identity (thanks to its serial number), but the cash economy relies on every $5 note having the same value as every other $5 note.
So I can have multiple copies of an object that represents the date 16 Jan 1998. Any of these copies will be equal to each other. For a small object such as this, it is often easier to create new ones and move them around rather than rely on a single object to represent the date.
A value object should always override .equals() in Java (or = in Smalltalk). (Remember to override .hashCode() as well.)
A value object is not a Business Object/Reference Object. A Business Object/Reference Object is something you find in the world, while a Value Object is a measure or description of something.
www.riehle.org presents an in-depth discussion of why and where you want value objects and how to implement them efficiently in different languages.
Chapter 9 of Functional Pattern System For Object Oriented Design describes Value Object.
I haven't read it yet, but there is an article on Value Object(s) in the July/August 1998 issue of the Journal Of Object Oriented Programming. It is 'Values and Objects Revisited' by Peter Van Der Werf. -- Michael Feathers
Someone good with C++ can explain what to do with that language for value objects.
Compare this with a Reference Object.
Comment: In C++, you typically implement value objects using reference-counted copy-on-write classes (body/handle idiom). Jim Coplien explains this idiom well in his book on Advanced C++. Otherwise, see our technical report. -- Dirk Riehle
If the definition of value object is an object whose identity is defined by its state rather than by its address, I'm inclined to think that they are defined in C++ as objects that override the copy constructor, assignment and comparison operators to assign and compare state between two objects. Overriding the assignment operator is key and means that in C++ Value Objects Can Be Mutable and usually are. The aliasing problems addressed in Value Objects Should Be Immutable are generally taken care of by using pass-by-value semantics. -- Phil Goodwin
I think there's a useful distinction to be drawn between assignment and mutation in general, especially in C++. Say you have a plain old int, "i," whose value is five. This object is mutable in the sense that, yes, you can change it. But what you're changing is not the value, but which value. In other words, if I assign a value of ten to "i," I'm not effecting any mutation upon the value "five;" I'm replacing the value "five." Such is the general case with value types in C++. In some sense, assignment for a value type on which assignment is the only "mutating" operation can be thought of as a shorthand for a manual destructor call followed by a placement new. Borrowing from the "Point" example below, modulo stylistic choices:
struct point { const int x; const int y;
point (const point&) = default;
point& operator = (const point& other) { this->~point (); return *new (this) point (other); } };
Even this is really a folded version of a pair of types, one of which represents the point (x, y), the other a point (x, y). We fold them together because C++ makes it so much cheaper and easier than putting "the" objects on the heap, and implementing "a" objects as references thereon (IIRC, this is the behaviour (though not necessarily implementation) Scheme defines for integers: as though an integer is a reference to the value encoded). The latter approach, I suspect, is a potential reason to argue that Value Objects Require Garbage Collection. -- Stuart Olsen
In C++, creating a Value Object is almost trivial. For example:
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; }
Now you can declare both mutable and immutable Point objects:
Point aMutablePoint( 4, 10 ); const Point anImmutablePoint( 5, 5 );
The compiler will not allow you to call setX() or setY() on anImmutablePoint, since they are not declared as const methods.
Of course, you can get around this if you really want to:
((Point) anImmutablePoint). setX( 7 );
but this is cheating - akin to writing self-modifying code.
-- Russell Gold
You need to be aware of the difference between logical state and physical state. Sometimes, what Russell Gold calls "cheating" above is due to this difference.
Logical State is when the externally visible behaviour of an object depends on its history. Physical State is about its implementation. For example, updating a cache usually means a change in the physical state but not the logical state.
Optimizers are usually interested in implementations and the physical state. For example, to store a value object in Read Only Memory, its physical state needs to be immutable. Programmers are usually interested in interfaces and logical state. They want to be free to change implementation state, introduce caches etc. This can invalidate the assumptions the optimizer makes.
Thus in the context of Value Object(s), these two forces are present and in conflict. Care may be needed to balance their requirements. (Modern C++ has extra language features to help, including
const,
mutable,
)
-- Dave Harris
Given that
Value Objects Should Be Immutable, and that
Value Objects Should Be Side Effect Free (i.e. all non-constructor methods are queries or accessors)
... Value Objects become particularly amenable to processing with Pipes And Filters-style architecture (since ordering of processing becomes irrelevant).
--
Sometimes you have too many arguments for a Single Step Constructor to be convenient. Then you may have a 2-phase object: it's mutable during the set-up processes, but then becomes immutable once it is complete. Or you have set-once variables. Thus:
void synchronized setTarget( Point target ) { Assert.assert( this.target == null ); Assert.assert( target != null ); this.target = target; }
This falls short of a full Value Object but has many of the advantages. -- Dave Harris
If I had too many arguments for a single constructor call, I would create a 'warehouse' object and pass that to my object's constructor. I can even modify the warehouse object (which is mutable) incrementally and when it's just right, pass it to my object, which sets its own state within its constructor, so it can still be const. (This is related to Memento Pattern, except the memento is created from scratch, rather than from an existing object). Anyone else Have This Pattern? (I've wanted to say that!) -- Joshua Juran
Such an object is called an Essence Object.
Kinda sounds like a Builder Pattern. -- Craig Putnam
Here are some examples of value object classes:
The elements of the periodic table. (Atomic number, atomic mass, group and so on shouldn't change over time.)
The instances of a class that represents a www client request.
The direct instances of classes that model enumerated types.
There is an interesting proposal for immutable value classes in Java: java.sun.com
--
In Java, hashcode of Value Object must be calculated only once and then reused. (Or, more accurately, if equals() returns true for two objects, then the result of hashCode() must be the same for each. You can calculate the value as much as you want as long as that rule is upheld.)
I have a couple of nice (IMHO) base classes for c++ that wrap a pointer to create a concrete object that has either value- or reference- semantics: www.geocities.com
(Broken Link, available instead at web.archive.org )
See also:
Sun uses the term Value Object to refer to a local cache of instance variables from a remote object. Perhaps a better name for their pattern would be Remote Values Cache or something similar.
More like a portable version of the heavy server-side object. -- Geraldo Xexeo
Hehe, looks like they *did* change the name:
(now I have to go and rename all of my Value Objects, I guess ...) -- Mike Colbert
see Data Transfer Object -- Ben Arnold
One of the Object Objects
There is a very insightful lecture on this topic by Rich Hickey (creator of Clojure) titled 'The Value of Values': www.infoq.com
See original on c2.com