mdesjardins.github.io

Yesterday I read a blog post by Kenneth Downs entitled “Why I Do Not Use ORM” on his The Database Programmer blog. It wasn’t the first blog post with gripes about Object Relational Mapping, and it certainly won’t be the last. For me, this particular article highlighted a few misconceptions about why and how ORM should be used, and I thought I might chime in with my own perspective.

ORM is not a way to avoid SQL
The first thing that stood out for me was this quote:

“The language SQL is the most widely supported, implemented, and used way to connect to databases. But since most of us have long lists of complaints about the language, we end up writing abstraction layers that make it easier for us to avoid coding SQL directly.”

To his credit, the author wasn’t actually addressing ORM in this paragraph. However, anyone writing business logic which interacts with a database, who is unable to write some basic SQL, is like a bull in a china shop; nothing good will come of it regardless of the tools and abstraction layers employed.

The Simple Example
The next example in the post shows how one would write a row to a database in only four lines of PHP code – it looks something like this (I removed the comments):

$row = getPostStartingWith("inp_");
$table_id = myGetPostVarFunction('table_id');
if (!SQLX_Insert($table_id,$row)) {
 myFrameworkErrorReporting();
}

I don’t know PHP, but I think the code is reading every field in a posted form that starts with inp_, generates an insert statement straight from the ID’s on the form fields, and writes an insert statement with the results.

Perhaps it’s unfair to criticize this code because “it’s just a simple example,” but if this code is being held up as an example of how short and simple non-ORM code can be, one does have to wonder

He goes on to say that this task is made even easier by using a data dictionary to generate the SQL. After reading the “Using a Data Dictionary” article, one has to wonder whether or not the author realizes that it is a very crude form of ORM.

What about Business Logic?
Kenneth Downs tries to head-off any arguments about business logic before they come up, knowing that ORM evangelists will argue that the domain objects can encapsulate essential business logic for the application. His response?

“The SQLX_Insert() routine can call out to functions (fast) or objects (much slower) that massage data before and after the insert operation. I will be demonstrating some of these techniques in future essays, but of course the best permforming and safest method is to use triggers.”

For me, this sounds alarm bells. Triggers slow down transactions. Triggers are in your database, which is often your system’s biggest bottleneck. Triggers silently do things behind your back without telling you. Triggers change databases from vast, efficient places to store relational data, into a lumbering behemoth interpreting procedural code inside big iron.

Conversely, business logic that can be easily distributed across many smaller web servers scales horizontally. The domain layer is a fantastic place to embed simple data massaging – sadly, I often see a pile of persistent entities with getters and setters that don’t do anything.

Counter Example: The Disaster Scenario
Lastly, Ken (can I call him that? What is the ettiquite for this sort of thing, anyway?) shows an example of a piece of code that is likely to cause hundreds of unneeded reads to the database in an untuned ORM-based system. I don’t dispute this; in fact, I posted about an almost identical nightmare scenario myself a while ago.

For this, I go back to my “bull in a china shop” analogy. Programmers can write horrible code in any language, with any tool. Layers of abstraction are a double-edged sword, because you need to understand what they are doing for you. But it’s not the tool’s fault; it’s the person misusing it.

Computer Science’s Vietnam
In 2004, Ted Neward famously called ORM Computer Science’s Vietnam. Encouraged by early successes, we got sucked into the quagmire. There are plenty of reasons to be frustrated with ORM, but I’m not sure I agree with Ken’s. I try to hit the 80/20 rule with ORM, and use it where it makes sense. When I get into a convoluted transaction or need to do a large batch of operations, I’m not afraid to dive into SQL and do the work in a stored procedure. I think it’s a good mix. How about you?