48

I'm interested in whether ActiveRecord pattern, made famous from Ruby on Rails, encourages or discourages the use of SOLID design principles.

For example, it seems to me that ActiveRecord objects both contain domain logic, and persistence logic, which is a violation of Single Responsibility.

4
  • 6
    Jim Weirich, at the end of his SOLID Ruby Talk at the 2009 Ruby Conference, asks the audience: "ActiveRecord objects implement a domain concept and a persistence concept. Does this violate the SRP (Single Responsibility Principle)?" The audience agrees that it does violate the SRP. Jim asks if this bothers them. Many members of the audience say yes. Why? It makes testing harder. It makes the persistence object a lot heavier.
    – David J.
    Jun 26, 2012 at 16:35
  • @DavidJ. the link is now dead, is this talk archived somewhere?
    – jrh
    Aug 13, 2021 at 17:06
  • 1
    @jrh I'm not surprised; I wrote the comment ~9 years ago. Did you try searching? I found an up-to-date link very quickly: youtube.com/watch?v=dKRbsE061u4
    – David J.
    Aug 23, 2021 at 20:02
  • @DavidJ. nope, didn't try searching because a lot of conferences don't make it to YT, glad this one did though!
    – jrh
    Aug 23, 2021 at 20:42

2 Answers 2

58

There's some valid criticism on ActiveRecord. As always, Uncle Bob sums it up perfectly:

The problem I have with Active Record is that it creates confusion about these two very different styles of programming. A database table is a data structure. It has exposed data and no behavior. But an Active Record appears to be an object. It has “hidden” data, and exposed behavior. I put the word “hidden” in quotes because the data is, in fact, not hidden. Almost all ActiveRecord derivatives export the database columns through accessors and mutators. Indeed, the Active Record is meant to be used like a data structure.

On the other hand, many people put business rule methods in their Active Record classes; which makes them appear to be objects. This leads to a dilemma. On which side of the line does the Active Record really fall? Is it an object? Or is it a data structure?

Wikipedia sums the criticism in a testability concern:

In OOP the concept of encapsulation is often at odds with the concept of separation of concerns. Generally speaking, patterns that favor separation of concerns are more suitable to isolated unit tests while patterns that favor encapsulation have easier to use APIs. Active Record heavily favors encapsulation to the point where testing without a database is quite difficult.

Specifically for the Ruby on Rails implementation, Gavin King writes (emphasis mine):

At this point, most developers are thinking um, ok, so how the hell am I supposed to know what attributes a Company has by looking at my code? And how can my IDE auto-complete them? Of course, the Rails folks have a quick answer to this question Oh, just fire up your database client and look in the database!. Then, assuming that you know ActiveRecord's automagic capitalization and pluralization rules /perfectly/, you will be able to guess the names of the attributes of your own Company class, and type them in manually.

Also on the Ruby on Rails implementation, John Januszczak writes (emphasis mine):

PROBLEM #1: STATIC METHODS

...

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

...

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!

A few more resources on why ActiveRecord and ORM is generally considered to be an anti-pattern:

ActiveRecord always felt like an extremely useful anti-pattern, but I do agree that it goes against SRP and additionaly that it goes against the dependency inversion principle.

2
  • IMPORTANT update for rails 5+: " And how can my IDE auto-complete them? Of course, the Rails folks have a quick answer to this question Oh, just fire up your database client and look in the database!. " is not valid anymore. With attributes API you can define all available columns on model Feb 2, 2017 at 0:37
  • The Uncle Bob link redirects to a shady looking real estate site now, but it can be found on archive.org
    – jrh
    Aug 13, 2021 at 17:10
7

(I am assuming that the ActiveRecord class is implemented without any possibility for dependency injection).

From personal experience I can say that ActiveRecord pattern becomes a major obstacle for writing unit tests. The coupling of the persistence layer and business logic in a single "ActiveRecord class" makes it impossible to write unit tests (unless you refactor first). Therefore, the only option is writing integration tests; and that is not as effective as unit-tests. This becomes a major issue especially if you take over a project with a lot of ActiveRecord classes; it yields to highly complicated integration tests that are hard to maintain.

So, the ActiveRecord comes pretty much against SRP and creates some maintenance headache; it seems to take away the power to write unit-tests.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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