Nov 17, 2008

Changes in Db4o configuration.....

Hi,

If you take a look in our svn repository you'll see that lots of changes were applied to configuration code (starting with version 7.7). Take it easy, we kept the "old" configuration interface in place; we just deprecated it, so update your code to use the new interfaces if you have the chance ;)

In this post I'd like to discuss some of these changes.

New, specific, factory classes


Do you remember Db4oFactory OpenFile(), OpenServer() and OpenClient() methods? We decided to move them to more specific factory classes:
  • Db4oClientServer
  • Db4oEmbedded
This way the boilerplate code used to open an embedded database changed from:

IObjectContainer db = Db4oFactory.OpenFile("MyData.odb");

to:

IObjectContainer db = Db4oEmbedded.OpenFile(Db4oEmbedded.NewConfiguration(), "MyData.odb");

As an additional benefit now we use the same class in both platforms (Java/.Net) (Remember, we used to have Db4o.openXXXX() for Java and  Db4oFactory.OpenXXX()for .Net).


Configuration interface split in File / Network / Common

We are applying Interface Segregation principle to configuration, so, now related configuration options are close together in specific interfaces.

For instance, all embedded related configuration lives in IEmbeddedConfiguration. But we didn't stopped there. We went a step further and broke common functionality in more coarse grained interfaces. For instance, there are configurations that do apply to both embedded and client server modes. So we introduced the concept of Configuration Providers which sole purpose is to help to aggregate configuration into specific interfaces, so it's easier (at least in our opinion :) to identify which configuration applies to each db4o mode and also make it more clear which aspect of db4o are being affected by that configuration.For instance:

IEmbeddedConfig config = Db4oEnbedded.NewConfiguration();
config.File.ReadOnly = true;

In this sample there's no space for doubts that ReadOnly configuration relates to a file system aspect of an embedded database.

That said, we basically partitioned configuration into four categories:
  • Embedded
  • Server
  • Client
  • Common

No more "default" configuration;

Suppose your application, at some point, requires a Db4o database with an activation depth configured to the highest possible value (in most scenarios this is not recommended) so you use some code like this:

IConfiguration globalConfig = Db4oFactory.Configure();
globalConfig.ActivationDepth(Int32.MaxValue);

using(IObjectContainer db = Db4oFactory.OpenFile("test.yap"))
{
/* Use the database */
}

So far, so good. Now, in a completely different point in your application you need to open another Db4o database and so you just type:

using(IObjectContainer anotherDb = Db4oFactory.OpenFile("test1.yap"))
{
/* Use the database */
}

This new database ends up configured to fully activate objects! Even knowing that you should avoid configuring activation depth this way (you did your homework, right?) it's possible to do it by accident.

The problem is that it is relatively easy to mess with configuration.

That's the reason that now, all OpenXXXX() methods (in the new factories) requires a configuration to be passed through!

We are considering reintroducing the original signature methods but with different semantics; instead of return a clone of the global configuration we can return a fresh configuration object populated with default values so developers can be sure about what configuration they get!

To wrap up the session on configuration I'd like to present a short "cheat sheet":

Emdedded Old
Db4oFactory.OpenFile("dbfile");
New
Db4oEmbedded.OpenFile(
   Db4oEmbedded.NewConfiguration(),
   "dbfile");
S
e
r
v
e
r
Old
Db4oFactory.OpenServer("dbfile", port);
New
Db4oClientServer.OpenServer(
 Db4oClientServer.NewServerConfiguration(),
 "dbfile",
 port);
C
l
i
e
n
t
Old
Db4oFactory.OpenClient(
       "dbfile", 
        port, 
        "user", 
        "pwd");
New
Db4oClientServer.OpenClient(
 Db4oClientServer.NewClientConfiguration(), 
        "dbfile", 
        port, 
        "user",
        "pwd")

ExceptionsOnNotStorable is turned on by default

That's (IMHO) really nice. I don't like to just pretend that classes are storable on Db4o and let customers struggling trying to figure out why their applications doesn't work when we could follow fail fast principles and let they know that one or more classes may have problems as it is.


Use of properties in .Net

That's mean more natural code style for .Net developers :). Now, instead of saying:

config.OutStream(Console.Out);

you will write:

config.OutStream = Console.Out;

We are aware that there other places where using properties instead of methods (or even using a different approach) would make more sense (on .Net of course) but we just don't have the time to improve them now. But you may be sure we'll do our best to keep improving both .Net/Java developers experience.


That's it!

See you.

No comments: