Mutable Value Object vs. Immutable Value Object vs. Immutable Value Object Factory.

OK.

I have had this issue on my mind for some while now. And these opinions come from personal experience.

Mutable Value Object

One thing I have noticed in developing Java Enterprise application is that a lot of people use a Mutable version of the Value Object pattern.
The value object pattern is simply an object that contains data that is passed between different layers in the application. [Or within the layers themselves]
The reason that a lot of Java engineers make the ValueObject mutable is because sometimes it may have to worked on by many intermediate processes before its final use.
In one application I have worked on, there were over 20 different processes adding and manipulating data in a value object before finally being sent to a presentation layer. [In this case it was sent out as an email, but the ideas stand]
The following is a simplified mutable value object;
[java]
import java.math.BigDecimal;

/**
*
* @author coderkeitaro
*/
public class ImmutableVO {
private String stringVal = null;
private Integer integerVal = null;
private BigDecimal bigDecVal = null;

/** Creates a new instance of ImmutableVO */
public ImmutableVO(String some_string) {
if (some_string == null){
// throw an exception or something
}
this.stringVal = some_string;
}

/** getters and setters **/

public String getStringVal() {
return stringVal;
}

public Integer getIntegerVal() {
return integerVal;
}

public BigDecimal getBigDecVal() {
return bigDecVal;
}

public void setIntegerVal(Integer integerVal) {
this.integerVal = integerVal;
}

public void setBigDecVal(BigDecimal bigDecVal) {
this.bigDecVal = bigDecVal;
}

}
[/java]
Now when the persistence layer creates the initial value object, it fills in the StringVal, which is the default value for the value object.
as the value object processes through the business logic layer of the application the business logic adds and manipulates the bigDecVal and integerVal members of the value object.
Now, suppose the business logic is flawed in some way and inserts a null in one of mutable members of the value object?
If the value object MUST be fully filled with valid data, no nulls, at the presentation layer then a null pointer exception will occur. [Unless some skeptical coder validates each mutable value object before presenting it and throws a custom exception]
There would have to be multiple validators to check for the correct state of the mutable value object after each business object has touched it.
But what if someone forgot to check the validity for their section of business logic?
Tracking down a null pointer exception in a large application can be a nightmare if you have mutable value objects.
You do not have a clue which of the many business processes that touch it have introduced the invalid data.
There is, as you can guess, a much better way

Immutable Value Object

If you make the value object immutable, like a string, you can ensure validity of the object in the constructor.
Each time data must be added or manipulated by a business process a totally new immutable value object is created.
The null pointer would happen at the point of creation, making debugging a cinch.
[java]
/**
* ImmutableBaseVO.java
*
* @author coderkeitaro
*/
public class ImmutableBaseVO {
private String stringVal = null;

/** Creates a new instance of ImmutableBaseVO */
public ImmutableBaseVO(String stringVal) {
if (stringVal==null){
// throw exceptions and stuff here
}
this.stringVal = stringVal;
}

/** getters and setters **/
public String getStringVal() {
return stringVal;
}

}

/*
* ImmutableSecondVO.java
*/
import java.math.BigDecimal;
/**
*
* @author coderkeitaro
*/
public class ImmutableSecondVO{
private String stringVal = null;
private Integer integerVal = null;
private BigDecimal bigDecVal = null;

/** Creates a new instance of ImmutableSecondVO */
public ImmutableSecondVO(ImmutableBaseVO baseVO, Integer integerVal, BigDecimal bigDecVal) {
if (baseVO==null||integerVal==null||bigDecVal==null){
// throw exceptions and stuff here
}
this.stringVal = baseVO.getStringVal();
this.integerVal = integerVal;
this.bigDecVal = bigDecVal;
}
/** getters and setters **/

public String getStringVal() {
return stringVal;
}

public Integer getIntegerVal() {
return integerVal;
}

public BigDecimal getBigDecVal() {
return bigDecVal;
}

}

