Friday, July 21, 2006

Constructing View objects with the Builder pattern

Domain-Driven Design gives us important concepts like Entities, Value objects, Factories, Repositories, Aggregates, Services, but doesn't talk about View objects and how to construct them.

View objects, as I see them, are a kind of DTOs without the burden of DTOs.
While DTOs represent and duplicate domain objects data, View objects simply represent data requested by a view and extracted from one or more domain objects.
What's more important, they cannot be used as replacements of domain objects, because they are immutable containers of simple data.
So, their use is (and must be) restricted to those scenarios where you need read only report-style views and fast performances.

What about View objects construction?

Like discussed in this post from the Domain-Driven Design group, there are different possibilities.
I think the best one is to use the Builder pattern:

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

You can use the Builder pattern for implementing build methods that directly access the data store for constructing different parts of the View object.
This gives you the following advantages:

  • You can separate the process of building your View object in different steps, and use only the steps you need for a particular view page, without even having to construct the full View object.

  • You can have a generic ObjectAViewBuilder with generic buildPartA() and buildPartB() steps, and then having subclasses specify what data you actually need for every given step, i.e. depending on a particular view page.



This gives you better performances and higher flexibility.

Let us go now with a simple example.

Say we have two domain objects: Employee and Office (I'm not going to show interfaces here because they are of no interest in our context).


@Entity()
@Table(name="Employee")
@Proxy(proxyClass=Employee.class)
public class EmployeeImpl implements Employee {

@Id()
private int id;
@Version()
private int version;

@Column(unique=true)
private String matriculationCode;
private String firstname;
private String surname;
@ManyToOne(targetEntity=OfficeImpl.class)
private Office office;

protected EmployeeImpl() {}

public EmployeeImpl(String matriculationCode) {
this.matriculationCode = matriculationCode;
}

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = firstname;
}

public String getSurname() {
return surname;
}

public void setSurname(String surname) {
this.surname = surname;
}

public String getMatriculationCode() {
return matriculationCode;
}

public Office getOffice() {
return this.office;
}

public void setOffice(Office office) {
this.office = office;
}

public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Employee)) return false;

Employee other = (Employee) obj;

return new EqualsBuilder().append(this.getMatriculationCode(), other.getMatriculationCode()).isEquals();
}

public int hashCode() {
return new HashCodeBuilder().append(this.getMatriculationCode()).toHashCode();
}
}


@Entity()
@Table(name="Office")
@Proxy(proxyClass=Office.class)
public class OfficeImpl implements Office {

@Id()
private int id;
@Version()
private int version;

@Column(unique=true)
private String officeId;
private String name;

protected OfficeImpl() {}

public OfficeImpl(String officeId, String name) {
this.officeId = officeId;
this.name = name;
}

public String getName() {
return name;
}

public String getOfficeId() {
return officeId;
}

public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Office)) return false;

Office other = (Office) obj;

return new EqualsBuilder().append(this.getOfficeId(), other.getOfficeId()).isEquals();
}

public int hashCode() {
return new HashCodeBuilder().append(this.getOfficeId()).toHashCode();
}
}


The two domain entities are annotated with EJB3 annotations, so they are persistent objects.

Now, your application needs some report-style view listing a few employees data, but you don't want to get the full Employee object graph: so you create a marker EmployeeView interface for representing employee related views, and an extended interface for showing just some simple data from an employee and its related office, the SimpleEmployeeView (with related implementation):


public interface EmployeeView extends Serializable {
}


public interface SimpleEmployeeView extends EmployeeView {

public String getMatriculationCode();

public String getFirstname();

public String getSurname();

public String getOfficeName();
}


public class SimpleEmployeeViewImpl implements SimpleEmployeeView {

private String matriculationCode;
private String firstname;
private String surname;
private String officeName;

public String getMatriculationCode() {
return matriculationCode;
}

public void setMatriculationCode(String matriculationCode) {
this.matriculationCode = matriculationCode;
}

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = firstname;
}

public String getSurname() {
return surname;
}

public void setSurname(String surname) {
this.surname = surname;
}

public String getOfficeName() {
return officeName;
}

public void setOfficeName(String officeName) {
this.officeName = officeName;
}
}


Please note: the view implementation has setters method, while the interface has not. This is because the view (hence its interface) has to be immutable, but setter methods must be used by the builder for constructing the View object.

Once you have some View object, you need a Builder!
So here is the generic Builder interface for constructing generic EmployeeView objects (EmployeeViewBuilder), and its concrete implementation (SimpleEmployeeViewBuilder):


