ORMs and database access

These are some notes I created recently. Comments welcome…

Thinking about data storage:
Databases, ORMs, and separation of concerns


  1. ORMs are good — they help fix the disconnect between OOP and the database. But I don’t always like the way they work.
  2. Inheritance is very brute-force
    • What if you had to inherit from IO?
    • If you inherit from ActiveRecord::Base, you can’t inherit from anything else…
    • …unless you move the ActiveRecord inheritance to the top of the hierarchy, possibly even making descendants of classes that don’t need to be
    • ActiveRecord::Base adds 134 instance methods to your class
    • I also dislike AR’s lengthy method names and pathological use of method_missing
    • AR encourages higher-level thinking, but arguably not high enough
  3. I don’t like cluttering the model with database stuff
    • models should be object models, not database models
    • database logic distracts from the real object behavior
    • what if I want to change ORMs later?

A better way?

  1. Just as the ORM tries to hide the database, our code should try to hide the ORM
  2. Encapsulating behavior at a high level (abstracting) helps the situation
  3. I have played with AR and DataMapper and glanced at Ambition. My favorite so far is Sequel.
  4. But if I had time, I would develop yet another way. I once worked with Ezra Zygmuntowicz on “PassiveRecord” (not the one on github now), but we ran out of steam.
  5. Sub-digression: What’s the receiver?
    • Sometimes the receiver seems clear (but not always).
      dog.wag(tail) # not tail.wag(dog)
    • We do this:
      puts "Hello"; STDERR.puts "Something went wrong"
    • But we could have done this:
      "Hello".puts; "Something went wrong".puts(STDERR)
    • Marshal is consistent:
      str = Marshal.dump(obj); obj = Marshal.load(str)
    • YAML is not:
      str = obj.to_yaml; obj = YAML.load(str)
    • Note that YAML thus “pollutes” every object with (at least) a to_yaml method
    • To a much greater extent, ActiveRecord pollutes the object with class and instance methods
    • I do like saying obj.save, but I’m not sure it’s worth it
    • I think I’d rather say: db.save(obj)

Ideas and principles

  1. So some of my principles are:
    • Decouple the model from the ORM/database as much as possible
    • Add the fewest possible number of methods and attributes to the model’s class and instance
    • Centralize all information (including associations) in a kind of registry (data store)
    • As far as possible, hide even those details
  2. This blog post by Piotr Solnica is excellent:

  3. And also Avdi Grimm’s comments, “The trouble with ActiveRecord” at:

More ideas

  1. The Rails mantra “convention over configuration” is a good principle in general
  2. Let the table name default to the class name – forget plurals
  3. Append _id for the id and make it the primary key
  4. Let id be an alias for CLASS_id
  5. Let fields default to String type (the most common)
  6. Let xxx_id fields default to Integer (understood to be foreign keys)
  7. Unsure: Let xxx_at fields default to DateTime and be handled automatically
  8. Inheritance: Look up the child record by parent id
  9. Rubylike fields: Array, Hash, YAML, more? Non-queryable
  10. Concise notation for defining tables, associations
  11. has_one and belongs_to are not two associations, but one
  12. Determine inheritance structure through Ruby reflection
  13. After all metadata specified, discover relationships, add extra fields, and build tables

Leave a comment

No comments yet.

Comments RSS TrackBack Identifier URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s