Additions to the list of db4o shortcomings

I had initially intended this to be a comment on Evan’s previous post, but as it grew longer I thought it’d be better served as an actual post.

After working with Evan on a db4o-based project for a while now, I too have some constructive criticism for db4o. Before I get to the criticism, though, I’d like to add that I really enjoy using db4o.

In contrast to db4o, we had initially tried ORM’s like NHibernate and SubSonic, but we always found ourselves back at the same spot… we weren’t actually getting anything done! We were either fighting with installing SQL Server (which, on one attempt blue-screened my computer and necessitated a full reinstall of Windows) or fighting with learning and/or configuring the ORM’s. Among other time sinks, we had to figure out a way to synchronize our SQL schema changes between me, Evan, our development server, and SVN. The story goes on and is exceedingly painful to add up all the hours of wasted time. It all boils down to one question: Why should you have to learn something completely unrelated to the domain of your project just to get things done!

The lustre of a purely object-oriented database is too strong to deny. Think about it: no more object/relational impedance mismatch! No more schema synchronization! No more battles over who’s ORM is the best! It is in these pillars of data-access where db4o shines. Db4o tries its hardest to get out of your way and let you get on with your work!

My following criticism about db4o should be taken constructively: in all honesty, I want to use db4o and forever do away with the other DB/ORM “solutions” out there. IMHO, db4o is all about getting things done, while the other solutions are all about picking the color of the bike shed.

1. db4o transactions

The transactional nature of db4o is not up to par with the offerings of NHibernate, ADO.NET, etc. I know this is like comparing apples to oranges, but I think it still holds that db4o’s transactions need a first-class presence.

2. “Real” lazy loading support

Without lazy loading, db4o forces you to choose a load-depth each time you run a query. If you don’t chose a load-depth then db4o uses a default value (5, I think). Either way, you must be aware of the consequences of choosing load-depth values.

If you choose a load-depth value that is too large, you will load more data than you’ll actually use which, in turn, negatively affects query performace. But, if you choose a load-depth value that is too small, you will not load enough data and db4o will leave any references to data beyond your load-depth value as null. Hopefully you are aware of this gotcha and have implemented null-checks throughout your data-access codebase.

Dealing with the load-depth problem forces the developer to be aware of intricate low-level details of their domain persistence, which no developer should ever be burdened with. Heck, isn’t this is why we’ve chosen to program in higher-level languages!

One of the most important reasons, if not the most important reason to do-away with load-depth, is that once you choose a value, you are tightly coupling your codebase to a magic number that you’ll need to remember to update whenever you change the structure of your domain.

If you choose not to tightly couple your code with load-depth values, you’ll use the default load depth. But with the risk of not loading enough data still present, you’ll still need to include null-checks. Though it is a simple stop-gap solution, using the default load-depth is definately not optimal. We need the ability to load the exactly amount of data that we’ll use: enter lazy loading.

Yes, I’ll admit that db4o currently offers a lazy loading solution, albeit a _very_ bad one at that! They’ve “implemented” lazy loading via a post-build process (yuck!). In my opinion, this doesn’t even constitute a viable option. If NHibernate can do lazy loading (via Castle’s DynamicProxy, or linfu) without requiring an added post-build process, so should db4o.

3. Built-in change tracking

This almost goes hand in hand with #2. Though Db4o makes saving a new object graph to the database very easy, updating data requires the developer be aware of details they shouldn’t be bothered with (hey, just like with load-depth!).

First, you have to make sure the object you are updating is loaded from db4o. You can’t just create a new instance of the object with the updated data and save it to the database: this will not have the effect of updating the original object, instead it will save a new object to the database! Granted, this requirement is understandable; but then again, it isn’t this requirement that I’ve got a beef with.

Now that you’ve made sure your object has been loaded from db4o before you begin updating it, you need to make sure that the object’s graph (i.e. references from your object to other objects) has been loaded to the correct load-depth; just because one of your object’s references is null doesn’t mean there isn’t an object referenced – it’s just that db4o might not have loaded it. If the object you’ve loaded from db4o has a null reference to an object which actually exists in the database but wasn’t loaded by db4o (due to shallow load-depth) and you replace that null reference with a new object, when you save your updated object (the one that was initially loaded from db4o) db4o will happily save the newly referenced object without complaint while silently leaving the previous instance untouched in the database. This creates what I like to call a “dangling object” because nothing points to it anymore! This problem is only worsened by the fact that you can’t (easily) load the database into a manager to look for these “dangling objects”.

With proper change tracking implemented, developers shouldn’t be bothered with keeping track of load-depths when updating an objects.

Final thoughts

Although I think db4o has some major shortcomings, I think it is a promising project. With these items addressed, I think db4o could be a major contender in the DB/ORM space.

This entry was posted in db4o and tagged , . Bookmark the permalink.

Leave a Reply