public interface EmployeeViewBuilder {

public void buildEmployee(String matriculationCode);

public void buildEmployeeOffice();

public EmployeeView getEmployeeView();
}


public class SimpleEmployeeViewBuilder implements EmployeeViewBuilder {

private HibernateTemplate hibernateTemplate;
private SimpleEmployeeViewImpl view = new SimpleEmployeeViewImpl();

public void buildEmployee(String matriculationCode) {
List<Object[]> result = hibernateTemplate.find("select e.matriculationCode, e.firstname, e.surname from com.blogspot.sbtourist.domain.EmployeeImpl e where e.matriculationCode = ?", matriculationCode);
for (Object[] values : result) {
view.setMatriculationCode((String) values[0]);
view.setFirstname((String) values[1]);
view.setSurname((String) values[2]);
}
}

public void buildEmployeeOffice() {
if (view.getMatriculationCode() == null) {
throw new IllegalStateException("First call buildEmployee() method!");
}
List<String> result = hibernateTemplate.find("select e.office.name from com.blogspot.sbtourist.domain.EmployeeImpl e where e.matriculationCode = ?", view.getMatriculationCode());
for (String value : result) {
view.setOfficeName(value);
}
}

public SimpleEmployeeView getEmployeeView() {
return this.view;
}

public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}

public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
}



As you can see, SimpleEmployeeViewBuilder builds each part of the View object directly using data access API (in our example, Hibernate API), retrieving only the data it needs.
And, if you have a different employee view page, just implement a different EmployeeView with related EmployeeViewBuilder!

Finally, your Builder objects will have to be used in the Service layer, into view specific methods:


public EmployeeView getEmployeeWithOfficeView(String employeeMatriculationCode) {
EmployeeViewBuilder builder = new SimpleEmployeeViewBuilder();
builder.buildEmployee(employeeMatriculationCode);
builder.buildEmployeeOffice();
return builder.getEmployeeView();
}



I'd like to know your opinion, every feedback is welcome.

Happy building!

Updates
07/25/2006 : Improved example code (thanks to Christofer Jennings).

Friday, July 14, 2006

Spring Modules 0.5 and the XT Framework

Today, Spring Modules 0.5 has been released.

It contains a lot of improvements, as you can read from the announcement, among which you can find my main contribution to the project: the brand new Spring Modules XT Framework.

Born toward the end of the last year as SpringXT, you can find its old (never publicly announced) home page here, I'm proud and happy to say it is now a top level module of Spring Modules!

What is it?

Spring Modules XT, strongly influenced by modern Domain-Driven Design techniques and Ajax technologies, has a main aim: let you develop simple-to-complex business applications with your domain model in mind, and let you easily and powerfully construct the presentation layer of your domain model thanks to Spring MVC and Ajax techniques.
So, it provides an XT Modeling Framework, implementing Domain-Driven Design and AOP based techniques for enhancing your domain model, and XT Ajax Framework, an Ajax implemention which doesn't require you to learn any other framework or deeply change your application, because completely built on (and thought for) Spring MVC.

I invite you to take a look at its documentation and play with it.
It is just at its first stable release and it needs a lot of feedback!

Above all that, give the whole Spring Modules project a look, pick the module you need ... and let us know through its forum and mailing lists!

Tuesday, July 11, 2006

Avoid your getters and setters, Part 1

In the Java world, getters and setters are one of those things everyone says to hate but everyone actually uses.
I think this is mainly because:

  1. They are procedural, heritage of C-style (or even older) programming.

  2. They are a practice embedded by JavaBeans conventions.

  3. Many ORM and Web frameworks heavily use getters and setters.


In a series of blog posts called Avoid your getters and setters, I'll try to show you some ideas for avoiding getters and setters, by simply applying some fundamental Object Oriented and Domain Driven Design principles.

Any feedback will be highly appreciated.

Let's go!

Avoid your getters and setters: Programming to an Interface

From the GOF book:

Don't declare variables to be instances of particular concrete classes. Instead, commit only to an interface
defined by an abstract class.

This is probably the main Object Oriented principle: we could write words and words about it, but I prefer to remind you some good books like the one cited above, or like this one.

Programming to an interface is the first step toward good OO code.
Moreover, and here we come to our point, if you program to an interface, and think in terms of interfaces, you can better choose the getters and setters you need, while removing or hiding the unwanted ones.

