Struggling for Competence

Active Record verses Repository

This post compares the Active Record and Repository patterns; probably the two most popular data access patterns in use today. Let me put my cards on the table. Every project I've worked on has used the Active Record pattern. Some of these projects have been designed by me, and some by other folks. But either way, we've really struggled to unit test the object which were mapped to the database. We just could not substitute the data access layer during unit test. This is because the Active Record pattern is fundamentally untestable.

Fowler defines the Active Record pattern in Patterns of Enterprise Application Architecture:

An object that wraps a row in a database table or view, encapsulates the data access, and adds domain logic on that data.
active-record

The picture shows a fairly typical active record style class. Its got some business logic methods which aren't shown. It's got instance methods for insert, update and delete. And its got some static "get" methods for creating objects from database records. The Get(id) method returns a single object with primary key id. GetAll() returns a list of all the objects. And GetByFK() makes a list of objects based on a foreign key id.

So what's the problem when it comes to testing?

So, Active Record, by its nature it does not support testing. With a herculean effort, you might get some tests in - but you won't have much fun doing it.

The previous couple of posts have looked at a simple implemetation of the repository pattern, and how do genuine unit testing with the repository pattern. The repository pattern looks something like this:

repository

In the Repository pattern all of the data access is put in a separate class and is accessed via instance methods. To me, just doing this is beneficial, since data access is now encapsulated in a separate class, leaving the business object to get on with business. This should stop the unfortunate mixing of data access and business logic you tend to get with Active Record.

The big benefit comes though when you test. It's simple to put an interface on the repository, and then for testing, replace with a fake repository. The fake repository can be primed, during the arrange stage of the unit test, with objects for use in the test. The update, insert and delete methods just need to record what happened during the test.

So the big advantage of the repository, is its inherent testability. The unit test are easy to write when you use a repository interface with dependency injection. It's inherent goodness, does not however translate into popularity. In a googlefight, Active Record beats Repository hands down. Clearly the battle for testable architecture has not yet been won.