Active Record Pattern Has No Consequences?
I've been looking at Rails lately, partly to see what the hype is about and partly to see what useful elements can carry over into my ColdFusion development. One of the things that I have pretty deep concerns over is its focus on the Active Record pattern. Most books and tutorials go so far as to recommend building your database first and then working backwards from that!
It would be interesting to have a discussion on whether it is a bad idea (and I think it is) to work backwards from a relational database model and hammer this down on top of your domain model. But I don't want to go there just yet. What I wanted to talk about is the Active Record design pattern itself.
Active Record (or ActiveRecord if you prefer) underpins almost everything you will see about Rails. It is the reason why "the database comes first" for most Rails folks. And I won't argue that it seems to have some nice advantages. It handles relationships and SQL and all that boring database stuff. It makes things like scaffolding not only possible, but fairly simple. Because a lot of web applications ARE actually just CRUD front ends for database data, Active Record might often be just the ticket.
However, Active Record is supposed to be a design pattern. So why it that if I Google for "'Active Record Pattern' Consequences", I get only 33 results? 33! Where a search for "Active Record Pattern" alone brings back ten thousand?
Design Patterns are supposed to be defined in a very specific way. One of the parts of that definition is to describe the consequences. These are the drawbacks or implications of using that pattern. I'm not sure why, but for some reason no one seems to be considering the consequences of the Active Record pattern. In fact, even of the 33 results I could find, none of them actually discuss the consequences of the pattern. They just happen to be results where the word "consequences" happened to be somewhere on the page. I could not find a single pattern definition for Active Record that actually discussed the consequences (or most of the other established elements that should be present when defining a pattern).
First, does someone know if I am missing something? Is there some reason why no one would be considering the consequences of this hugely popular pattern? The cynic in me almost wants to think that someone (I believe it was Fowler, who I admire greatly) came up with this idea, and then a lot of other people just grabbed it and ran with it, slavishly applying it without really giving it any more thought. Does anyone have any ideas on this? Why is Active Record, as far as I can tell, such a popular "pattern" that actually doesn't seem to have a real pattern definition?