First, thinking in terms of interfaces is thinking in terms of contracts.
Say you have a Customer entity in your domain model.
How does it interact with other entities?
What are its behaviours?
What its pre / post conditions and invariants?
That is: what is the contract defined by the Customer interface?

You may have an issue(Order ) method, and you may discover you need to know, for business reasons, the customer code.
So, here is our Customer interface:


public interface Customer {

public String getCustomerCode();

public void issue(Order newOrder);
}


Think always in terms of business contracts: all methods in your interfaces must have a business meaning.
Obviously, also getters and setters can have business meaning, which is the case of getCustomerCode().
All getters and setters without this meaning must be removed from the interface.

Here it comes your preferred ORM tool or Web Framework: it requires a lot of setters and getters for writing and reading properties, and you really don't want to do all that dirty job by hand!

What to do?

Too bad, we cannot actually avoid all those getters and setters, but we can hide them from your code simply declaring them in your concrete classes, and leaving them out from interfaces: your code, depending on interfaces, will never see all those unwanted methods!.

So you have a Customer concrete class:


public class CustomerImpl implements Customer{

...

public String getCustomerCode() { ... }

public void issue(Order newOrder) { ... }

// Setters and getters not in the interface:

public void setSurname(String surname) { ... }

public String getSurname() { ... }
}


What really hurts is the setSurname() method: in your business, once defined a customer's surname should never change!
But, hey: your code is written in terms of the Customer interface, so it will not be able to call unwanted methods!


public class CustomerService {

public void register(Customer c) { ... }
}


public class CustomerDAO {

public void save(Customer c) { ... }
}


Moreover, under the hood they actually are CustomerImpl objects, so your Web or ORM frameworks will be able to call all getters and setters thanks to Java reflection!



That's all.
And it's awful simple.
I hope to have explained well how you can hide getters and setters by simply programming to interfaces, while still using common frameworks.

In my next Avoid your getters and setters post we'll talk about the expert pattern ... in the meantime, let me know what do you think!

Saturday, July 08, 2006

Java should provide interface level equality

While working to a business domain model in a pure Object Oriented approach, one thing I miss in Java is the concept, hence the implementation, of type equality, where for type I mean interface.

Let me explain with a simple example.

Say you have a Customer entity, that in your domain model is an interface, that is, a type:


public interface Customer {

public String getCustomerCode();

public String getSurname();

public Date getBirthdate();
}



You have different concrete Customer implementations, i.e. StandardCustomer and PremiumCustomer, but customer equality is the same for all customers, because defined by the customer code: so, you want to define equality for the Customer type.
Too bad, in Java the only way to go is to implement a base class for all customers, defining, among other methods, the equals() one:


public abstract class BaseCustomer implements Customer {

public String getCustomerCode() { ... }

public String getSurname() { ... }

public Date getBirthdate() { ... }

public boolean equals(Object obj) {
if ((obj == null) || (!(obj instanceof Customer))) return false;

Customer other = (Customer) obj;

return this.getCustomerCode().equals(other.getCustomerCode());
}
}


public class StandardCustomer extends BaseCustomer {
...
}


public class PremiumCustomer extends BaseCustomer {
...
}



However, this is not correct, nor safe, because you could implement another Customer directly implementing the interface, or even extending another base class: doing so, you would break the equals contract.
For example:


public class CustomerOfTheMonth implements Customer {

public String getCustomerCode() { ... }

public String getSurname() { ... }

public Date getBirthdate() { ... }

// You forget to implement equals(), or maybe implement a different one ....
}



Now, a StandardCustomer is equal to a CustomerOfTheMonth, but a CustomerOfTheMonth is not equal to a StandardCustomer!
This is because BaseCustomer defines equality for all Customers, but CustomerOfTheMonth, while being a Customer, is not a base one!
So, the symmetry of the equals() method is broken!

The problem would be solved if we could implement the equals() method into the Customer interface, rather than into the BaseCustomer concrete class: if you had then to implement equality in a different way for some concrete class, you'd be also free to overwrite it later!

Here we come back to the beginning of my post: why doesn't Java provide interface level equality?

Tuesday, July 04, 2006

A great day

About one month has passed since the last time I've made a post.
I'm very busy at the moment, but today is a great day.

I'd like to say I'm very proud of being, from now on, a Spring Modules committer!



Thank you very much to Costin Leau, the Spring Modules Lead, and the whole team: I'll try to do my best!

What will be my involvement in Spring Modules?

Stay tuned, I'll let you know in another post.