/*
* ImmutableThridVO.java
*/
import java.math.BigDecimal;
/**
*
* @author coderkeitaro
*/
public class ImmutableThridVO {
private String stringVal = null;
private Integer integerVal = null;
private BigDecimal bigDecVal = null;

/** Creates a new instance of ImmutableThridVO */
public ImmutableThridVO(ImmutableSecondVO secondVO,BigDecimal addBigDec) {
if (secondVO==null||bigDecVal==addBigDec){
// throw exceptions and stuff here
}
this.stringVal = secondVO.getStringVal();
this.integerVal = secondVO.getIntegerVal();
this.bigDecVal = addBigDec.add(secondVO.getBigDecVal());
}
/** getters and setters **/

public String getStringVal() {
return stringVal;
}

public Integer getIntegerVal() {
return integerVal;
}

public BigDecimal getBigDecVal() {
return bigDecVal;
}

}
[/java]
Hmm. This is better because now if you enter invalid data the exception happens during construction of the value object.
But you end up with lots of new classes. Each one for each new manipulated version of the value object.
This can make sense in most applications, as the raw data is different from the manipulated data, and can be seen as different architecturally.
But some people, incorrectly, consider that the more classes that exist in a system the more complex it is and thus the harder it is to maintain. [Well, I think in the case of Immutable vs. Mutable VOs this is actually the complete opposite. The more immutable VOs you have the easier it is to spot the difference.]
People also complain because you have to rewrite a lot of code. Notice in the above that you have to rewrite all the getters for each new ValueObject, even though they are essentially the same. If you used inheritance you could use protected members, but then this violates the immutability of the value object.
Is there a way to keep the value object immutable ad still have only a single value object…?
The answer is yes. If you also use the object factory method. And exercise some caution.

Immutable Value Object Factory

This take on the value object pattern could use a separate object as the factory for value object, but it is easier to just implement the factory as a static factory method on the ValueObject itself.
[java]
/*
* ImmutableFactoryVO.java
*/
import java.math.BigDecimal;
/**
*
* @author coderkeitaro
*/
public class ImmutableFactoryVO {

private String stringVal = null;
private Integer integerVal = null;
private BigDecimal bigDecVal = null;

/** Creates a new instance of ImmutableFactoryVO */
private ImmutableFactoryVO(String stringVal, Integer integerVal, BigDecimal bigDecVal) {
// cannot create an instance! must use factory methods!!
this.stringVal = stringVal;
this.integerVal = integerVal;
this.bigDecVal = bigDecVal;
}
/** factory methods! **/
public static ImmutableFactoryVO getNewBaseVO(String stringVal){
if (stringVal == null) {
// throw the exceptions here
}
return new ImmutableFactoryVO(stringVal, null, null);
}
public static ImmutableFactoryVO getNewSecondVO(ImmutableFactoryVO baseVO, Integer integerVal, BigDecimal bigDecVal){
if (baseVO==null||integerVal==null||bigDecVal==null){
// throw exceptions and stuff here
}
return new ImmutableFactoryVO(baseVO.getStringVal(), integerVal, bigDecVal);
}
public static ImmutableFactoryVO getNewThirdVO(ImmutableFactoryVO secondVO,BigDecimal addBigDec){
if (secondVO==null||secondVO.bigDecVal==null||addBigDec==null){
// throw exceptions and stuff here
}
return new ImmutableFactoryVO(secondVO.getStringVal(), secondVO.getIntegerVal(), addBigDec.add(secondVO.getBigDecVal()));
}

/** getters and setters **/

public String getStringVal() {
return stringVal;
}

public Integer getIntegerVal() {
return integerVal;
}

public BigDecimal getBigDecVal() {
return bigDecVal;
}

}
[/java]
Notice a subtle difference between this and the previous immutable solution.
The factory method for the third business process HAS TO also check the validity of the data in the passed in value object is valid, as well as checking that it is not null.
I have lazily not implemented all the appropriate checks….
what happens if someone creates a new factory method that does not initialize the integerVal and then passes that factory method the object…
the same as in the first scenario. You end up with a null pointer exception far, far away from the actual cause of the problem.
So make sure, if you use this pattern, to check that ALL the data, including data inside passed in value objects, is valid.

