March 1st, 2015
(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: email@example.com
The pattern (or one might say the way it is implemented) has several issues:
It (seriously) violates SRP. In a typical implementation of the pattern you will have the following set of methods and properties in every class:
Getting the data from database.
Instantiating a new instance in memory for inserting it into the database.
Saving changes to the database.
Loading related entities.
Usually loads of methods (inherited from the base framework class) to deal with all the complexity involved with the above-mentioned methods.
Column related properties: there will be at least one property generated per column.
Also frameworks usually provide several overloads of each method to enable you to handle every possible scenario. And then of course there is the business logic that you put into this class.
No POCO. I have yet to see an implementation of the pattern with POCO support, and it just makes sense. Due to the complexity of the pattern there is a load of methods implemented by the framework which your class inherits from.
One to one mapping between table structure and entity that is for each column in the table there is one property on the entity (Most ORMs allow you to hide some columns on your entity).
Database is very nicely abstracted away which is a good thing; but this also means accessing a property could cause a database hit. In fact, due to the simplicity, a lot of developers tend to forget that they are working with a row in database. One typical mistake I have seen is applying some logic on the object in a foreach loop not knowing that each iteration hits the database.
In my experience unit testing Active Record entities is next to impossible. Active Record entities have a lot of infrastructure to make them interact with the database easily. You use a property on your entity and it wants to hit the database. This makes unit testing very hard (in my experience impractical); so you are left with one option that is integration testing.
Active Record gone crazy
As mentioned above in most cases your application is not that simple so this pattern quickly becomes an anti-pattern:
You start with a big application, you have limited time, and there it is the framework in the shelf that could help you deliver “value” very quickly. So you think: “yeah, this is a simple forms over data. Let’s just generate some entities from the schema and bind them to the UI”. Two months later, you have a lot of UI elements bound to your active record entities, inevitably you have implemented lots of validation rules in them plus binding and UI related logic. In fact your entity kind of has to know how it is being displayed on the UI as it has UI related validation logic/messages with binding attributes all over it. You just managed to merge all the architectural layers into one class and your project will turn into a BBOM quickly. It is also no longer the class that you have generated once and no longer touch. In fact everything – including UI, business and validation logic – is in that class and most of your changes end up in that class one way or another.