Live data from Hacker News

OrmHate

martinfowler.com

91–100 of 136 posts

Re: OrmHate

#91
post #71
post #38

I think a lot of the frustration with relational databases in general comes from a misunderstanding. People conflate "relational" with "SQL", because of the historical accident that SQL is the most popular way to query relational data. Then when SQL isn't a good fit for their problem, they think relational is not a good fit for their problem, which is almost certainly not true. The original motivation for relational…

People conflate "relational" with "SQL", because of the historical accident that SQL is the most popular way to query relational data. Then when SQL isn't a good fit for their problem, they think relational is not a good fit for their problem, which is almost certainly not true. For most practical purposes, SQL is the only way to query relational data. In the absence of alternatives, it's natural to conflate the noti…

I'm not sure what you mean by fit poorly in the relational model.

ORDER BY, LIMIT/OFFSET have to do with presentation of data. So, although it's highly desired that a language based on the relational model supports them, they have nothing to do with the model per se.

As for opaque keys, I thought the old debate about surrogate/artificial and natural keys was over years ago. The relational model has nothing to say about it, that would be like trying to make a model understand if facts are true in the real world or not. A key is a key.

Moreover, last time I've checked transitive closure operators were defined for the relation model (people should not stop ad Codd papers, Date and Darwen wrote a lot of books, e.g. The Third Manifesto, extending on the original ideas).

NULL is a completely different beast and this is the only real thing one can consider problematic.

In some cases NULL just means the predicate for the relation is different because values for an attribute don't apply, so this is not really a problem, in some other cases we simply don't know the value when we are collecting information, and this is indeed a problem.

Date follows Wittgestein that said we should remain silent about things we can't speak about i.e. we shouldn't collect incomplete information, Codd came up with I-marks, A-marks and n-valued logic, SQL collapsed everything into NULLs and 3-valued logic.

Re: OrmHate

#92
post #56

Earlier quoted context omitted.

"If I was to write the sql for this, I'd take 10x the time and it would be wrong anyway." SQL is the problem here. It's so hard to write reusable, composable fragments of SQL that we've all just internalized the idea that we have to write the query you're referring to from scratch every time, which is a bizarre and annoying intrusion of 1970s software engineering into our 2012 world. You almost certainly have pattern…

I've often felt that SQL was terrible, but I don't know what would be better.

Relational algebra or Datalog.

Re: OrmHate

#93

Earlier quoted context omitted.

> In my admittedly anecdotal experience, I have found that ORMs are the most useful for the most trivial queries. True, but 'trivial queries' generally cover the majority of use cases within your average CRUD application, and that's exactly why ORMs are useful -- you don't end up re-typing 'select bar from fu where id = 1' or 'select * from fu, bar where fu.bar_id = bar.id' etc., etc. Beyond that, most of the common…

But ORM's don't actually help for the trivial queries. I generally find myself writing functions to automate the trivial ones: get_single_field_by_primary_key(), get_row_by_primary_key(), get_values_by_field(), etc. There are maybe 4 or 5 of these. An entire ORM is total overkill. As for the common joins, in my experience they rarely are that trivial. Sometimes it's a left join, sometimes an inner join. Sometimes the…

> I generally find myself writing functions to automate the trivial ones: get_single_field_by_primary_key(), get_row_by_primary_key(), get_values_by_field(), etc. There are maybe 4 or 5 of these. An entire ORM is total overkill.

Making a homebrew data layer isn't avoiding an ORM, it's building one.

> If you find yourself writing the same query structure 20 times, then create a function for it.

What do you think ORM's do? That is what they do, they provide a standard API for all the common queries.

Re: OrmHate

#94
post #23

> There is a lot of truth to these charges, but such charges miss a vital piece of context. The object/relational mapping problem is hard. I suspect that context is precisely what underlies the common critiques of ORMs. Those people who best understand the inherent object-relational impedance mismatch tend to be the very people who conclude that the effort isn't worth it. In my admittedly anecdotal experience, I have…

> In my admittedly anecdotal experience, I have found that ORMs are the most useful for the most trivial queries. Bingo. In other words, non-relational queries work well and relational queries don't. When I'm joining multiple tables and looking for specific rows/objects that match multiple restrictions, ORM turns into a migrane of epic proportions. SQL was specifically designed to solve that exact problem. Abstractin…

> When I'm joining multiple tables and looking for specific rows/objects that match multiple restrictions, ORM turns into a migrane of epic proportions.

Perhaps you're doing it wrong. Put the complex query in a proc or view, and use the ORM to map the result set into memory. Using an ORM doesn't mean not using SQL when it works better.

Re: OrmHate

#95
post #70

