Randolph Cabral’s Weblog

…beauty is just a dimmer switch away…

Active Record Vs. Unit of Work

Posted by Randolph Cabral on Thursday, April 3, 2008

Lately, I’ve been doing some research on which path to take – Active Record or a pure Domain Model using the Unit of Work pattern.  Clearly there are advantages and disadvantages to both.  I’m hoping to find a good compromise between simplicity and flexibility.  When I say ‘simplicity’, I’m talking about the ever-elusive ‘elegant solution’ where we are free from framework traps and anemic domain models.  As for ‘flexibility’, I’m referring to the ability to quickly change delivered functionality without having to rip apart the guts of the existing code base.  The thing that I keep getting hung up on is deciding which of the two best fits these goals.  I’ve used both approaches and like them both, but this is one of those debates that has no clear winner.  Let’s take a closer look at each approach.

The Active Record Pattern

In this model, an entity and its properties are directly mapped to a database table and its columns.  Additionally, every entity is implemented with its own insert, update, delete and select (CRUD) behaviors.  Method names like Save, Delete and Load are commonplace with many Active Record implementations.  Rounding out the package adds various static methods that expose query capabilities to allow filtering.  Having these behaviors included with the entities provides a convenient way of persisting state back to a data source.  I have used this pattern a lot and have had many successful projects that I credit the pattern for.  Needless to say, as with most solutions, it isn’t perfect.  There are a few cases where this pattern can create some interesting challenges.

Consider this case:  Cardinality, A.K.A. relationships with other entities.   Think of the classic customer and order example.  A customer can have many orders which is to say that the customer object has a one-to-many relationship with order objects.  Remember, the Active Record pattern exposes public Save methods on both the customer object and the order object.  What would you expect to happen when you call the Save method on the customer object?  Certainly the customer object will be saved to the database, but what about the orders?  If you’re using Ruby’s Active Record implementation, the orders that are associated with the customer object may or may not be saved depending on whether the customer’s Save method call is an initial or subsequent call.  Using Jammer.NET’s implementation, the associated orders are not saved at all.  The developer must take action by either modifying the Save method on the customer object to handle cascade saving or by calling the Save method on the orders collection manually.

The Unit of Work Pattern

According to Martin Fowler’s anemic domain model anti-pattern, the domain model should only have objects that are named after the nouns in the domain space and connected to each other with rich relationship structures.  Furthermore, the behaviors of each object should model only those rules that are domain space specific.  This means that the Active Record pattern violates this rule because CRUD behaviors are forms of data store persistence logic not domain space logic.  Going by this definition, we must implement persistence using the Unit of Work pattern.  Two great examples of this pattern is implemented by Hibernate and Microsoft’s LINQ to SQL technology.  Hibernate and LINQ to SQL take a sort of hybrid approach which combines both the Active Record pattern’s metadata mapping and the Unit of Work pattern.  This hybrid approach creates a very clean model for handling persistence regardless of cardinality between entity objects.  Using LINQ to SQL, the entities, for the most part, adhere to the notion of POCOs which are persistence ignorant.  Great right? Unfortunately, as with the Active Record approach, this model is also not without its challenges.

Consider this case: Objects that become disconnected from its Unit of Work container.  Let’s assume that you are writing a web application and you’re coding up a three step registration wizard.  Ideally, having the UoW container stay in scope through completion of the wizard is preferred.  Unfortunately, that may not be the best idea if your application needs have as light a footprint on memory usage as possible.  Considering this, you decide to let the UoW container go out of scope once your business objects are loaded causing the business objects to become disconnected.  Finally, the registration wizard reaches its last step which is to persist the state of the registration business object to the data store.  Because the UoW container got garbage collected a new container instance must be created and the business object must be re-attached.  I know what you’re probably thinking, “This logic is not so hard to write.  Why all the heartburn?”  The problem I have is with the additional lines of code that must be written to re-attach the entities.  These lines of code are entirely house keeping items that, in my opinion, muddy up the code.  In my opinion, this pattern also does not code as naturally as the Active Record pattern.  However, I do think it’s the better pattern in the sense that related entities are automatically handled by the UoW container.

Sound Off!

So what do you think?  Which pattern gets your vote?  Have I missed anything?  Help me to choose which way to go.  I’m sure this debate will likely live on for many years and I look forward to hearing from all of you.

Advertisements

2 Responses to “Active Record Vs. Unit of Work”

  1. […] Active Record Vs. Unit of Work […]

  2. […] Active Record и Domain Model. Неплохая аргументация приведена вот тут. Скажу ещё в дополнение пару […]

Sorry, the comment form is closed at this time.

 
%d bloggers like this: