Abstract

Persisting domain objects is one of the most challenging aspects of designing a flexible and testable enterprise application. There are lots of examples, in the industry, when developers get it wrong and end-up either with an effectively procedural, non-object-oriented structure and/or a highly complicated, tightly coupled design which is hard to unit-test.

Persistent Domain Objects Pattern gives a solution to resolve tight-coupling of the persistence and application logic code. PDOP decouples those by extracting the details of the persistence implementation and hiding it behind an interface, employing Dependency Injection techniques. As a result, domain objects do not need to know or worry about the details of the persistence code and can concentrate on their main task - delivering encapsulated data and behavior that models the domain under question. It, also, makes domain objects, much easier to unit-test in isolation from its dependency - persistent storage (e.g. database). Effective unit-testing increases the quality of a programming code and its extensibility.

Scope

Domain Model, Persisting Domain Objects.

Problem Definition

The core of most applications is their Domain Model. A Domain Model defines business rules (behavior) and the data that the business rules apply to. The behavior and the data are encapsulated into objects that form a hierarchy and can interact with each-other, thus effectively modeling the domain reality. For a wide-range of applications this Object-Oriented way of modeling the real-life scenarios works with the best, most effective approximation possible.

Usually, humans desire to interact with the model, in one way or another: influence the system or get a glimpse of what is going on. This is achieved via a View layer. Since the business rules (Model) change far less frequently than the user interface to the system (View), there is, often, a requirement of being able to change View without disturbing the Model. The requirement can be satisfied by decoupling Model and View through the introduction of a Controller. This brings us to the infamous Model-View-Controller (MVC) pattern.

If we could just start-up an application in-memory and guarantee that it always stays there, the above would be as much as we would have to worry about. Alas, that’s not the case. We have to periodically (or constantly) backup a snapshot of the system’s state into some kind of persistent storage. This way we can restore the state from the backup, if needed, or share it with others. The motivation and mechanisms, for the persistence, can be numerous and different but it is, almost, always necessary.

In fact, the persistence is so important that some people begin with the design of the persistent storage (e.g. DB tables) and end-up with an Anemic Domain Model and a separate “Service Layer” consisting of queries to the persistent storage. Martin Fowler et al. have identified it as an anti-pattern. Such tight coupling of the application code and the persistence one, makes it very hard to unit-test your application - makes application code less reliable and extensible.

Solution

One solution to the defined problem is to abstractly extract the concrete implementation of the persistence code out of the Domain Model. Basically: decouple the persistence from the application code. By decoupling, besides making our application much easier to unit-test, we will, also, make it more flexible - different persistent storage mechanisms (LDAP, DB, plain files, XML etc.) can be swapped-in on-demand, without affecting the application code and logic.

While we do this, we have a supplemental goal: we want to keep the implementation simple. One way of achieving the goal is to declare persistence as a dependency of a domain object. We can introduce a Manager interface that our domain object depends on for all its persistence needs.

Concrete implementations of Manager can be registered with the appropriate entities using Dependency Injection; so that the entity itself never needs to know the specific implementation used.

Sample Code

In this sample, we will look at a Blog entity. For the purpose of this demo, we will use the Context IoC introduced by Sony Matthew. The reason why we choose it over the Constructor or Setter Dependency Injection is to make example code simpler.

Let’s look at the Blog interface. Please, note that the only addition to the interface, that would not be present in a “pure” domain object, is the declaration of the interface for the persistence dependency:

public interface Blog {

  public interface Manager {
    //-- The argument to the load() method is entity's PK\
    public Blog load( String name );
    public void save( Blog blog );
    public void remove( Blog blog);
  }

  //-- The rest of the Blog interface goes below\
  // .....
}

Implementation:

public class BlogImpl implements Blog {

  private static Blog.Manager manager = null;
    public static Blog.Manager getManager () {
      return BlogImpl.manager;
    }

    public static void setManager ( Blog.Manager manager ) {
      BlogImpl.manager = manager;
    }

    public BlogImpl() {
      // ..
    }

    private String name = null;
    public String getName() {
      return this.name;
    }

    public void setName( String name ) {
      this.name = name;
    }

    //-- Below go any other properties and methods relevant\
    //-- to the Blog entity as a purely Domain Object.\
    //.....\
 }

In the above example, the primary key of the Blog entity is the name property. One of the manager implementations can have an implementation that looks like the following:

public class BlogManagerImpl implements Blog.Manager {

  public BlogManagerImpl() {}

  public void save( Blog blog) {
    //-- Save the state of the Blog object, into a database
  }

  public Blog load( String name) {
    //-- Load the Blog instance from a database.
    //-- e.g. using hibernate:
    //-- return (BlogImpl) session.load( BlogImpl.class, name );

    //-- this is just for the demonstration purposes
    BlogImpl blog = new BlogImpl();
    blog.setName ( name );

    System.out.println ( "Loaded blog: " + blog.getName() );
    return blog;
  }

  public void remove( Blog blog) {\
    //-- Remove the persisted state of the object from the
    //-- database..
  }

}

and, finally, the following is how your application may use all of the above to load two blogs:

public class Main {

  public static void main(String[] args) {

    Blog blog, blog2;

    Blog.Manager blogManager = new BlogManagerImpl();
    BlogImpl.setManager( blogManager );

    blog = (BlogImpl) BlogImpl.getManager().load ( "John" );
    blog2 = (BlogImpl) BlogImpl.getManager().load ( "Joanna" );
  }
}

each call to the getManager().load() will load an entity from a database. For the purposes of this demo, it, also, displays a message.

Conclusion

Using the PDO pattern, we have extracted the persistence code details out of the Blog entity. This made Blog entity more object-oriented. By decoupling its dependency (a database, in this case) from the entity, we made unit-testing the entity much easier. Better unit-testing delivers more reliable, extensible code and significantly improves the overall design.