The Problem With Active Record

May 5th, 2009 · 21 Comments ·

By John Januszczak

The Active Record pattern has gained a lot of attention lately, particularly because of it’s use in the wildly popular Ruby On Rails (“RoR’) framework. Other frameworks which employ the Active Record pattern include the Castle Project, which aims to simplify the creation of enterprise and web applications for .NET developers. If you are new to the Active Record design pattern, it is an object-relational mapping and object persistence pattern for binding business objects with database records. Specifically:

Active record is an approach to access data in a database. A database table or view is wrapped into a class, thus an object instance is tied to a single row in the table. After creation of an object, a new row is added to the table upon save. Any object loaded gets its information from the database; when an object is updated, the corresponding row in the table is also updated. The wrapper class implements accessor methods or properties for each column in the table or view.

Source: Wikipedia

Therefore, typical implementations of the Active Record pattern consist of instance properties representing a record’s fields in the database, instance methods that act on that specific record and static methods acting on all records, i.e. the database table or view. David Hayden gives a nice overview of how this pattern might be implemented in his article Active Record Design Pattern – Domain Driven Design and Domain Layer – Object Persistence.

Problems

I would hazard to guess that almost anyone who has developed web applications with Ruby On Rails would testify to the utility and even aesthetics of the Active Record pattern. For the record, I share this admiration. However, I can see problems lurking inside of the various implementations, in terms of both design principles and testability.

Problem #1: Static Methods

