In my last post I described my slow realization that ORM, much like my old HTML editor, is very helpful until you realize it has auto-generated a code mess all over your project. I’ve categorized what I see as the four biggest issues, in order of increasing PITA:

Caching

The ORM that we use at Rally handles our caching strategy. This in and of itself is not really so much of an issue. It is generally pretty seamless and gives us good performance despite some inefficiencies. The problem is that because the caching strategy generally works we generally don’t think about it, and this can really throw us off when the ORM cache does something stupid.

These problems don’t usually manifest themselves until my code makes it to a clustered test environment where the cache must sync across multiple VMs. Not thinking about caching strategy because the ORM is handling it causes us to catch bugs late. These bugs are not typically easy to fix.

Bugs

Throughout my time at Rally there have been multiple occasions in which we have identified bugs in our ORM and had to work around them. One such time I was working on making our Test Case editor stateless. Test Case has a one to many relationship with another domain object called a “Step”. Test Case Steps are order dependent; should this order not be preserved the steps will lose their meaning.

During development time we noticed that our ORM was refusing to return the collection of steps in the correct order. To further complicate the matter this would only occur once the result of an earlier request for the steps had been cached. This turned to be an ORM bug that took us a week to work around. It was difficult to uncover the issue in the first place and our fix was neither pretty nor simple.

Inefficiencies

It is not a matter of if, but a matter of when the ORM begins to hinder the scaling of an application. This is a battle that we regularly fight here at Rally. ORM is great to kick-start a new project but for an application the size, scope and maturity of Rally it really begins to show its limitations. The specific situations in which ORM has caused us performance issues as a result of its choice of queries are too numerous to list in detail here. There is however a common thread that links all of these cases together: the object model.

Java operations that seem completely normal and are “good style” can be converted into an incredibly inefficient set of database queries. We often see this when traversing relationships and/or hierarchies. Depending on what data is in scope this can bring the system to its knees.

Issues of this sort are either caught late or not caught until we identify production performance issues.

No way out

Probably the worst thing about ORM is its pervasiveness. As I wrote earlier an ORM does make sense in the early stages of a project. But then the team continues to build the project around the ORM. Well, after so many years of continually adding to the system…

ORM is everywhere.

There is no escape.

The engineering team at Rally has made significant effort towards converting our ORM specific code to JPA. But we are still married to our ORM. We have so much technology specific code that the mere suggestion of removing it from our system is typically met with a laugh.

Were it not for this last point maybe the other issues with ORM would be more forgivable. But I have seen firsthand the difficulties that having a system you cannot change and cannot remove has on the agility of a project. Anything that hinders your ability to change directions or implementations should be approached with extreme caution. This is especially dangerous because ORM is really most attractive to those whom are not coding with caution, but rather with the need to create as much “stuff” in as little time as possible. The ORM that helped you along early in the project will slowly become your enemy. Expect it.

TL;DR
This isn’t normal……but on ORM it is.

ORM, not even once.