Tuesday, 7 December 2010

A New Flavour of ORM

Object-Reality Mapping

Despite the best efforts of many, the Object-Oriented vs. Relational Database "impedance mismatch" is still with us. Don't get me wrong; the aforementioned projects and specifications have done sterling work abstracting away tons of tedious, error-prone, boilerplate rubbish so that we can concentrate on our domain model.

But there lies the problem.

Far too often, domain models are so elaborate, so needlessly-baroque and overengineered that actually squeezing them down into two-dimensional database tables takes quite extraordinary levels of hackery. Now that the persistence-layer tools are so good, some developers are failing to stop and think "hang on, just because we can have a seven-level inheritance tree and persist it, doesn't mean we should".

Here's a trivially simple example. The good-old User class. Just about every webapp has one. Let's look at the (imagined) requirements:

  • A User should have a login name, real name, email address and (hashed and salted) password
  • There should be a special class of User called Admin who has greater power to mess upconfigure the system

At this point, 8/10 OO developers will get tremendously excited - they've spotted an actual situation where inheritance can be applied!. And we could even stick a Person on the top for people who aren't yet users!:


Gosh how exciting!

Except do we really need to model people who don't use the system? Will we ever? And is an Admin really a specialisation of a User? Isn't it actually a role that a user can play? We could persist that far more easily with a simple enumerated type. Or if we're really doing the simplest thing that can possibly work then couldn't we just have a boolean isAdmin flag?

Another example. Consider the classic Parent-Child relationship; let's use Course and Student as our concrete types. Traditional object modeling would have Course holding a collection of Student, with Student holding a reference back to Course. But now stop and think. If all this data is being persisted anyway, how often would we actually use that collection from Java-land? If we really need that information, it's a trivial DAO method away - the parent reference in the child maintains the referential integrity, so why use a bidirectional relationship?

With just a few small optimisations like those suggested above, a lot of the supposed "impedance" drops to zero. So the next time your square object model won't fit through the round RDBMS hole, cut a few corners!

No comments:

Post a Comment