DEV Community

Ryan Westlund
Ryan Westlund

Posted on

Losing faith in ORMs

I love ORMs. Ever since I found out about them, I've thought they were the greatest thing ever. But lately I'm losing faith and considering dumping the Jennifer ORM - which I settled on after looking at several different ORMs - in favor of raw SQL in Didact. And this is a dream project of mine, so my emotional incentive to use the things I like is stronger than ever. So what's happening?

First, let me lay out the 4 main benefits of ORMs I see:

  1. Decrease dependence on specific backends by abstracting away differences in SQL syntax etc.

  2. Greatly reduce the amount of code you have to write. At my job at Awning Tracker, a good 1/4 or 1/5 of the server code is manual SQL implementing CRUD methods on every domain object.

  3. Single source of truth. With manual SQL, there are many different places that need to change when you change the schema.

  4. In a statically typed language (which Didact is written in: Crystal), allow SQL to type-checked too.

These are all great benefits, but the last few months have taught me that there are downsides too.

  1. Adds a dependency which probably has bugs, doesn't implement some important things you expect from an ORM, and has an unresponsive maintainer.

  2. Time spent learning the language of the ORM.

  3. Most of them have deeply questionable designs that restrict their flexibility, like having database connections be part of model definitions. Many of them have more than one such offending design choice.

And there's something else: that 4th benefit I mentioned seems to be almost never realized.

Obviously it can't be realized in dynamic languages, but even most ORMs for static languages fail at it because they implement their query methods with some type-checker-overriding language feature like Go's interface{}, or Crystal's **kwargs and using reflection on the inside to tell if an argument is valid and - get this - ignore it silently if it's not, not raise an exception. That's what both Granite and Jennifer do.

I think Diesel might be the only ORM I've seen that actually realizes this benefit. And it had other issues that led me to reject it.

Over the course of planning and making Didact, I've looked at at least 7 different ORMs. 4 in Rust and 3 in Crystal. The 3 Rust ones besides Diesel were all either abandoned or in early development and far from ready. The Crystal one I looked at besides Granite and Jennifer, Clear, is Postgres-specific.

And apart from the cost of researching and trying out so many different ORMs, they've costed me a lot more. Both Granite and Jennifer blocked Didact development for weeks if not months as I waited on maintainer feedback on an issue or pull request.

There is no doubt in my mind that ORMs have tremendously failed to pull their own weight in this project. I think maybe tomorrow I'll look at dumping Jennifer and just go raw SQLite. The biggest dependency cut loose, it probably won't actually increase my SLOC by much, and it will probably bring the memory cost of compilation back into the range where Didact can be compiled on a $5/month VPS.

And as much as I want to blame this on "Rust and Crystal are both new and their ecosystems aren't ready", it has shaken my faith in ORMs in general. Looking back on my experience with SQLAlchemy, I'm not even positive that pulled its own weight for me despite being a very mature and feature-complete ORM. I'll always remember how confused I got by SQLAlchemy and Postgres both wanting to be the one to handle foreign key constraints.

Discussion (7)

Collapse
misobelica profile image
Mišo

Hi, I have +- the same feelings. Despite I quite like SQLAlchemy I had to work also with Java (and then Kotlin fortunately). In Java world that means Hibernate which is just terrible ORM IMO. I was always questioning myself how is it possible that no one implement something better. I can't be alone seeing it trashy. And then I found JOOQ. I started reading blogs, documentation and even without using the library I learned new things about SQL and databases. It has strong static typing to the degree you catch renamed column on the table and even if it's not really an ORM I think it's worth to watch and maybe to inspire there so one day when the time comes you can implement your own better library for your favorite language :)

Collapse
mitchartemis profile image
Mitch Stanley

I’m also left wanting for a good, active ORM in Crystal.

I think Ecto’s design is a good middle ground, which is built in Elixir, as it exposes you more to the SQL queries that it’s running. It’s also quite flexible in how you can build complex queries.

I know Crecto exists with a similar API for Crystal, but unfortunately it’s not actively maintained. I have a pull request that’s been open for several months now.

Collapse
phantas0s profile image
Matthieu Cneude • Edited on

ORMs are good if you only do basic operations on your data: create, read, delete, update. When your queries get more complicated, you'll end up trying to go around your ORM and hack it. Personally, I don't see the point anymore: the amount of time I lost to write my own requests is regained afterward when I get the flexibility I need.

This is a good example of interface simplification which has big cost: flexibility.

Collapse
texpert profile image
Aurel Branzeanu

Maybe have a look at Avram? github.com/luckyframework/avram

Collapse
yujiri8 profile image
Ryan Westlund Author

Is that the ORM the Lucky framework uses? Regardless, it seems to be Postgres-only (same reason I rejected clear).

Collapse
braisdom profile image
Braisdom

Why don't you try ObjectiveSQL

github.com/braisdom/ObjectiveSql

Collapse
yujiri8 profile image
Ryan Westlund Author

Um, that's a Java ORM. My project is in Crystal.