Design Patterns – Drawbacks to the ActiveRecord Pattern

design-patterns

I'm curious what are the drawbacks to using the ActiveRecord pattern for data access/business objects. The only one I can think of off the top of my head is that it violates the Single Responsibility Principle, but the AR pattern is common enough that this reason alone doesn't seem "good enough" to justify not using it (of course my view may be skewed since often none of the code I work with follows any of the SOLID principles).

Personally I am not a fan of ActiveRecord (with the exception of writing a Ruby on Rails application, where AR feels "natural") because it feels like the class is doing too much, and data access shouldn't be up to the class itself to handle. I prefer to use Repositories that return business objects. Most of the code I work with tends to use a variation of ActiveRecord, in the form of (I do not know why the method is a boolean):

public class Foo
{
    // properties...

    public Foo(int fooID)
    {
        this.fooID = fooID;
    }

    public bool Load()
    {
        // DB stuff here...
        // map DataReader to properties...

        bool returnCode = false;
        if (dr.HasRows)
            returnCode = true;

        return returnCode;
    }
}

or sometimes the more "traditional" way of having a public static Foo FindFooByID(int fooID) method for the finders and something along the lines of public void Save() for saving/updating.

I get that ActiveRecord is typically much simpler to implement and use, but it seems a little too simple for complex applications and you could have a more robust architecture by encapsulating your data access logic in a Repository (not to mention having it easier to swap out data access strategies e.g. maybe you use Stored Procs + DataSets and want to switch to LINQ or something)

So what are other drawbacks to this pattern that should be considered when deciding if ActiveRecord is the best candidate for the job?

Best Answer

The main drawback is your "entities" are aware of their own persistence which leads to a lot of other bad design decisions.

The other issues is that most active record toolkits basically map 1 to 1 to table fields with zero layers of indirection. This works on small scales but falls apart when you have trickier problems to solve.


Well, having your objects know about their persistence means you need to do things like:

  • easily have database connections available everywhere. This typically leads to nasty hardcoding or some sort of static connection that gets hit from everywhere.
  • your objects tend to look more like SQL than objects.
  • hard to do anything in the app disconnected because database is so ingrained.

There ends up being a whole slew of other bad decisions on top of this.

Related Topic