Active Record pattern used in Rails, Hibernate, and many other ORM tools is a data persistence pattern that allows mapping database rows to objects. This useful tool, however, is a source of confusion according to Bob Martin. “A 1:1 correspondence between tables and classes, columns and fields” is based on the presumption that tables and objects are similar, whereas, in fact, programming style oriented around data and OOP have virtually opposite characteristics.
Objects hide data and expose behavior because public interface is built around methods. Data structures expose data and have no behavior because they typically don’t contain business rules. Hence, objects and Data structures don’t have same immunities and vulnerabilities. Objects are immune to the addition of new types - because in OOP, algorithms don’t have any information about the kind of object they are dealing with” – but they are not immune to the addition of new functions:
The old example: shape.draw(); makes the point. The caller has no idea what kind of shape is being drawn. Indeed, if I add new types of shapes, the algorithms that call draw() are not aware of the change, and do not need to be rebuilt, retested, or redeployed.
[…]
By the same token, if I add new methods to the shape class, then all derivatives of shape must be modified.
Algorithms that use data structures are, on the contrary, immune to the addition of new functions but vulnerable to the addition of new types:
Now consider an algorithm that uses a data structure.
switch(s.type) {
case SQUARE: Shape.drawSquare((Square)s); break;
case CIRCLE: Shape.drawCircle((Circle)s); break;
}
[…]
Consider what happens if we add a new set of functions, such as Shape.eraseXXX(). None of the existing code is affected. Indeed, it does not need to be recompiled, retested, or redeployed.
[…]
By the same token if I add a new type of shape, I must find every algorithm and add the new shape to the corresponding switch statement.
According to Bob Martin, using Active Record pattern results in a confusion typical for this “impedance mismatch between relational databases and object oriented languages.” He argues that even though “Active Record appears to be an object”, it “is meant to be used like a data structure.” It is true that it exposes behaviour since Active Record classes often contain business rule methods. However, Active Record doesn't really allow hiding data since “almost all ActiveRecord derivatives export the database columns through accessors and mutators”:
“The problem is that Active Records are data structures. Putting business rule methods in them doesn’t turn them into true objects. In the end, the algorithms that employ Active Records are vulnerable to changes in schema, and changes in type.
[…]
So applications built around ActiveRecord are applications built around data structures. And applications that are built around data structures are procedural—they are not object oriented. The opportunity we miss when we structure our applications around Active Record is the opportunity to use object oriented design.”
This does not mean that Active Records should not be used. Bob Martin believes indeed that “ much of good design is about how to mix and match the different vulnerabilities and immunities of the different styles.” He advocates, however, for not using it as "the organizing principle of the application". In his opinion, it should rather belong “in the layer that separates the database from the application” and play the role of “a fine transport mechanism” between the hard data structures of database tables and the application's objects. This way, the application - "oriented around objects that expose behaviour and hide data" - is designed according to the Open Closed Principle and remains flexible for the addition of new features by adding new types.