I'm not sure what books you've looked at, but the ones I've read focused on the front-end first?
http://terrychay.com/blog/article/simple-prescript...
@Sami, nothing is technically stopping me from "doing it the way I want to". I just dislike the data-centric approach that is pushed by Rails. Everything seems to revolve around the database and, as a result, the properties of the ActiveRecord objects. In other words, the focus is on data, not behavior. I'd be very interested to see an article or book that actually talks about building a real domain model within a Rails app.
This is the Patterns of Enterprise Applications book. Go to page 160 for Active Record.
>they plan out what the interface will be and from that
>decide what the schema should be to support it
...and that what really bothers me about Rails. It shouldn't be "schema to support it," it should be "domain objects to support it" as Brian pointed towards in his "there is no discussion of actual domain modeling." The schema shouldn't be approached until figuring out how to persist the domain objects. The paradigm mismatch between OO and relational storage is too big to have a schema = object model reflection do your application justice.
@kyle and brian (re: Fowler's book)
I think the rest of the definition is in the full book...he does point out some of AR's shortfalls in the available excerpt.
In my own limited experience, most developers really don't have an interest in theoretical debates. They want to find a solution that works at least marginally well and apply it to a specific problem they are facing at that moment. A few people might document their findings to share with others, but they don't take the time to really delve into the theory behind the solution.
Still, I would expect to find more on the theory behind Active Record than I did. The cynic in me thinks that people (like Fowler) who spend the time and energy to describe programming theory want you to buy their books instead of reading about it for free.
Thanks, and I agree: to me, anyone who embarks on a 6-month model planning cycle is probably doomed! I'm considered fairly formal in that I like to follow UP for discovery/decomposition, and that's rarely more than a day or so of whiteboard and Enterprise Architect UML in a given iteration.
It's not that I don't believe in shooting the relational fish in the barrel. I just think you should know what kind of a gun you're holding....you may be shooting a shark with a slingshot, and you'll just make him angry.
http://www.firemoss.com/blog/index.cfm?mode=entry&...
If I had a blog I would have posted the same (or very similar, anyways) thing. It seems to me like in both Rails and PHP the approach is database first, model next. This implementation of the ActiveRecord pattern seems to produce an anemic domain model.
I took last week off work and decided to learn and compare OO implementations in PHP with that in CF. I even checked out some of MVC frameworks, CakePHP and CodeIgnitor, both of which use the ActiveRecord Pattern. I kept finding myself wondering, "how do I create 'smart' getters and setters instead of just mirroring my database table and fields?" I decided to generate some models in both frameworks and when I looked at the resulting code all I saw was framework specific code ($name = tableName; is all that was in the model).
I started a thread on the SitePoint forums to discuss available DI/IoC frameworks for PHP and everybody seemed to think that a DI container was unnecessary. I guess it figures since they put their framework specific code directly in their model - everything is coupled together anyways so why bother with DI?).
To get back to your topic though, I had the same problem when I was considering the ActiveRecord Pattern for my own applications. I had a hard time finding anything related to the disadvantages of the pattern. I finally decided not to use it because I like having a service layer as a single API for CRUD and bulk queries. I was afraid that if I used the ActiveRecord pattern I would not be able to changed the front-end out to Flex or Flash without major modifications.
This was always my beef with Rails. Check out Django or RiFE both of which allow you to declaratively describe your object model and then just gen the appropriate db tables once you've described your rules for persisting objects. Both are a little limited in terms of the ORM they support, but at least they start by describing the domain object and then worry about persistence afterwards.
Let's start with the whole ActiveRecord thing first. The downside of the ActiveRecord pattern is that it's tied to a database or view by definition. Regardless of the language, that's a problem. Maybe. Depends on your application. And it means that at some point either you'll have to code-generate the db from the object or the object from the db. It's not a language thing, it's a chicken and the egg thing. You can work forwards or backwards, but the very definition of the pattern *assumes* a database -- there's no point in abstracting that out because you are making the existence of the matching database table (or view) a part of your initial design. So you've got your data access built-in plus some domain logic.
Is ActiveRecord always the *right* way to model objects in your app -- heck no. Only ones that get persisted to the db for starters.
Now on to Rails. Nothing forces you to use ActiveRecord for *every* domain object. Nothing forces you to do iterative development using the database as your primary domain modeling tool. All the higher-end Railsistas are using tools like RSpec to specify behavior of objects and mock them out LONG before you hit a database. Take some of this with a grain of salt -- I mean do any of you build your apps like the OrangeWhip app of Ben's in the CF books by Adobe? :) :)
So ActiveRecord is a pattern that has its place, but is no more the only one than the Gateway/DTO/bean model that folks in the CF world slavishly use because they've seen a few blog posts. Use them in the right place and they rock
"[the ActiveRecord pattern] two stunting problems: lack of associations and inheritance"
That's from, interestingly, the docs for ActiveRecord (http://api.rubyonrails.com/files/vendor/rails/acti...)
and also explains how the Rails ActiveRecord implementation solves both of those problems.
http://www.loudthinking.com/arc/000209.html has a brief discussion of the pros/cons of ActiveRecord vs DataMapper and basically applies the 80/20 rule. I agree.
As an aside, one of the key development practices of the Rails world is the so-called skinny controller/fat model approach
http://weblog.jamisbuck.org/2006/10/18/skinny-cont...
So the object in Rails might derive from ActiveRecord, which makes it pretty "basic" in the OO world, by the time you mixin some functionality, you're looking at just as rich an object as you'd build in most other languages, just with a few thousand less lines of code and a few hundred less files :)
Speaking to the main point of this blog post: One disadvantage of ActiveRecord (that I've run into personally) is that ALL columns in your database become attributes on your model. So if you want encapsulation (i.e. private attributes) in ActiveRecord, then you are out of luck. Encapsulation? In object oriented code? I know it is asking for a lot... ;)
So instead of (only) complaining, I wrote a patch for ActiveRecord:
which adds a method called attr_private. It passes the tests I wrote for it and would be interested in feedback of all sorts. (Yes, I've heard of attr_protected, but it does *not* really make a database column protected.)
Since the patch hasn't gotten much attention, I would guess (a) the Rails Core team is busy with more pressing issues, (b) my patch needs improvement, (c) my patch is missing the point of the active record pattern entirely (i.e. active record is not intended to encapsulate at all).
My pragmatic advice? If you want to be able to {encapsulate, rearrange, compose} database columns then check out DataMapper and see what you think. You might take a look at Merb while you are at it.
If you are interested in my patch for 'attr_private' just put that term into google, or see:
dev dot rubyonrails.org / ticket / 8355
Your App is a section of real world and you try to create a miniworld that maps this section.
You extract the needed classes and their relation between them and then you think about persistence.
So, if I start such an App - I start with designing my database. And then I build my app above that.
I can't accept Robert Martin's argument, that it's "evil" so handle an ActiveRecord structure as if it's the object.
In my view - the ActiveRecord thing IS our object. It stands in our App and it is persistent in our database.
How else do you start developing an application? GUI first? Even so, it is quite removed from the actual database, so it should not be a problem.
The consequences of A.R. is that you tend to forget SQL.
There are plenty of ORM frameworks that let you "forget SQL" but don't rely on ActiveRecord. Handling CRUD operations or generic filter queries has never been the problem. Generating that is simple.