What are Transfer Objects and what are Value Objects? This is a question that has plagued me since I started Enterprise Java Programming. While Transfer Objects actually have a nice definition in the J2EE Design Patterns Value Objects are a different beast and various companies, individuals and organisations seem to have different ideas about what they are.
Some are naturally pretty hilarious (as are the implementations of most nebulous ideas in IT) the most ridiculous so far is that a Value Object is a collection of public fields. Pretty much like a struct in C. I think that came from a misunderstanding of the blueprint definition that states: the members in the Transfer Object are defined as public, thus eliminating the need for get and set methods. Of course you still need to make the fields final if the object is to be immutable and a value object by definition is immutable.
Now though I feel I have enough of a working understand of the ideas to offer the following definitions.
Firstly a Value Object must be immutable, serializable and it’s content must be publicly accessible. The content of a Value Object can be accessible via public final fields but to avoid the internal data becoming part of the public interface access should ideally be abstracted via getter methods. A value object should always be initialised entirely via its constructor; nesting value objects if necessary to avoid excessively long constructors.
A Value Object can only be changed and persisted by the creation of a new Value Object based on the values of the original Value Object obtained.
A Transfer Object while similar in most respects is mutable. In addition there is a reasonable expectation that the Transfer Object will be persisted if it is returned to the originating layer. So for example if a Session Bean provides a Transfer Object as the return value of one of its methods it is reasonable to expect the API to also provide a method that accepts an instance of the same Transfer Object. Any changes communicated to the Bean will be persisted and consistent so that if the original method that obtained the instance is called again it returns the values that have been returned to the layer and not the original object.
In this respect a Transfer Object is more the statement of expected behaviour on a Java Bean. I went to a talk about EJB3 where the speaker mentioned the detached object anti-pattern and I couldn’t agree more. Value Objects and Transfer Objects are really only useful in situations where the recipient layer is not really going to modify the objects that much. As soon as you allow POJO clones of entities to change value during a user transaction then you tend to get into all kinds of problems. It is exactly this kind of situation that ORMs and Hibernate clones tend to fall apart. They are great at obtaining Value Lists and dreadful at the kind of heavy lifting that is actually difficult and is where Entity Beans came a cropper in the first place.