In Part I of "Architecture Dilemmas: O/R Mapping Why/When" I briefly explained what Object/Relational (O/R) Mapping is as well as presented some of the other options available for getting data from a relational database (RDBMS). In Part II, I examine some of the motivations to use O/R mapping and some of the costs and limitations O/R mappers.

The premise of O/R mapping is that you have a focused investment in creating the mapping and that you are free from worrying about the data structure.

This leads to quite a few benefits for using O/R mapping:

  • Clean OO design. Hiding the relational model specifics lets the object model be more cleanly analyzed and applied.
  • Productivity. Simpler code as the object model is free from persistence constraints. Developers can navigate object hierarchies, etc.
  • Separation of concerns and specialization. Let the DB people worry about DB structure and the Object people worry about their OO models.
  • Time savings. The O/R mapping layer saves you from writing the code to persist and retrieve objects. O/R mapping tool vendors claim 20-30% reduction in the code that needs to be written. Writing less code also means less testing.

One problem with O/R mappers is that they usually commit the "Needless Repetition" deadly sin (a.k.a. DRY?"Don't Repeat Yourself"). The table structure as well as their relations are stored both in the DB and in the mapping files used by the O/R mapper. This causes a maintenance problem as you need to ensure that both versions of the meta-data don't get out of sync. Rails (as in Ruby on Rails) partly solves this problem by relying on naming conventions. (Note: You can also override the default mapping.) In other environments, you can use code generation for the mapping file to get a similar effect. Both of these approaches result in limited mapping--which means you are likely to switch to manual mapping so you can benefit from the DB capabilities.

Which brings us to another problem with O/R mappers. Writing these mapping files is a daunting task (unless we are talking about trivial mappings) not to mention that O/R mappers tend to have favorite mappings (e.g., class = table or class hierarchy = table etc.) and trying other mapping are more complicated (if at all possible). This needs to be updated every time you change the DB.

One approach I've been taking recently is to isolate the DB structure from the DB side as well; that is, to add database views that expose the DB to the O/R mapper in simple-to-map structure. which means the mapping is simple and straightforward and the database is free to evolve and adapt as needed. For example, in one project we have set up "self-recording" where each update on the view resulting in an insert on the underlying table(s), while the view always reflects the latest version. Other views or queries can be used to go back in time to an earlier snapshot of the data. The downside of this approach is, of course, the double mapping layer (but at least O/R mapping is simple and relatively stable) hasn't been tested for high-data access load scenarios (as with the projects where it is used don't have such characteristics )

Then there are the queries, which is where a lot of O/R mappers stumble. You either get limited query capabilities or you get performance problems on complicated queries which means that you may need to resort to writing the queries manually (if your O/R mapper supports this)--which is what you were trying to avoid in the first place, not to mention that if your team is already familiar with DB techniques (SQL etc.) There's also the added overhead of learning that new query language. If you do feel comfortable with SQL and you want to take the middle ground you can use iBATis which lets you externalize the SQL into XML.

Note that you probably want to look at O/R mappers that support features like caches, lazy initialization , batch modes etc. to help avid the performance problems mentioned above.

On the next and final post on O/R Mapping I'll recommend when and when not to use O/R mapping.

Posted by Arnon Rotem-Gal-Oz at 06:32 PM  Permalink | Comments