Converting business objects into value objects

In my current project there are two types of data holder objects defined: business objects, used by the server side of the application and value objects (aka data transfer objects) which are very very very (etc.) similar to business objects in terms of properties. These types of value objects are used to pass data to the client. Nothing new so far, this actually happens in pretty many projects.

The problem occurs when these objects are converted back and forth (business object to value objects on client requests and vice versa on client pushes).  These conversations many times are implemented like this:

	public CustomerVO getCustomer() {
		CustomerVO customerVO = new CustomerVO();
		CustomerBO customerBO = new CustomerBO();

		//somehow retrieve a BusinessObject ...

		customerVO.setCustomerFirstName(customerBO.getFirstName());
		customerVO.setCustomerLastName(customerBO.getLastName());
		customerVO.setCustomerPrimaryAddress(customerBO.getPrimaryAddress());
		customerVO.setCustomerSecondaryAddress(customerBO.getSecondaryAddress());
		customerVO.setCustomerCity(customerBO.getCity());
		customerVO.setCustomerState(customerBO.getState());
		customerVO.setCustomerZip(customerBO.getZip());

		return customerVO;
	}

Well this is not very nice for some reasons. First of all, the violated single responsibility principle. This is a business method, but still, it is busy converting objects when its sole job would be to retrieve the business object. Secondly, the high number of getter/setter calls make the method noisy and long. Last, but not least it is obvious that this implementation will repeat over and over again, every time a conversion is needed, which leads to code multiplication. Just imagine what happens when a new property is added to the customer object. It would be a nightmare to correct all the methods.

So, here is an easy way these three smells are avoided: combining a (so called) Adapter with a Builder. The adapter will take an argument, the object to be converted and will return with a translated object. It will do so using the Builder (which is reusable and safe, will see in a minute) that incrementally constructs the object. Clear separation of concepts, yet really easy to use. Let’s see some code…
The Builder will look like this:

public class CustomerBuilder {

	private CustomerVO customerVO = new CustomerVO();
	
	public CustomerBuilder withFirstName(String firstName) {
		if (firstName != null) { //may default to something, don't mess up
			customerVO.setCustomerFirstName(firstName);
		}
		return this;
	}
	
	public CustomerBuilder withLastName(String lastName) {
		if (lastName != null) { 
			customerVO.setCustomerLastName(lastName);
		}
		return this;
	}

	public CustomerBuilder withZip(Integer zip) {
		if (zip != null && zip < 99999) { 
			customerVO.setCustomerZip(zip);
		}
		return this;
	}

	//... and so on with all the properties
	
	public CustomerVO build() {
		return customerVO;
	}
}

The cool thing about such a builder is that you can write it absolutely bullet proof. All kinds of validations can be included so the object’s state will never be compromised. Now we have a guy to build the object, just need one more to coordinate the process. Meet the Adapter:

public class CustomerAdapter {

	private final CustomerBuilder customerBuilder = new CustomerBuilder();
	
	public CustomerVO adapt(CustomerBO customerBO) {
		
		customerBuilder.withFirstName(customerBO.getFirstName()).
			withLastName(customerBO.getLastName()).
			withZip(customerBO.getZip());
		  //withOtherProperties(...)...
		
		return customerBuilder.build();
	}
}

Yep this is only a convenience class, so the object translation will be just one method call.
And now, we are able to replace the body of the business method with something like this:

	public CustomerVO getCustomer() {
		CustomerBO customerBO = new CustomerBO();
		//somehow retrieve a BusinessObject...
		return customerAdapter.adapt(customerBO);
	}

Well, looks nicer, I guess. Code multiplication is eliminated, as all the things that can vary are moved out into two classes; two classes accessible to all the system. And finally (wow, it’s so cool, you ready?) the roles are clearly defined and separated. The business method cares for business logic, the Adapter translates the objects while the Builder creates the object.

Advertisements

Author: tamasgyorfi

Senior software engineer, certified enterprise architect and certified Scrum master. Feel free to connect on Twitter: @tamasgyorfi

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