⇥ Right conclusion, wrong reasons
The reason I call ORM an anti-pattern is because it matches the two criteria the author of AntiPatterns used to distinguish anti-patterns from mere bad habits, specifically:
It initially appears to be beneficial, but in the long term has more bad consequences than good ones
An alternative solution exists that is proven and repeatable
It is the first characteristic that has led to ORM’s maddening (to me) popularity: it seems like a good idea at first, and by the time the problems become apparent, it’s too late to switch away.
I agree that ORMs are, in general, to be treated with much suspicion. Their main shortcoming is that they are a square-peg solution for a round-hole problem: attempting to map a data model to another inevitably leads to conflicts and issues, or there wouldn’t be a need for the two different data models in the first place.
The real problem with this blog post, however, is that it uses an incomplete definition of anti-pattern (there’s Wikipedia for you). In his original article on anti-patterns, Andrew Koenig1 speaks specifically of anti-patterns as juxtaposing to patterns; like ying and yang, you can’t have anti-patterns without having patterns that they can be related to.
The significance of this is that an anti-pattern is not just something that is “bad on its own.” More often than not, it is more like “a pattern that has gone bad”—the right concept being applied under the wrong circumstances.
Thus, ORMs are not inherently bad. They are just inappropriate for a number of settings in which they are, admittedly, used. An ORM can be an excellent solution to scenarios in which a key-value store is not available, or in which a very simple schema is all you need. In those cases, the overhead of an ORM may be an acceptable tradeoff for the simplicity that it brings to an application.
This, in turn, brings me to another point: using an ORM does not excuse you from understanding the underlying data model and the way the ORM uses it. If you do, the ORM becomes almost inevitably an anti-pattern, because you’re resorting to magic and applying a solution without knowing the problem.
Thus, while it’s true that ORMs encourage (and mostly fail) the developer not to think in terms of SQL queries, there is no way to use an ORM well without understanding relational data mapping. Or, put another way, the ORM doesn’t replace your knowledge of SQL—it simply adds one more layer of indirection to it.
An argument could be made that ORMs do not scale well over time, because the relationship between the overhead they introduce and the complexity of the underlying data model is not linear. This, however, seems to me like a symptom of application design, rather than an inherent flaw in ORMs.
Let me give you an example; if you’re writing an application that you know you will only need to run once (for example, some sort of importer or data analysis function), an ORM can greatly simplify your job and bring immense benefits. Will you care if it doesn’t scale? No, because you’re writing a single-use application.
If, on the other hand, you’re writing a more complex application, then you need to evaluate how well an ORM will hold up over time. That’s as much an art as it is a science, but it doesn’t make ORMs inherently bad; it simply means that you need to learn to design software properly.
- The original article in JOOP is not available online, but it’s included in Linda Rising’s Patterns Handbook ↩
Comments
Fred Brooks nailed it in 1986. There’s No Silver Bullet. No tool or technique is applicable to all situations all the time.
Good article. Thanks. Am I right in thinking that the fact that it doesn’t scale well is usually exactly what makes an anti-pattern – a solution that appears to help to start with but causes problems later? Most patters are precisely the opposite – they can look like overkill to start with but they seriously help down the line.
You say that it “doesn’t replace your knowledge of SQL”, although usually this is exactly the point of abstraction – that you don’t need to understand the underlying implementation (programmers don’t understand machine code; CMS users don’t understand programming). You would obviously need to understand how your data related to each other, but if ORMs succeeded in being an abstraction you shouldn’t ever need to know SQL per se.
Whether it’s an anti-pattern or not depends on whether its inability to scale exceeds your requirements for it to scale. In other words, if you expect it to suit your requirements for the reasonable lifespan of your application, then it’s not an anti-pattern. You should read Koenig’s original article to really understand this point.
As for abstraction—the point of abstraction is slightly different from what you mention, I think. Abstraction allows you to *ignore* the underlying technology, but that doesn’t mean that you don’t have to know it. Developers may not know assembler, but they have to understand the underlying technology in at least broad strokes to make good decisions.
You don’t give any reasons for your conclusion. You state a “definition” of anti-pattern and then you just assert it fits w/o stating why.
Also it seems to me that at the end of your post you come to the conclusion that ORM is no anti-pattern actually if you know the workings of a RDBMS and SQL.
I’m a big fan of graph databases and object stores – who needs mapping; just let me persist things!
@Robin: Saying that ORM prevent scaling is also looking to short. Like Marco says its an abstraction which has inherit overhead, but allows flexibility that you cannot get otherwise.
The best example are things like trees in RDBMS. A prime example of a square-peg. However if you hand craft your SQL you will hardcode your algorithm to adjacency list, materialized path, nested set (unless you come up with some other form of abstraction). With an ORM you can switch as needed. So if your usage patterns change, you can adapt much easier. If you provide a shrink wrapped products, your customers can tweak things etc.
Oh and I should add that even if you want objects, you might still want the underlying data inside an RDBMS because you need to be able to easily do adhoc reporting queries.
At any rate in my experience I can better deal with developers with limited SQL experience inside an ORM than if I let them work with SQL directly because I can do lots of optimizations without them having to remember all little details.
But thats a very rare case, the key reason for ORM in my book is complex business logic that needs to be attached to every query that isn’t possible to easily model with VIEW’s.
I feel like this article falls flat on its face. It started off in the right direction but ended up proving/showing me nothing.
If you can elaborate more that would be great. Please give examples.