I think it's basically the O part. In theory, one might have a delightful ontology of object oriented code, like Animal->Mammal->Cow , but in reality you often have something much more like CompanyNamePersistentObjectBaseClass->Entity->ExtendedPersistentEntity->CacheFactory->Entity(but in a different package)->NeedToAddAPropertyForJustThisReleaseIPromiseThisClassIsGoingAway->IdAddThisToTheBaseClassButIReallyNeedToRel…

Your comment is screwing up the page layout. (Firefox, Win7)

Re: OrmHate

#96
post #49
post #35

Earlier quoted context omitted.

>I don't think there is an easy answer. Uhm, ActiveRecord at least will print the SQL it generated. If you think it's inefficient, you can just… write your own sql that maps out to that query. With Arel/scopes, they're also composable and lazy loaded. What's not to like?

I find that the opposite way is way harder to debug: I see that a controller causes a bunch of SQL queries, but where do they come from? In the view? In a helper? In another library within the app?

Active record tells you where it came from in the log.

Re: OrmHate

#97
post #38

I think a lot of the frustration with relational databases in general comes from a misunderstanding. People conflate "relational" with "SQL", because of the historical accident that SQL is the most popular way to query relational data. Then when SQL isn't a good fit for their problem, they think relational is not a good fit for their problem, which is almost certainly not true. The original motivation for relational…

Can you suggest any good references for alternatives to SQL or a more general discussion of path independent data access? My background is such that practically "relational" and "uses SQL" are wholly conflated. I would be very interested to get a broader view. Does datalog fit somewhere in the discussion?

Tutorial D: http://en.wikipedia.org/wiki/D_(data_language_specification)

Re: OrmHate

#98

> There is a lot of truth to these charges, but such charges miss a vital piece of context. The object/relational mapping problem is hard. I suspect that context is precisely what underlies the common critiques of ORMs. Those people who best understand the inherent object-relational impedance mismatch tend to be the very people who conclude that the effort isn't worth it. In my admittedly anecdotal experience, I have…

> In my admittedly anecdotal experience, I have found that ORMs are the most useful for the most trivial queries. For anything complicated, I find it easier to drop into SQL and write the query directly As a recovering DBA, I want to jump out of my seat and say "Yes, exactly!" In many situations, "simple" queries can easily cover 90% of what you actually need, and simple queries are often an order of magnitude less e…

> If your devs are in the habit of writing lots of SQL,

> they'll often decide to do things like write one complex

> query to avoid the need for a few trivial queries.

As someone who single-handedly maintains a large codebase and a large database for a large website, I can assure you you've hit the nail on the head but completely missed the point.

Unless you're writing a hello world style to-do list, trivial queries tend to be the vast minority of the application logic needed. Most queries need some degree of tuning, whether that be to pull out specific rows, associate related data, summarise, or sort. Do this right, and you can achieve in a single query what would take multiple, dozens, perhaps hundreds of round trips to the database if written with "trivial" queries.

And let's not forget, it's particularly rare for the "complex" query to be more complex than the application code needed to implement the equivalent task. SQL isn't always beautiful, but it can often express ideas more succinctly than most general purpose languages. One GROUP BY can save you from writing big loops. One INNER JOIN or subquery can save you from subsequent database calls. One HAVING clause can save you pages of twisted logic.

A "complex" query generally avoids the need for a few trivial queries that are comparatively inefficient, both in terms of resources and latency. The goal is to allow the database to do the hard work of extracting every byte you need and nothing else. Databases are good at this shit, and even with a good ORM you're often forced to compromise or maintain two worlds within one app.

---------

That said, I acknowledge that there are multiple legitimate points of view on this debate. I tend to find that the SQL vs ORM debate tends to fall depending on the sort of code that's being written, and the sort of logic that's needed. Desktop apps tend to suit ORMs more readily than web apps. Smaller and self-contained apps tend to survive ORMs more gracefully than broad-scoped apps.

Nothing can excuse stored procedures though. Useless garbage.

Re: OrmHate

#99
post #71
post #38

I think a lot of the frustration with relational databases in general comes from a misunderstanding. People conflate "relational" with "SQL", because of the historical accident that SQL is the most popular way to query relational data. Then when SQL isn't a good fit for their problem, they think relational is not a good fit for their problem, which is almost certainly not true. The original motivation for relational…

People conflate "relational" with "SQL", because of the historical accident that SQL is the most popular way to query relational data. Then when SQL isn't a good fit for their problem, they think relational is not a good fit for their problem, which is almost certainly not true. For most practical purposes, SQL is the only way to query relational data. In the absence of alternatives, it's natural to conflate the noti…

