Value Objects Should Be Immutable

You can easily get a nasty bug if you make a change to a ValueObject.

  task1.setStartDate(new Date("1 Jan 98");
  //then somewhere in the task class
  void delay(int delayDays) {
	_startDate.setDate(_startDate.getDate() + delayDays);

// then somewhere task2.delay(5);

and now you find task1's start date has changed.

This is doubly nasty because it is really hard to find the cause of the trouble.

So if you design an object that should be a value object, don't provide any methods that change its state, ie make it immutable.

Users will have to write

  void delay(int delayDays) {
	_startDate := (new Date(_startDate.getYear(),
	_startDate.getDate + delayDays);

If you are using a ValueObject that is mutable, treat it like it is immutable. You may not realize why, but you will save a lot of time and money.

-- MartinFowler

I have observed another manifestation of this in Java:

Problem: Returning an object by means of an accessor method. You intend to return a value but you return a Java object reference.

Symptoms: the client object is given a reference to an attribute. This attribute may have been declared private. The client of the class could invoke methods through this reference to change the value of the attribute.

Only if someone is violating the LawOfDemeter. Only A should be sending messages to B. -- JackRich

Solution: The accessor method returns a copy of the attribute and not a reference to the attribute itself.

(See [] (for a concrete example) and ReturnNewObjectsFromAccessorMethods for further details. (Also of interest: JavaIdioms.)

I'm not convinced ValueObject classes are classes at all since:

Personally, I choose to model each kind of ValueObject as an AbstractDataType implementation.

-- DafyddRees

This doesn't make any sense to me. The way that Java models an AbstractDataType is with a class. "Class" is a language feature in Java, while AbstractDataType is not. So, how can you choose to model anything as an AbstractDataType?

Further, it is very useful to model an AbstractDataType as a class, because that way you get polymorphism for free. Sometimes inheritance is useful, too. As a long-time Smalltalker, I realize that it is a little funny to use the same language mechanism to represent integers and customers, but there are advantages to having as few mechanisms as possible, and there are some fairly simple idioms for implementing a ValueObject, so I long ago decided that it was unnecessary to have two language mechanisms, one for objects and one for AbstractDataType.

-- RalphJohnson

To make things clearer, I should have pointed out that I'm talking about conceptual models rather than code.

There are types in Java that behave like ADTs. Consider the primitive data types (i.e. boolean, char, byte, short, int, long, float and double), for example: they have values, the values can be related using constants and side-effect free functions. Above all, their (logical) states can't be changed.

This use of ADTs fits well with the attributes allowed in the Class Diagrams of OMT and the FusionMethodology. (Especially since you are told in the OMT book (ISBN 0136298419 ) that attributes in OOA class diagrams are types of "pure data values" rather than other objects.)

Hope that helps.

-- DafyddRees

How does SmalltalkLanguage handle ValueObjects? For example integers, boolean values. How are these defined? (What other classes make up their definition?)

-- DafyddRees

SmallIntegers? are primitives in Smalltalk. Although there is a class SmallInteger, you can't subclass it and a lot of the methods can't be changed. On the other hand, Boolean, True and False are just normal Smalltalk classes. Moreover, I consider classes like Date and Fraction to be ValueObjects, too. To me, a ValueObject is not a language feature, it is a design feature. I call an object a ValueObject when I want to treat it like a value, and that means making it be immutable. It is theoretically possible to modify a Date or a Fraction, though I've never seen it done, so in practice they are immutable. Point should also be immutable, though I've seen a Point modified. It shouldn't be; if you want a Point with a different value, make a new one. The problem with Point is that it has an x: and a y: message that lets you change its value. Those methods should be deleted and the only way you should be able to set those fields is to create a new object.

-- RalphJohnson

It is interesting to note that the classic CircleAndEllipseProblem is a variation on the same theme. Ellipses that can be modified really represent the mathematical notion of a family of ellipses rather than a single concrete instance. -- MichaelFeathers

It is even more interesting that constness hasn't been brought up in this discussion at all.

See ValueObjectsCanBeMutable, RefactoringImprovingTheDesignOfExistingCode

EditText of this page (last edited January 4, 2005)
FindPage by browsing or searching

This page mirrored in JavaIdioms as of April 29, 2006