I have a confession to make. I like ORM. Especially ActiveRecord, but let’s not get specific just yet. Let’s first go through my journey from ignoring to rejecting, then accidentally enjoying, and finally finding my happy place.
I was one of those SQL People
ORM did not help me write my first program. On the contrary, my career was forged in the fires of SQL. I made a database with ClarisWorks during my sophomore year of high school to keep track of phone numbers. Back then you actually had to dial them digits, ya dig? My first paid gig was changing an Access database with a relationships window that looked like a harp. My first two years of “programming” were spent writing ETL packages in DTS converting AS400 files into MSSQL tables and ultimately designing Business Objects universes for the finance team to report on. Yeah, I was a Data Warehouser. Ralph Kimball was the man, and I’m not afraid to say it. All of that taught me a ton about physical data modeling, relational and dimensional, a somewhat lost art.
When I started writing Java professionally (i.e. not school), it was back in the 3k sloc jsp days. Debugging the query executed on lines 2050-2110 within the infamous TCFTC block taught me a lot about low level database connectivity. Eventually I found Spring and really liked SpringJDBC. I wrote a very thin DAO layer for my app with simple SQL generation, which met my needs. I was nervous to jump into Hibernate or even Ibatis because I was so familiar with SQL. Then Rails came along, however one of the biggest selling points, ActiveRecord, didn’t impress me much. I foolishly fought ORM because I was so familiar with writing dope SQL. I was not looking for anything else.
When it all changed
Later in life I found myself dabbling with GORM on a Grails project. I really enjoyed how much time it saved me. It wasn’t long after I started working in Rails daily and although 2.0 was kind of a mess, I still gained a productivity boost. Once ActiveRecord 3.0 came out, I was hooked. Nowadays, I find it hard to live without.
Getting to a point where I can start iterating on product is key. Unless I’m lucky, because who doesn’t love one-off scripts, I’m going to need a database. I’m not at all thrilled about setting up my own plumbing for that. It’s repetitive and takes time away from the hardest part of software, building a good product. That’s when we actually start delivering value to our clients.
There was no going back for me, but there are still a number of arguments against ORM. Some of these arguments are valid, but not always sound. What I mean, is that there’s usually a flawed premise on which those arguments are founded. This is by no means an exhaustive list of said arguments against ORM, but let’s address some of the concerns.
ORM is slow
Nonsense.
In fact, most ORMs introduce or afford pluggable caching. You might even end up with faster performance. There’s almost always a way to drop down to raw result sets and avoid most of the instantiation overhead if your case calls for it. Regardless, new objects are usually cheap (unless callbacks, ugh). There are also profiling tools to help you see what’s going on inside of your application.
Premature optimization is a known evil. We can optimize that query when there’s enough data to realize it’s slow, and when someone is actually running it enough to care.
You wouldn’t create a mess that you can’t optimize your way out of because you have plenty of tests to refactor… right?
ORM means you don’t need to know SQL
This unfortunately has some truth to it. ORM does enable people to develop applications without having any idea how things are working. But this is like saying cars are bad because most people don’t understand internal combustion. If all you’re trying to do is drive to work then this is fine.
But as a developer, it is important to get under the hood and comprehend what is going on. There’s no excuse for not learning exactly what’s going on inside of the database. Not in the abstract either. Developers will benefit from knowing how to exploit not just SQL, but commands specific to the database platform they are using. MSSQL, Postgres and even Oracle have some pretty wicked tricks you can leverage and I encourage you to do so.
Do you need to drop down and understand everything right away? Probably not, but the more you know the better off you are.
Side note on leveraging database specific features: I’ve never seen someone port their application from one database to another. So exploiting platform specific strengths is more useful than portability. So go nuts.
ORM forces me into a relational data model.
Not only ORM catches heat. Relational databases have been under fire ever since the NOSQL movement. There’s a reason why the relational model works. Tabular data has has existed since at least 200 CE. It also works physically, as-in, computers deal very well with storing data this way. Document, key-value and column based stores have very specific applications and are incredibly useful in those scenarios. At the end of the day, that activity usually ends up in a relational store anyways so people can make sense of it.
ORM patterns also work over a number of non-relational stores. So even if i’m not writing SQL to fetch or store data, I still benefit from libraries that allow me to think less about how things get to me over the wire.
I hope the NOSQL movement has no sequel.
ORM is not simple
After my fiftieth rails new
I no longer want something simple.
I want easy!
The alternative to embracing ORM is mixing your own custom cocktail of disjointed, sometimes custom, libraries to achieve what ORM could have done for you. The argument that a library does too much or is bloated is often incorrect. Most libraries have an a-la-carte mode which means you an ignore or even remove the features you don’t plan to use. But rolling your own is something very, very rarely needed.
To me, Active Record is the best
I’ve explored many ORMs but I find Active Record to be the most complete by a land slide. Not only does it serve the base case elegantly, it is flexible enough to accommodate even the most sophisticated scenarios. Sure, there are a few features which can get you into trouble (looking at you, callbacks). You’ll definitely write an n+1 or two and the cost of understanding things under the hood is real. But once you learn how to use it you can write beautiful, composable queries which are easy to understand and maintain. Dropping down into raw SQL is rarely needed, but simple to achieve. Validations with i18n error messages, a powerful answer to schema management, serialization and the ability to save an entire object graph are just some of the additional features that are built in.
As long as you don’t go off-the-rails you get a wealth of plugins to extend and enhance AR when/if you run into problems.
- Need fast inserts? See bulk insert
- Stronger caching? Merely configuration
- Search indexing? No problem!
- Powerful form integration? Check!
- Need to store JSON? Structured or unstructured?
- Advanced serialization? Indeed
- Testing factories? The best available!
- Something else? Check here
Tons of ways to extend Active Record already exist but keep in mind they may not play nicely if you do something non-standard. It’s disappointing to see, but it happens. In fact, I see it all the time.
Honorable mentions go out to Ecto and LINQ for interesting alternatives in the ORM space not as comprehensive as AR. Whether it’s the migration story, form integration, ease of use from console or availability of add ons, I find myself missing something. Then there are some downright terrible and disappointing ORMs — but we’re going to keep it positive =)
In conclusion
I like ORM. I love ActiveRecord.
Developers should learn their database platform, how their ORM works and be able to get intimate with SQL. But then put it in your back pocket. Even though I commonly roll up my sleeves and get low level with the database, I’d always rather not. It frees me up to be able to focus on the hard problems like does this solve the user’s problem, and that’s highly valuable.