Replacing O/R Mapping Framework: Is It Hard?

There are so many O/R mapping frameworks (O/R MF) on the market these days that it is quite hard to find the best one for your project. You can’t spent a life on selection, so a week on see/try/select process is all what you have. In most cases maybe it will be enough and you will find framework with required functionality with luck. However, sometimes this will be not the case.

You’ve made the selection and build the first release of your product. All works fine so far. Well, you’ve noticed some quirks with code generation and lack of important features like aggregations support, but you can live with it so far.

Then project starts to grow. More entities, more dependencies, more features. After a year you encounter really hard problems:

  • Performance on average data volumes is bad. And this is a killer problem that should be addressed ASAP.
  • Your O/R MF does not support inheritance, so reducing code duplications and work with general types is quite problematic
  • Code generation really lacks features, so you spending more and more time on tailoring it to feet your needs
  • Some annoying bugs like absence of TEXT column type support force you to dig into O/R MF code and fix them

Suddenly you start to think that O/R MF you’ve selected is a real pain in the neck and it should be definitely replaced with something faster and more reliable: “Why the hell we didn’t use old familiar DAO pattern? At least with DAO we are in charge of everything and with database Views and Denormalization Tables system performance will be sweet! And maybe we could generate all DAOs classes with help of Code Smith, why not?” This thought pop-ups every day while you are looking at SQL Profiler and trying to reduce SQL queries from 1000 to at least 100 for a single list. How to resolve this problem?

There are three possible solutions:

  1. Find new (a better one) O/R MF
  2. Implement DAO layer and replace your O/R MF with it
  3. Find a way to improve your O/R MF

And there are several critteria you should use to select the best solution:

  1. Minimal effort on application refactoring
  2. Acceptable performance
  3. Minimal maintenance effort
  4. Different databases support effort (if required)
  5. Development speed (how it will be affected)

Let’s try to evaluate all cases. Assume that application was designed without possible data layer change in mind. Let’s take a system with about 20 main entities and team of 3 developers. Each entity has at least 5 methods that use O/R MF (excluding simple CRUD operations), so about 100 of methods should be refactored. Controllers has references on O/R MF as well, since usually you have to initialize and pass UnitOfWork (Session or Context) into methods (about 3 controllers for each entity, so 90 in total). Estimates will be quite abstract anyway.

Criteria New O/R MF DAO Improving O/R MF
Application refactoring Effort Learn – 32hrs*3 = 100hrs
Code generation – 40hrs
All data layer methods refactoring – 100*0.5 = 50hrs
Changes in UI layer – 90*1 = 90hrs.

Total: 280hrs

Code generation – 120hrs
All data layer methods refactoring – 100*2 = 200hrs
Changes in UI layer – 90*1 = 90hrs.

Total: 410hrs

This is a tricky part. But in general improvements you want will be very time consuming. 2-3 man-month is a quite natural estimate. But risks are high anyway.

Total: 400hrs

Effort on Acceptable Performance Views for lists: DB views creation – 40hrs
New objects configuration – 20hrs
Controllers changes – 20hrs

Total: 80hrs

Views for lists: DB views creation – 40hrs
New objects configuration – 10hrs
Controllers changes – 20hrs

Total: 70hrs

Views for lists: DB views creation – 40hrs
New objects configuration – 20hrs
Controllers changes – 10hrs

Total: 70hrs

Maintenance effort Average Average Low
Different databases support effort 20hrs Code generation changes – 60hrs
Other – 20hrs

Total: 80hrs

20hrs
Development speed High. After learning period, all tasks will be easy to do Low. New DAO methods will require hand-written SQL queries and/or Views. High. Assuming all problems resolved during O/R MF improvements.
Total 380hrs
+ High development speed
– Hard performance optimization in complex cases
560hrs
– Low development speed
+ Better performance in complex cases
490hrs
+ High development speed
– High risk
– Hard performance optimization in complex cases

Some basic observations:

  • O/R MF replacement/refactoring is not a easy task and will be time consuming in any way
  • Refactoring existing O/R MF is a risky way (if it is not Open Source, this is completely impossible to do)
  • Any O/R MF reduces possible performance optimization ways

Conclusions:

  • Stick to DAO if application will work with large data volumes (1,000,000+ records). DAO is very flexible for high-end performance tuning, but you will need great DBA.
  • In most cases do not try to improve existing O/R MF, since risks are high and effort significant
  • Choose new O/R MF with care, based on all your experience and knows issues with existing one.

Next time I will write about more interesting topic: How to design application to support safe data layer replacement.