As soon as you have arbitrary one to many relationships you have relational data so there are a lot of add hock systems out there. As to larger scale ones I often use linq to do in memory query's of objects with relationships.

More limited examples often fit the hierarchical database model such as graphics API's that have can handle object -> Vertex relationship, and or recursive relationships between objects. But, games frequently need 1:M or M:M relationships between things like factions, so there are plenty of addhock API's out there that fit the relational data model.

Re: OrmHate

#100
I really have never understood the ORM hate. I've found them to be immensely useful in 99% of circumstances, and for the remaining 1%, a good ORM will always let you fall back to raw SQL. Aside from providing a simpler syntax for performing basic queries, there are a few features that ORMs provide that have greatly simplified my life:

1. Automatically using prepared statements and validating/escaping query arguments to prevent injection. You have to be quite a bit more careful when you're working with raw SQL.

2. Providing an clean API to construct complex queries.

This typically becomes an issue when you have a query where you are filtering and/or sorting by multiple fields which are specified by the user, some of which are conditional. If you're writing raw SQL you end up needing to do a lot of string manipulation which can get fairly messy (and makes the code more difficult to understand). An ORM which provides some sort of query builder syntax that lets you do:

  if (some condition):
    query.addWhere(clause)
  if (some other condition):
    query.addWhere(other clause)
  etc.
is pretty convenient.

3. Collating repeated result rows from joins

Whenever you're working with joins you end up with repeated data in your result set, which you generally end up having to collate before display. For example if I have Recipes Categories and do a query to load the both of them, I might end up with something like this:

  recipe_id | recipe_name  | recipe_ingredients | category_id | category_name
  --------------------------------------------------------------------------
  1         | Shrimp Pasta | 1 cup tomato sauce | 1           | Pasta
  1         | Shrimp Pasta | 1 cup tomato sauce | 2           | Seafood
  1         | Shrimp Pasta | 1 cup tomato sauce | 3           | Shrimp
  2         | Fruit Cake   | 4 cups flour...    | 4           | Dessert
  2         | Fruit Cake   | 4 cups flour...    | 5           | Cakes
Without an ORM I have to loop through the result set to re-format the data the way I wanted before displaying it. An ORM takes care of that for me and gives me back 2 recipes with their categories accessible via recipe.categories.

4. Simplified manipulation of many-to-many relationships. Following the above example, if I want to add a new Category to a Recipe I can simply do:

  recipe.categories.add(category)
If I want to set the categories to something entirely different, I can do:

  recipe.categories = [category1, category2, category3, etc]
Without the ORM I would have to manually sync up the entries in the join table which is kind of a pain in the ass. Working with join tables in general is rather obnoxious, so I'm quite glad that the ORM takes care of that one for me.

5. Some ORMs give you notifications when an object (or collection of objects) changes. This is pretty important on the client side when you want to make sure the data you're displaying stays up to date, even as it is being manipulated. For example: if I'm viewing a recipe on my iPad and I update that recipe on my desktop. A background thread is running which keeps the two synchronized, and at some point the underlying recipe is updated in the database on my iPad.

If I'm working with raw SQL there's basically no way to know when that object is changed (short of polling it periodically, or rolling your own notification system). But my ORM will keep me notified of changes to the object so I can refresh the user interface with the updated recipe after the sync completes.

6. Some ORMs implement a unit of work that allows you to track what changes have been made to an object since it was retrieved from the database. So you can easily see which fields have been modified, and then when you go to save the object back out, it will intelligently only issue the SQL to update the columns which have changed, or won't even touch the database if nothing has actually changed.

7. Some ORMs put their objects into an identity map, so if you query for the same object under multiple different scenarios (e.g different areas of your UI), you always get the same underlying instance back. This means that you don't have multiple copies of what is semantically the same object floating around in different places of your app, and the object is always up to date with the latest changes.

Note: my use case is typically client-side database backed software, so features like (5), (6), and (7) save me from having to do a TON of work. If you're doing more web oriented stuff, I can see how those particular features may be less useful to you. Still, I think ORMs are a huge win overall.

Of course, none of this absolves you from needing to know what's going on at the database level. You still have to know what SQL your ORM is generating in order to make sure you're using it correctly. But I get really confused when people badmouth ORMs and try to tell me that it's simpler to use raw SQL, cause it never has been for me and my use cases. And the funniest thing is, if I stuck with raw SQL while attempting to solve all of the problems I listed above, I probably would end up with a half-assed version of a full-fledged ORM anyway.

(The only use case I can think of where I'd prefer to use raw SQL over an ORM is with report generation type activities: usually those types of queries aren't very dynamic, they can often be too complex to be expressed via the ORM's API, and once you have the data you're just dumping it to display without worrying about interactivity anyway.)

Post reply on HN