As this is basically state based you could also implement an enum that contains values for all the states that the value object contains.
Passing in the appropriate enum value during the construction of the Immutable Value Object Factory so that you can check that the state is set correctly, i.e. that you have the right type of ImmutableFactoryVO before creating the new one.
[java]
/*
* ImmutableFactoryVO.java
*/
import java.math.BigDecimal;
/**
*
* @author coderkeitaro
*/
public class ImmutableFactoryVO {
public enum ImmutableFactoryState{
BASE, SECOND, THIRD;
}
private String stringVal = null;
private Integer integerVal = null;
private BigDecimal bigDecVal = null;
private ImmutableFactoryState state;

/** Creates a new instance of ImmutableFactoryVO */
private ImmutableFactoryVO(String stringVal, Integer integerVal, BigDecimal bigDecVal, ImmutableFactoryState state) {
// cannot create an instance! must use factory methods!!
this.stringVal = stringVal;
this.integerVal = integerVal;
this.bigDecVal = bigDecVal;
this.state = state;
}
/** factory methods! **/
public static ImmutableFactoryVO getNewBaseVO(String stringVal){
if (stringVal == null) {
// throw the exceptions here
}
return new ImmutableFactoryVO(stringVal, null, null, ImmutableFactoryState.BASE);
}
public static ImmutableFactoryVO getNewSecondVO(ImmutableFactoryVO baseVO, Integer integerVal, BigDecimal bigDecVal){
if (baseVO==null||integerVal==null||bigDecVal==null){
// throw exceptions and stuff here
}
return new ImmutableFactoryVO(baseVO.getStringVal(), integerVal, bigDecVal,ImmutableFactoryState.SECOND);
}
public static ImmutableFactoryVO getNewThirdVO(ImmutableFactoryVO secondVO,BigDecimal addBigDec){
if (secondVO==null||secondVO.state!=ImmutableFactoryState.SECOND||addBigDec==null){
// throw exceptions and stuff here
}
return new ImmutableFactoryVO(secondVO.getStringVal(), secondVO.getIntegerVal(), addBigDec.add(secondVO.getBigDecVal()),ImmutableFactoryState.THIRD);
}

/** getters and setters **/

public String getStringVal() {
return stringVal;
}

public Integer getIntegerVal() {
return integerVal;
}

public BigDecimal getBigDecVal() {
return bigDecVal;
}

public ImmutableFactoryVO.ImmutableFactoryState getState() {
return state;
}

}
[/java]
Although this looks like hardly any benefit, with my overly simplistic Value Object, it can be of great benefit for complex value objects as you now know what you are getting. The state of the value object represents the validate done to enter that state. ImmutableFactoryState.SECOND MUST have all the data in the object not null. It MUST be valid.
[Make sure to add comments to the enums so that you know what has/has not been initialized in the VO. That way you won’t forget, and other developers won’t make silly mistakes]
This also allows complex states too. Say you do create a new factory method that only initializes the bigDecVal, called getNewFourthVO, and another, called getNewFifthVO, that can can take value objects with either ImmutableFactoryState.SECOND, ImmutableFactoryState.THIRD or ImmutableFactoryState.FOURTH for their state. If there is a null in the integerVal it uses some default value, and returns the value object in the ImmutableFactoryState.FIFTH state.

So there you have it.
Three different solutions to the Value Object pattern.

The first I would avoid like the plague after having bad experiences with it in the past.
I prefer the second [More classes, but easier to find bugs due to invalid states].
But I would settle for the enum version of the last solution if the architects and other developers complained at the number of Value Object classes being spawned by the second solution.

One thought on “Mutable Value Object vs. Immutable Value Object vs. Immutable Value Object Factory.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s