Active Record Design Pattern - Domain Driven Design and Domain Layer - Object Persistence

Active Record Design Pattern - Domain Driven Design and Domain Layer - Object Persistence

by David Hayden ( .NET Developer )

Filed: Design Patterns

 

During the last couple days I have been sketching out a design for a new blogging engine for my website. I decided to create my own blogging application, because 1) it is incredibly simple and 2) I enjoy blogging and wanted a bit more control over a hobby that I planned to spend more time on.

After sketching an Entity-Relationship Diagram, some simple use cases, and a domain model, I have come to the conclusion that my blogging engine persistence needs are best served by the Active Record Design Pattern.

 

Active Record Design Pattern

The Active Record Design Pattern is a widely used design pattern for forms-over-data applications that have few business rules and very much a 1:1 ratio between business objects and database tables. An Active Record Object represents a single row in a database table and persistence is not looked as a service, but more as a responsibility of the business objects themselves. Since there are very few if any business rules, there is very little need for additional persistence layer objects (other than a simple dataprovider ) to keep a clear-cut separation of concerns. Developers who accept the Active Record Design Pattern as a solution in their toolbox are not religiously tied to preferences of POCO ( Plain Old CLR Objects ) and the need for a clear separation of persistence when the business objects are doing little of anything else.

As I mentioned above, the Active Record Design Pattern is most ideal when you have a 1:1 relationship between business object properties and table properties and the needs of a Data Mapper are un-necessary. In the case of something as simple as a Post ( and other domain objects ) in a blogging engine, there is basically a 1:1 relationship:

 

 

Since we have such a simple relationship between the Domain Model ( Object Model ) and the Relational Model, we do not require the needs of a Data Mapper. And, since I can only think of very few business rules for my blogging engine, I will add the persistence logic directly to the domain object itself to avoid the un-necessary overhead of separate persistence layer objects when they are not necessary. Although I agree with the idea of separation of concerns and a layered architecture, this is most important when persistence is a service and I want to remove the persistence functionality from the domain objects as it distracts the intent of the objects. In my case, there is very little intent of the domain objects other than to retrieve and persist from the underlying datastore :)

 

Persistence Is A Responsibility in Active Record

With the Active Record Design Pattern we will focus on persistence as a responsibility rather than as a service. Normal CRUD operations will now be mapped to static and instance methods on the domain object. Shown below are some examples of persistence methods that may occur on my Post Active Record Object:

 

int Save();
int Update();
int Delete();
static Post FetchbyId(int id);
static PostCollection FetchByBlogId(int blogId);

 

Methods like Save, Update, and Delete are typically instance methods while Finder Methods like FetchbyId or FetchByBlogId are often static methods. You could separate out the Finder Methods to a separate class since they are not specific to an instance. In the case of my blogging engine there are very few Finder Methods, so let's keep them on the domain object to keep things nice and simple.

 

Data Mapping Inside Domain Object

When reconstituting a domain object from the persistence store ( database ), we can often get away with a constructor or a method to map object properties to table columns since the mapping between object properties and database columns is essentially 1:1. Here is an example of a private constructor that accepts a DbDataReader to reconstitute the object:

 

private Post(DbDataReader dr)
{
    _id = dr.GetInt32("PostId");
    _title = dr.GetString("Title");
    _abstract = dr.GetString("Abstract");
    _description = dr.GetString("Description");
}

 

Making the constructor private better conveys the intention that this constructor is only to be used by static Finder Methods to reconstitute domain objects from persistent storage.

 

public static Post FindById(int id)
{
    Post post = null;
    
    using (DbDataReader dr = _dataProvider.ExecuteReader(...))
    {
        if (dr.Read())
            post = new Post(dr);
    }
    
    return post;
}

 

Conclusion

The Active Record Design Pattern is a very elegant domain model solution when you have few business rules with a fairly simple 1:1 mapping of domain objects and database tables. If your solution can also look as persistence as a responsibility as opposed to a service and you understand that a separation of concerns is mainly only necessary when your domain objects are busy with many rules, I encourage you to look at the Active Record Design Pattern as a tool in your toolbox.

Source: David Hayden ( .NET Developer )

Filed: Design Patterns

 

posted on Saturday, June 10, 2006 10:28 PM

Main

News

Green Tea

.NET Development

Enterprise Library

Patterns & Practices