Another rant about ORMs

ORM are wonderful pieces of technology. They tackle a thorny problem and solve it well in many situation. If you start building a web app, I would advise you to rely on the ORM to simplify access to the database. It will allow you to save a consequent amount of time, preventing the burden of mapping data. And even delay the decision of the datastore you will use.

Saddly though, it won't solve all your problem.

Once you've chosen postgreSQL as a datastore (reasonable choice), why would you restrict yourself with you ORM API?

SQL language is actually good. So much that every modern big data system include a SQL dialect to access data.

I'm currently working with Laravel, and I'm not so OK with its ORM. Using SQL, if you do not want to rely on operator precedence (which have precedence between OR and AND?) with parenthesis. Not so easy with your ORM.

Much funny, a generated query changed when I updated to Laravel 8 (a change not documented, of course).

Worse, using ORM entities like explained in framework tutorials lead to leak data access in the whole app.

Believe me, it's not funny when you unexpectedly face a SELECT N+1 problem while serializing entities to send them back in HTTP Response. I faced this kind of problem on a legacy project I workded on recently. It did not end well.

The use depend on your context. Decisions to do rely on lazy loading or eager loading depends on the data you want to receive. When I so the demo of ruby on rails, consisting in coding a blog in 15minutes, I was so amazed. But we do not work on blogs with articles linked with comments and author. But whwn you have more levels relations things get worse. With SQL you can choose to prioritize queries on roots or on leaves of your agregates. Why rely on 2 nested loops when you can have all needed data in 1 request. But it may be better who knows.

Finally, I find it hard to select a limited set of fields from tables (in the one I used). Too bad when you retrieve a collection of data, with several fields of description when you only need id and name. It may be feasible with the most ORM but it adds complexity.

Putting business logic in ORM entities is tempting. But how do you test? You'll eventually be forced to use a database, mount the whole framework. Your test suite takes longer to run and your tests become harder to implement.

So what can you do. I propose the hard and ugly way. You can start with the ORM, but hide all the ORM entities behind a repository class. Map your agregates to pure objects that implements your business logic. To be simple, consider your ORM as a syntaxic sugar over plain SQL. When you'll need to tune your database access, you can easily decide to acess your data through SQL statements without touching to your business logic.

Your strategy to gather data can depends on the context, and you won't be surprised by a SELECT N+1 issue.

You can test you business logic using pure unit tests.

Posted on 2021-04-19 at 22:00

Previous Back Next