J2EE Blueprints Design Pattern
Value Object

 name

Value Object

 intent

Reduce network traffic and improve response time for access to coarse-grained, read-only data

 category

Behavioral Pattern

 motivation

Some enterprise information objects have values that are always used together. For example, in the Java Pet Store sample application, the fields of the Address object are always used together. Using complete remote interfaces for such entities is overkill, and results in unacceptably high server communication.

The data for an Address object can be retrieved once, sent to the client from the server in serialized form, and instantiated on the client. From then on, the local copy of the Address information can serve as a Proxy for the Address property of the remote Order object. Subsequent accesses to the Address object's state are local, require no server communication, and use fewer resources. If the Address object is updated, and sent to the server to update the server-side object, the entire object is sent. Furthermore, local accesses obviously have lower latency than accesses deferred through a remote interface.

Such a client-side object is called a Value Object, because it represents a (composite) value from the server, not a reference to an object on the server. Value Objects tend to be more-or-less ad hoc groupings of data values to support a use case (or group of use cases).


 applicability

Use a Value Object when the business entity being modeled has:

  • only methods that get values from the object's internal state (in other words, it's immutable)
  • a lifecycle that is completely controlled by another object
  • relatively small size

 structure

Figure 1. UML Diagram for the Value Object.

 participants

LocalEntityObject

  • Presents a local interface to a remote object
  • Represents one or more properties of remote object as immutable instance(s)
EntityObject

  • Has meaningful identity
  • Represents one or more properties as immutable objects
ValueObject

  • Represents the value of a property of some other object
  • Is dependent upon that other object for its lifecycle
  • Provides access to its state via property accessors

 collaborations

LocalEntityObject

  • Acts as a Proxy for a RemoteEntityObject
  • Represents one or more properties of RemoteEntityObject as ValueObject instances
ValueObject

  • Acts as a Proxy for a property of RemoteEntityObject
  • Provides access to its internal state via property accessors
  • Is constructed, initialized, and serialized by EntityObject
  • Is deserialized and maintained by LocalEntityObject
RemoteEntityObject

  • Expresses a property as a ValueObject
  • Constructs, initializes, and serializes ValueObject
  • Transmits ValueObject to LocalEntityObject
  • Typically represents remote state

 consequences

The Value Object pattern provides the following benefits:

  • A Value Object can reduce network traffic by acting as a caching Proxy for a property of a remote object.
  • Total load on the remote object's remote interface is decreased, because data represented by the Value Object are cached on the client by the Value Object instance. All accesses to the properties of Value Objects are local, and so those accesses cause no remote method invocations.
  • Decreased latency can improve user response time.
  • Since a Value Object is a snapshot of database state, it can be stale.

 implementation-issues

Large objects do not make good Value Objects. The purpose of the Value Object is to decrease network traffic. Large objects by their nature are expensive to construct and transmit. For example, while Catalog object has values that are used together, it usually does not make a good candidate for the Value Object pattern. The cost of constructing, serializing, and transmitting an entire Catalog data structure usually outweighs the network traffic caused by remote access to a remote Catalog. An individual entry in a catalog, however, might well be appropriately represented as a Value Object.

Value Objects are local caches for groups of values, but they are not write-through caches. If a Value Object is modified, its value is out of synchronization with the state in the database. Appropriate cache invalidation schemes must be applied to avoid data inconsistency.

Programming with Value Objects can be tedious. The interface to a Value Object is not object-oriented in spirit, since its API is limited to getting and setting the properties of the object. The methods of Value Objects serve no useful business function. Doing anything useful with a Value Object implies pulling data out of the object and putting that data somewhere else. This implies that maybe those data should have been "somewhere else" in the first place. When writing methods that use value objects, try to localize the setting-and-getting, so that the rest of the system design can remain object-oriented.

Stale Value Objects can be an issue in distributed systems. When a Value Object represents a group of values extracted from some volatile resource (such as an EJB, a database, etc.) it represents not the state of that resource, but a snapshot of its state. For example, a Value Object containing "the current time" reflects not the true current time, but the time at which the value was created. The Value Object can't change to reflect the true current time, because Value Objects are immutable. In other words, Value Objects can become stale. When using Value Objects in a distributed environment, be sure to consider what impact stale Value Objects will have on your system's operation.

Heavy use of Value Objects may be a symptom of procedural thinking.Procedural designs concentrate on implementing procedural operations on values. In Object Oriented design, values belong primarily inside objects, and the objects operate on their own values with methods. Too many values being passed around indicates that the object design isn't well-factored, because the object methods don't know enough to do their job without a long list of arguments. The cure is to refactor the object design so that objects are responsible for working on their own data, not data belonging to some other object.


 sample-code

Definition: Address.java Usage: OrderDAO.java

Definition: com/sun/j2ee/blueprints/customer/util/CreditCard.java Usage: com/sun/j2ee/blueprints/customer/order/ejb/OrderDAO.java

Definition: sun/estore/util/ContactInformation.java Usage: com/sun/j2ee/blueprints/petstore/control/web/OrderHandler.java


 known-uses

An Address object contains only data fields, is completely dependent on the parent Account object, has only get property accessors, and is fairly lightweight; therefore, it is an ideal candidate for a Value Object.

A CreditCard shares with an Address its dependence on an Order, its immutability, and small size, and therefore is also a good candidate for the Value Object pattern.

The ContactInformation property of the Account object is also a Value Object.


 related-patterns

Proxy (GOF)