Monday 24 May 2010

Empowering your entities

The first thing I learnt when I started with Object-Oriented Programming was that an object should have state and behaviour. And indeed, that's how it was back then. However, since J2EE (Entity Beans) and other ORM tools like Hibernate, iBATIS, TopLink, JPA, etc, everything changed. We were so focused in mapping tables to objects, configure the relationships, lazy loading, eager fetching, primary keys and everything else that you can map and configure on the ORM tools that we simply forgot that those entities could and should also have some behaviour.

In general, for applications that use a database, the entities are the key focus of the application. They are the main components of an application's core domain and their names and methods should represent, and also help to define, a common language used by all members of the team and not just developers (See Ubiquitous Language - Domain Driven Design). 
 
Let's see a few situations where your entities could be empowered.

1. Default values / initialisation

Let's have a look at a fairly simple piece of code and see how many problems it may cause:

Listing 1.1
// Somewhere in the code 
DiscussionGroup dicussionGroup = new DiscussionGroup();
discussionGroup.setCreationDate(new Date());
discussionGroup.setLastUpdate(new Date()); 
discussionGroup.setAllowAnonymousPosts(false);

// Somewhere else in the code
if (discussionGroup.getAccess().equals(Access.PUBLIC) {
   this.displayDiscussionGroupInfo(discussionGroup);
};

Members members = discussionGroup.getMembers();
for (Member member : members) {
     // Do something
}

This code above has the following problems:
  • creationDate and lastUpdate setters being called right after creation. Let's assume both attributes are mandatory on the database. Wherever in the code a DiscussionGroup is created, we need to remember to set them both. In Failing to do so, we will get an error when persisting the entity.
  • The check to verify if the discussion group is public may throw a NullPointerException if the attribute is not initialised.
  • Like the access check, the iteration over the discussion group members can also fail if the list of members is not initialised.
  • The calling code needs to know about the internals of the entity and cater for that, like setting values to mandatory fields and also do null checks for some attributes.

To solve the problems, just initialise all the attributes you can, I mean, the ones where a default value would make sense. Always avoid having getters returning null.

Listing 1.2
// DiscussionGroup.class
public class DiscussionGroup {
    private Date creationDate;
    private Date lastUpdate;
    private boolean allowAnonymousPosts;
    private Access access;
    private List<Member> members;
    
    public DiscussionGroup() {
        this.creationDate = new Date();
        this.lastUpdate = new Date();
        this.allowAnonymousPosts = false;
        this.access = Access.PRIVATE;
        this.members = new ArrayList<Member>();    
    }
}

2. Operation that just involves an entity's attributes.

Look at the code below.

Listing 2.1
// OrderService.class
if (order.getTotal() > 0 
        && order.getOrderItems().size() > 0
        && order.getAuthorizationDate() != null 
        && order.getClient() != null) {
    this.processOrder(order);
}    

The if statement checks attributes from the order object so that it can decide if the order can be processed or not. Note that this logic is outside the order object, making the two classes tightly coupled and making a poor use of encapsulation. In this case, we could re-factor this code like that:

Listing 2.2
// Order.class
public boolean isReadyForProcessing() {
    this.getTotal() > 0 
        && this.getOrderItems().size() > 0
        && this.getAuthorizationDate() != null 
        && this.getClient() != null);
}      