As mentioned above, each Active Record class maps to a corresponding database table (or view), and each instance of such a class maps to a record in that table. So, to create a new Account record you might do the following (I’ll use c# syntax):

Account newAccount = new Account();

You then might set some field values and save it:

newAccount.Name = "Joe";
newAccount.Save();

However, if you want to get an account from the database you use a static method (because you are querying the whole table, not a specific record, to find it):

Account joesAccount = Account.Find("Joe");

Some would say using Static methods simply amounts to procedural programming, and therefore is poor Object Oriented design. Others would say static methods are death to testability.

Problem #2: Global Configuration Settings

In our example above, the Account class needs to connect to a database (or some source). You will find that most Active Record implementations have some kind of application config file. For example, Ruby On Rails uses a YAML file to persist the application’s database connection settings. Therefore there is no dependency injection on the Account class in my example, and by extension, on the Account instances.  As we should all know by now, looking for things is very, very bad!

Towards A Better Active Record

A better pattern might still include classes that represent the various database tables, but instead define separate logical state containers to represent the table’s records. Logical state containers are classes that simply define a set of fields with associated accessor methods/properties – you can almost think of it as a glorified struct.  The classes that represent the tables would be instantiated by passing the connection settings to its constructor:

AccountTable accounts 
  = new AccountTable(myConnectionSettings);

We can now query the instance of the database table that corresponds to our connection settings to retrieve records in the form of a simple logical state container:

AccountRecord joesAccount = accounts.Find("Joe");

Updates to the database would be done by passing instances of the proposed logical state containers into instance methods of the table classes:

joesAccount.Name = "Joe Jr.";
accounts.Save(joesAccount);

Separating responsibilities for the table and the records into two separate classes provides a better design and a decent shot at genuine testability.

Tags: Uncategorized

21 responses so far ↓

  • Sai Venkat // May 6, 2009 at 12:08 am

    Good point. I have similar reactions but from a different point of view about ActiveRecord. Wrote about here http://sai-venkat.tumblr.com/post/101030289/activerecord-domain-model

  • Filip Navara // May 6, 2009 at 12:23 am

    What you described is actually an existing design pattern called “Repository” if I am not mistaken. It was described by Martin Fowler and others.

  • Adam Pohorecki // May 6, 2009 at 12:50 am

    Isn’t the “better Active Record” you described the Data Access Object (DAO) pattern?

  • Jani Hartikainen // May 6, 2009 at 7:59 am

    I think the Doctrine ORM for PHP uses this kind of “better ActiveRecord” as they have a separate table object

  • John Januszczak // May 6, 2009 at 2:42 pm

    @Sai, thanks for the link and the other perspective.@Filip, Adam, & Jani, thanks for pointing out the other patterns and frameworks that implement, at least what I feel is, the better design. My main goal was to point out potential design and testability issues with Active Record. The ways to address these issues seem to manifest themselves and hence my suggestions. I really didn’t go looking for an alternative pattern that did what I was suggesting – I just wanted to point out how one might be constructed. I think I’d me more surprised if patterns like the ones you pointed out did not exist.

  • Marius // May 7, 2009 at 1:48 am

    In ruby classes are just objects. So the find method on an ActiveRecord class is just an instance method for the ActiveRecord object.
    It’s also possible to have different settings for each AR class.

  • Igor Brejc // May 7, 2009 at 4:42 am

    Wouldn’t it be even better to have an interface for active record instead of a concrete class? You could still have DI with it and keep the Save method:IAccountRecord joesAccount = accounts.Find(“Joe”);joesAccount.Save();

  • GR // May 7, 2009 at 4:14 pm

    I find it kind of humorous that you refer to various ‘implementations’ (plural) of ActiveRecord.There is only one, and it is ActiveRecord for Ruby.  You can’t lump other ORM’s which may be similar to ActiveRecord for other frameworks into one group that you can talk about homogeneously.Don’t you think it also odd that you are talking about ActiveRecord and its supposed ‘testability’ problems, yet all your code examples are in C# and you give no concrete examples of a testability problem?Have you used the various testing frameworks available to Ruby/RoR apps?  I have not seen any discussion about problems testing real world apps due to the flaw you find so apparent.

  • Joe the coder // May 8, 2009 at 4:32 pm

    This is nothing but Dao or repository concept. Another way to address the same problem.

  • misko // May 9, 2009 at 3:36 pm

    @Marius,

    yes I know that in Ruby, classes are objects. But that makes them Global, which is fine as long as you are not mutating them. So the problem is that if you want to Mock out static method Employee.FindByName, you need to override the global space. Which means that all tests after your will now get the overridden method. This is global state and is no different to having global variables. Hence undesirable.

  • misko // May 9, 2009 at 3:40 pm

    @Igor,

    If you want to have Save on Account class rather than Account Table, than the Accounts needs to have a reference to AccountsTable. This means that some of Account class fields will be persisted and some will not. This is mixing of concerns. Check out: http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/

  • misko // May 9, 2009 at 3:43 pm

    @GR,

    I think the point of the article was that any implementation which has static methods on the classes for persistence is a bad Idea. Those that separate it to two classes one for the table and one for row are much more testable.

  • Toby Hede // May 9, 2009 at 10:42 pm

    I am a bit puzzled about critiquing one language using another. Static methods on a class may create “testability concerns in other languages, but I have never encountered any issue like this in Ruby/Rails.Using rspec you can mock methods (static and otherwise) within a single test case without effecting other  tests in your system. There are other mocking frameworks in the Ruby space that behave similarly.Similarly with the configuration – Rails uses the YAML settings as a convention but it is not required for testing ActiveRecord.

  • Weekly Links #52 | GrantPalin.com // May 10, 2009 at 2:10 pm

    [...] The Problem With Active Record Interesting critique of the Active Record data access methodology. [...]

  • misko // May 10, 2009 at 3:17 pm

    @Toby,

    The testability issues are universal. But lets look at ruby

    1) Static methods are hard to override in Java, but easy in Ruby. Overriding the method is equivalent to changing global state since you have to clean up after-yourself. In ruby you have nice frameworks to do that for you, but it is global state any ways, which means you can never run things in parallel. So if ruby ever gets multithreaded you are in trouble. Also you can only override the method for everyone, while in instance method you con override it per instance. So for example if you have a chain of responsibility pattern you will have hard time testing it since you have just overridden the methods for everyone in the chain.
    2) Static methods do not make it clear where the configuration is coming from which causes your API to lie to you: http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
    3) Static methods are not OO, they are procedural. There is nothing wrong with procedural, but if your language of choice is OO, why are you writing procedural code.

    Just because ruby has figured out clever frameworks to test static methods, it does not make it a good idea.

  • VaNTa // May 11, 2009 at 7:04 am

    I also think that there are another words for DAO pattern. Misko, what You say? :)  

  • Marques Johansson // Jul 17, 2009 at 4:26 am

    Can’t you move your Blog to Blogger so your blog is more reusable ;-) .. At least implement Google Friend Connect or something..

    One of the niceties of some ActiveRecord implementations, is that the creation of an object will cause all of the necessary database table meta data to be resolved:

    abstract class ActiveRecordXYZ {
    protected $schema; // db name
    protected $table; // db table name
    protected static PDO $defaultconn;
    protected PDO $conn;
    protected static $metadata; // sql field types and other meta data

    public static setConnection(PDO $pdo) {
    return static::$defaultconn = $pdo;
    }

    public static getConnection() {
    return static::$defaultconn;
    }

    public __constructor() {
    $this->conn = self::getConnection();
    if (! $this->tablename) {
    $this->tablename = $this->guessTablename();
    }
    }

    protected function guessTablename() {
    .. regex get_class($this) …
    }

    public fetchMeta() { .. self::$metadata = …; done once per class at first use .. }

    public __get() {…$this->fetchMeta()…}
    public __set() {…}
    public load() {…}
    public save() {…}
    }

    class DBX extends ActiveRecordXYZ {
    protected $schema = ‘dbx’;

    public static getConnection() {
    if (! parent::getPDO()) {
    $pdo = PDOFactory::getConn(‘dbx_host’);
    return self::setConnection($pdo);
    }
    }
    }

    class DBX_TableY extends DBX {}

    $user = new DBX_TableY; // PHP now
    $user->load(array(‘id’=>123));
    $user->name .= ‘ Jr.’;
    $user->save();

    Everything is still testable and mockable and all run-time dependencies are optional. Do you agree?

    The getter/setters here are really tied to the Table class (as you put it), and I can’t justify breaking them out which would only seem to add more complexity with no practical advantage.

  • Marques Johansson // Jul 17, 2009 at 4:28 am

    sorry – ‘class DBX’ should be ‘abstract class DBX’

  • misko // Jul 20, 2009 at 1:25 pm

    @Marques,

    So how would you create XYZ without a database and without resorting to Global Variable Magic?

    If I do new XYZ() that how does $conn get set? From static GetConnection() method which resorts to global state. Not liking it :-(

  • Marques Johansson // Jul 21, 2009 at 8:27 am

    In some environments, config files may be used to define the default database connection and a registry might store that connection. I hear you grumbling about that already, as being hidden code.

    In this case, however, the static getConnection method inherited from the database class DBX by the Table_ABC class falls back to a PDOConnection factory where connection settings are stored as constants or retrieved from files, Apache environment, whatever.

    My database object knows about its dependency on a connection to a particular db host + schema and this ability is passed on to the extending table objects. This relationship is an implicit part of the model – a database object is a connection to a server/db.

    And yet, it can still be overridden with setConnection() for testing or custom purposes.

  • Ian Dunn // Jul 13, 2012 at 9:47 am

    I’m new to this, but it sounds like your “better Active Record” pattern is closer to the Data Mapper pattern than to the traditional Active Record pattern.

Leave a Comment