Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question

2 Answers 2

up vote 16 down vote accepted

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.

share|improve this answer
    
can you elaborate on "other bad design decisions" ? –  kevin cline Apr 21 '11 at 20:38
    
Thanks. I have not found these issues to be a problem in Ruby on Rails development. It is still possible to test behavior and persistence separately. IMO separating persistence from behavior has little practical value. –  kevin cline Apr 26 '11 at 13:18
    
@kevin: these things are less of a drawback with ruby features like mixins and duck typing. With static languages -- like C# which is what the OP used in his question -- it is a bit more difficult to separate the two. –  Wyatt Barnett May 24 '11 at 13:18
    
@Wayne: to me, classes are just boxes to put methods in -- I can separate business logic from persistence by putting them in separate classes, or I can just separate them conceptually by making sure that the business methods don't do I/O. In languages with poor delegation support (e.g. Java), this saves a huge amount of code. OTOH, I'm just getting into Hibernate so I could be completely wrong. –  kevin cline May 25 '11 at 6:02
    
What alternative is there to the antipattern ? –  Taiko Jun 13 at 2:36

The biggest drawback to active record is that your domain usually becomes tightly coupled to a particular persistence mechanism. Should that mechanism require a global change, perhaps from file-based to DB-based persistence, or between data access frameworks, EVERY class that implements this pattern may change. Depending on the language, framework, and design, even something so simple as changing where the DB is located or who "owns" it might require going through every object to update the data access methods (this is uncommon in most languages that provide easy access to config files with connection strings).

It also generally requires you to repeat yourself. Most persistence mechanisms have a lot of common code, to connect to a DB and start a transaction. DRY (Don't Repeat Yourself) would tell you as a coder to centralize such logic.

It also makes atomic operations tricky. If a group of objects must be saved in an all-or-nothing fashion (such as an Invoice and its InvoiceLines and/or Customer and/or GL entries), either one object must know about all these other objects and control their persistence (which stretches the scope of the controlling object; large interconnected records can easily become "god objects" that know everything about their dependencies), or the control over the entire transaction must be handled from outside the domain (and in that case why are you using AR?)

It's also "wrong" from an Object-Oriented perspective. In the real world, an invoice doesn't know how to file itself, so why would an Invoice code object know how to save itself to the DB? Of course, overly religious adherence to "objects should only model what their real-world counterparts can do" would lead to anemic domain models (an invoice also doesn't know how to calculate its own total, but splitting the calculation of that total to another object is generally considered a bad idea).

share|improve this answer
    
In Ruby, where persistence may be defined or abstracted behind a very simple keyword or command, it's probably less of a problem. In .NET, which requires more LoC to set up various persistence mechanisms, it is usually redundant to have a SQL connection for each object, especially if multiple objects must be saved in one atomic transaction. Connecting to the DB looks the same whether you're saving an Invoice or a Customer. You would either abstract the common stuff into a base class common to all ActiveRecord objects in your codebase, or extract it to its own class (a Repository) –  KeithS Sep 16 '11 at 20:14
    
can you provide examples of Ruby ActiveRecord usage that illustrate your points? I did not experience these problems, but my application was fairly small. I could write migrations in Ruby, and deploy them to differing DB implementations. I found that Ruby's ActiveRecord was very useful in eliminating repetition, so I don't see why you would assert that using ActiveRecord would have the opposite effect. I did not have problems with saving: I just modified the object model, and let AR update the DB to reflect the object model. –  kevin cline Sep 16 '11 at 20:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.