// OrderService.class - Somewhere in the code
if (order.isReadyForProcessing() {
    this.processOrder(order);
}

This re-factored code makes the code more expressive, easy to read and easy to test. This also makes the code to better represent the business rules.


3. Children manipulation

Look at the listings 3.1 and 3.2.

Listing 3.1
// Add an entry to a diary.
Diary diary = new Diary();
Entry entry = new Entry();
entry.setDate(new Date()); 
entry.setText("Today I went ... ");
diary.getEntries().add(entry);

Listing 3.2
// Remove an entry from a diary.
ListIterator<Entry> entriesIterator = 
        diary.getEntries().listIterator();
Entry entry;
while (entriesIterator.hasNext()) {
    entry = entriesIterator().next();
    if (entry.getDate().equals(someDateVar)) {
        entriesIterator.remove();
    }
}

The main problem with Listing 3.1 and Listing 3.2 is that the parent class Diary is exposing its internals, the entries. Once again, this is a major encapsulation breach. As a principle, the parent should never let a stranger manipulates its children without its consent. Besides all the code duplication that this may cause, in case that I want to add/delete entry in different parts of the application (for some reason), this also makes the code to be very fragile where the parent may break since it was not notified that someone changed its children.

This could be easily fixed if we add this logic to the parent class.

Listing 3.3
// Diary.class
public Entry addEntry(Date date, String text) {
    Entry entry = new Entry();
    entry.setDate(date);
    entry.setText(text);
    this.entries.add(entry);
    return entry;
}

public Entry deleteEntry(Date date) {
    ListIterator<entry> entriesIterator = 
            this.getEntries().listIterator();
    Entry entry;
    while (entriesIterator.hasNext()) {
        entry = entriesIterator().next();
        if (entry.getDate().equals(someDateVar) {
            entriesIterator.remove();
            break;
        }
    }        
    return entry;
}

The calling code would be like:

Listing 3.4
// Add an entry to a diary.
Diary diary = new Diary();
Date date = new Date();
diary.addEntry(date, "Today I went ... ");

// Remove an entry from a diary.
diary.deleteEntry(date);

Conclusion
Entities don't need to be just dumb classes with state and no behaviour. They should contain business logic that is related to their attributes and children. This will promote encapsulation, reduce code duplication, make your code more expressive and easy to read and also much easier to test.

Sources:
http://domaindrivendesign.org/
Domain Driven Design - by Eric Evans
Clean Code - by Robert C. Martin

Sunday 9 May 2010

MVC and Multi-tier architecture

Over the years, working in different web-based Java projects, I noticed that there is a big confusion about the boundaries and overlaps between MVC, that is an architectural pattern, and a multi-tier architecture (also known as n-tier architecture). The main confusion is in identifying what is controller, what is model and what is application (business) tier. The results of this confusion, to name just a few, are:
  • Unclear design;
  • Poor re-usability (loads of copy and paste);
  • Non-cohesive classes and methods;
  • Business logic all over the place;
  • Difficult to test;
  • Difficult to measure the impact of changes and improvements;
  • And people's favourite, actions (if using Struts-like web frameworks) with hundreds, if not thousands of lines.  
I'll quickly refresh our memories about multi-tier architecture and MVC so that later we can see how they relate to each other.


Multi-tier architecture

Often called n-tier architecture, the multi-tier architecture is a logical way to separate the different responsibilities of your application. The most common multi-tier architecture is the three-tier architecture, which will be the one that I'll be focusing on.


The tree-tier architecture is divided in the following tiers:

  1. Presentation tier: It is responsible to interact with the user, displaying information and providing ways where the user can input data and perform actions. 
  2. Application tier: It is responsible for the coordination of the application, its business logic, decisions, calculations and evaluations. It executes commands, actions and moves data between the presentation and data tiers. It is also known as business tier, logic tier or middle tier.
  3. Data tier: It is responsible to retrieve and store data. Data can be stored in a database, xml, file system or even other system. It is also known as persistence tier.

Each tier must be as independent as possible from each other, where a good practice would be to provide interfaces as "facades" to each tier. Organising your classes according to these logical tiers would make the code more cohesive, loosely coupled, easier to understand and easier to test. This approach would also help to improve greatly the re-usability and would make changes to be more localised, minimising the impact on the rest of the code.

A multi-tier architecture would be for applications that access other systems (RPCs, webservices, etc), access multiple sources of data, or uses any sort of middleware.

MVC and Java MVC frameworks.

I will assume that people reading this post already know MVC so I'll give just a brief and generic description of how MVC and its variations like Model 1 and Model 2 work. If you need more information about it, please refer to the links at the end of this post.



The general behaviour of the MVC pattern is:
  1. User performs an action on the view (screen, page). This action can be anything like clicking a button, clicking a link, selecting an item from a drop down list, etc. Data may be submitted, in case of a form.
  2. Controller receives the request or event and invokes the model.
  3. Model will perform some business logic, persist or fetch some data.
  4. Model return the result of this operation to the controller. This result may include some data. 
  5. Controller, according to the result from the model, invokes the next view. The next view can be the same one that originated the request or a different one.
  6. View is rendered. The view may display any data returned from the model.
Java MVC frameworks like Struts, Spring MVC and alike are based on what we call MVC Model 2, that is a variation of the original MVC pattern.

Fitting MVC into a Three-tier Architecture

In a traditional java web application, View and Controller will belong to the Presentation tier and Model will belong to the application and data tiers.


So far so good, but when using Java Web frameworks like Struts, Spring MVC, JSF, etc, the catch is to be able to identify what is controller and what is model.  

Understanding the role of the "action" classes.

Struts was one of the first and one of the most used Java MVC frameworks. When it was released, back in 2000 (version 1.0 in 2001), many developers did not get the whole MVC Model 2 thing and very quickly started misusing the framework and sacrificing some important architectural patterns. The situation got worse when other frameworks also based on Model 2 were released, since the same bad old habits from Struts  were used to develop applications with frameworks like WebWork, Spring MVC, etc.

In Struts, when some action is performed on the page, an "action" class is invoked. This action class is probably the source of the whole problem. What exactly is this action class? I mean, what's the purpose of this class and where does it belong, taking into consideration the MVC pattern and the three-tier application?

Since the View is done by the JSPs, the Controller is done by the servlet (that is configured on the web.xml), many would answer that this class is the model. This would explain why we find so many actions with thousands of lines and full of business logic.

However, the action class DOES NOT belong to the Model.

All requests are handled by the same servlet (Front Controller design pattern), and then the respective action is called (Command design pattern). The result of this action will be the view to be displayed. So, in summary, what is the responsibility of this action class? The action is triggered by the view, does some thing and decides which view will be displayed next. This is exactly what a MVC Controller does, meaning that action classes are also part of the Controller, working almost as an extension or helpers for the main servlet.

When Spring MVC came out, one of the first things that I noticed was that they called the equivalent Struts Action class, "Controller". That's right. In Spring MVC, you create controllers instead of actions, what makes much more sense. However, even naming the classes as controllers, some developers kept adding business logic to them.


In summary, the action class must just invoke the model (could be a service, session bean, business object, etc.), get the result, set it into a context (session, request, etc) and invoke the view. Action classes should be small, clean and without any business logic, as a Controller class should be.

Component-centric frameworks and its "backing bean" classes

In component-centric frameworks like JSF, Tapestry, Wicket and alike, the pages (generally XHTML) have components that are bound to Java classes (known as backing beans in JSF). These components can be input texts, drop down lists, tables, etc, or even the entire page. Basically each component on the page can be bound to a Java class, that would behave like a model and sometimes controller for these components.The backing beans are responsible to hold the state of the components and also handle events, validation, conversions, trigger business logic, update/refresh other components, fire events, listen to events, etc.  

Now that we know that Struts Actions and Spring Controllers belong to the Controller part of the MVC, where do the backing bean classes (JSF like) belong to?

When we talk about component-centric web frameworks and also add AJAX into the mix, the line between controller and model becomes a little bit blurred.

The backing bean may handle navigation and in this case, it would act as a controller. When acting as model for its view component, although it is a model, it is a model for that specific view component. That means, the logic that this backing bean should perform would be related to rendering the view component or invoking other view components (events, re-render, etc) and not exactly application business logic, keeping this managed bean coherent. Any application business logic like making calculations, fetching or storing data, make a web service call, etc, should be delegated to a business class belonging to the application tier.

So in the case of a component-centric framework, managed beans would belong to the presentation tier, even being models for view components.


NOTE: All classes related to the java web frameworks like validators, converters, forms, etc, also belong to the Presentation tier.

Summary

When developing applications it is important to keep your code cohesive and loosely coupled. The first step is to make a quick analyses and define the logical tiers. In case of a web application with database access, it will not differ too much from a three-tier architecture. If integrating with other systems or accessing multiple data sources, application and data tiers may be broken down into more tiers.

When using Java web frameworks, regardless if they are page-centric (Struts like) or component-centric (JSF like), chances are that everything related to the framework (forms, converters, validators, actions, controllers, managed beans, etc) will belong to the presentation tier and should not have business logic. Business logic and data access should be delegated from the presentation tier to the application tier. This would allow us to keep our managed beans and actions (controllers) very small and clean.

In case of too much view logic (enabling/disabling components, populating tables and drop down lists, validations, etc), use helper classes for the actions and managed beans (see View Helper design pattern)   

For the model, application and data tier, they will be covered in future posts since they can vary a lot from application to application.


Source
http://en.wikipedia.org/wiki/Multitier_architecture
http://en.wikipedia.org/wiki/Model-view-controller
http://java.sun.com/blueprints/patterns/MVC-detailed.html
http://www.ibm.com/developerworks/library/j-jsf1/
http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html
http://java.sun.com/developer/technicalArticles/J2EE/despat/
http://java.sun.com/blueprints/corej2eepatterns/Patterns/ViewHelper.html